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>
Launch options must be documented. A draft passed an option its server
doesn't have; servers ignore unknown options, so it booted and passed every
boot test while its setting did nothing. build now reads the pages research
based the variant on, in full, and the drafter rejects any launch option in
the startup command that none of them, nor the image's own scripts, mention.
Shell tools' options (mkdir -p, [ -n ...]) are skipped; the check is off
without sources.
The builder is game-agnostic:
- AUTHORING.md (the model's rules), the research prompt and the schema
describe the rules without naming a game.
- The draft prompt no longer includes real templates from the repo. Its
format example is one invented server (no real command, options, ports or
app id), checked by TestExampleTemplateFollowsTheRules.
- Comments, help texts, BUILDER.md and test fixtures use invented names and
values.
- TestBuilderIsGameAgnostic reads every game's name and id from games/ and
fails if any appears in the builder's code, tests, rules, schemas or docs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ARK's image is built around user gameserver (uid 25000) and locks
/home/gameserver to it, so under the node's default 1000:1000 the
startup script got "Permission denied" and the server restart-looped,
on real nodes as well as in boot tests. Set containerUser 25000:25000
(needs node-agent and panel support for containerUser).
The startup command read ${RCON_PORT}, but the node passes the RCONPort
setting as RCONPORT, so custom RCON ports were ignored for 27020.
Boot-tested in the Linux agent image: up 30 minutes with no restart.
The test now waits 10 minutes, covering the first ~13 GB download.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Only games whose folder changed are boot-tested (against the previous
main commit, or against main on branches; manual runs pick games). Each
one is deployed by the node-agent's real deploy code on a dedicated
game-test runner, in a network that can reach the internet but not the
LAN. Publishing to the panel runs only if they all booted.
- boottest-payload builds the DEPLOY_SERVER message the panel would send
- readyPattern/failPatterns in game.yaml; readyExample in test.yaml is
checked against the pattern during validation
- secrets in test.yaml come from CI; a game missing one is skipped
- Minecraft gets a ready pattern; Dragonwilds needs DRAGONWILDS_OWNER_ID
- RUNNER.md + scripts/runner: runner, isolated network, systemd unit
Also fixes newline values ("\n" separators/footers) that yaml.v3 wrote
as "" on import, which would have broken ARK and Dragonwilds config
files once synced, and adds a round-trip test for the importer.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Public game templates for GBR Hosting, one games/<id>/game.yaml per game,
imported from the panel. A Go tool validates them against JSON Schemas and
checks for credentials, private addresses and consents that default to
accepted; CI runs it on every push.
Admin/RCON passwords are no longer shared defaults: they are blank with
x-generate so the panel creates one per server, and Palworld/ARK no longer
publish their RCON/REST ports.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>