feat(builder): every boot through the node-agent, every lost file counted, Steam cache
What a builder boot sees is now what a node does: - First boots (untouched, or -as-deployed with exactly a new server's settings) are deployed by the node-agent's BootTest in keep mode; the builder only watches the console and inspects what's left. The Go copy of the deploy (its own docker run, mounts and startup prefix) is gone. It had drifted: it gave the image's VOLUME folders their own volumes, which nodes don't, so saves there looked safe while every start loses them. - Files written outside /server and /data are counted whatever their type (it only counted config-like extensions, so .sav or .db saves went unseen), including the image's VOLUME folders; logs, pid and lock files and system folders are left out. - Boot tests ask the server to stay up holdSec (60 s, test.yaml can set it) after its ready line and to listen on every published container port (needs the node-agent's matching BootTest). - Steam apps are downloaded once per build into a gbr.cache volume and copied into each boot, so later boots only check the files (STEAM_CACHE=off). - RUNNER.md no longer suggests docker system prune, which deletes the gbr-boottest network when nothing is using it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
e07025f03d
commit
04967a8a16
10 files changed
+424
-171
No files matched your search
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
@@ -79,3 +80,29 @@ configSchema:
|
||||
t.Errorf("-fill-blank-passwords: ServerPassword not filled: %v", payload.GameConfig["ServerPassword"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestBootTestPayloadAsksForPublishedPortsAndHold(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
game := filepath.Join(dir, "example")
|
||||
os.MkdirAll(game, 0o755)
|
||||
os.WriteFile(filepath.Join(game, "game.yaml"), []byte("id: example\nname: Example\ndefaultDockerImage: x\ndefaultPorts:\n - 30000/udp\n - 30001:30001/tcp\n"), 0o644)
|
||||
os.WriteFile(filepath.Join(game, "test.yaml"), []byte("holdSec: 90\n"), 0o644)
|
||||
p, err := bootTestPayload(dir, "example", false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ports, _ := p["expectPorts"].([]any)
|
||||
if len(ports) != 2 || ports[0] != "30000/udp" || ports[1] != "30001:30001/tcp" {
|
||||
t.Errorf("expectPorts %v", p["expectPorts"])
|
||||
}
|
||||
if p["holdSec"] != 90 || p["settleSec"] != 120 {
|
||||
t.Errorf("hold %v settle %v", p["holdSec"], p["settleSec"])
|
||||
}
|
||||
|
||||
os.WriteFile(filepath.Join(game, "test.yaml"), []byte("secrets:\n OwnerId: EXAMPLE_OWNER\n"), 0o644)
|
||||
_, err = bootTestPayload(dir, "example", false)
|
||||
var missing *missingSecretError
|
||||
if !errors.As(err, &missing) || missing.secret != "EXAMPLE_OWNER" {
|
||||
t.Errorf("missing secret: %v", err)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user