CI deployed every Steam game from scratch on each run, downloading the whole
game from Steam each time. scripts/boot-test.sh now runs the new
`gbrgames boot-test ID`, the builder's own deploy path: the same payload and
node-agent BootTest, but Steam games start from the cache volume
(gbr-steamcache-<app>, kept by RUNNER.md's prune).
The cache is updated at most once a day (a timestamp in the cache volume, not
copied into servers), so a repeat run within a day doesn't ask Steam for an
update at all; the node-agent's own install still checks the files and fetches
anything newer.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Some servers open a published port only once a player connects (through a
proxy, for example), so the boot test's port check can't see it after boot.
A template lists those ports as unboundPorts in its test.yaml, with the
reason. The first template that needs it lists one UDP port, until a real
client confirms how players reach it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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>
CI's boot test gave every blank password-like setting a throwaway value. A
real deploy only fills x-generate fields, so a template whose server won't
start without one passed CI and failed for the first owner who deployed it.
boottest-payload now fills only x-generate fields, for CI and the builder
alike. The old behaviour is kept as -fill-blank-passwords, used only by
the builder's second boot to tell whether an empty setting is why a draft
fails. Messages and AUTHORING.md no longer say boot tests fill passwords;
a server that needs a join password gets x-generate.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The builder's boot test filled every blank password-like setting with a
throwaway value. A real deploy only fills x-generate fields, so a draft whose
server refuses to run with an empty join password passed the builder and CI,
and then shut down on its first real deploy.
The builder now boots drafts with boottest-payload -as-deployed: only
x-generate fields are filled, everything else exactly as the template's
defaults. A server that won't run with its own defaults fails the build, and
the model is told that empty settings stay empty, so the value must come from
a default or x-generate. CI's boot test is unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The payload builder filled anything matching the validator's broad
credential pattern that wasn't a non-empty string, so RCON_PORT,
ENABLE_RCON and ARK's RCONEnabled/RCONPort became 'boot-123456' in the
first runner run. Only fill keys named like passwords (or x-generate),
and only when missing or an empty string. Adds a test.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>