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 (
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -103,3 +104,39 @@ func TestConfigCandidates(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestOutsideFilesCountsEverySaveButNotSystemOrTransientFiles(t *testing.T) {
|
||||
diff := `C /home
|
||||
C /home/steam
|
||||
A /home/steam/.config
|
||||
A /home/steam/.config/example
|
||||
A /home/steam/.config/example/worlds
|
||||
A /home/steam/.config/example/worlds/world1.db
|
||||
A /home/steam/.config/example/worlds/world1.fwl
|
||||
A /home/steam/.config/example/Player.log
|
||||
C /etc
|
||||
C /etc/hostname
|
||||
A /tmp/x.sock
|
||||
A /server/should-not-count.sav
|
||||
D /home/steam/old.txt
|
||||
A /home/steam/server.pid`
|
||||
got := outsideFiles(diff, map[string]string{"/server": "v", "/data": "v"})
|
||||
want := []string{"A /home/steam/.config/example/worlds/world1.db", "A /home/steam/.config/example/worlds/world1.fwl"}
|
||||
if strings.Join(got, "|") != strings.Join(want, "|") {
|
||||
t.Errorf("got %q\nwant %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUntouchedPayloadDeploysWithoutTemplateSettings(t *testing.T) {
|
||||
p := untouchedPayload(&bootSpec{Image: "example/image", Startup: "./server", SteamAppID: "1000000", MemoryMb: 4096,
|
||||
User: "1000:1000", Env: map[string]string{"EULA": "TRUE"}})
|
||||
if p["installMethod"] != "STEAMCMD" || p["installConfig"].(map[string]any)["appId"] != "1000000" || p["timeoutSec"] != 2400 {
|
||||
t.Errorf("steam install: %v", p)
|
||||
}
|
||||
if p["startupCommand"] != "./server" || p["dockerNetwork"] != bootTestNetwork || p["gameConfig"].(map[string]any)["EULA"] != "TRUE" {
|
||||
t.Errorf("payload: %v", p)
|
||||
}
|
||||
if _, ok := untouchedPayload(&bootSpec{Image: "x"})["startupCommand"]; ok {
|
||||
t.Error("no startup command means the image's own entrypoint")
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user