Commit Graph
30 Commits
Author SHA1 Message Date
greg dd92b6be4c Merge pull request 'fix(worker): start with a repository-only token' (#12) from fix/worker-repo-scope-token into main
Builder image / publish (push) Successful in 22s
Validate game templates / validate (push) Successful in 24s
Validate game templates / boot-test (push) Skipped
Validate game templates / publish (push) Skipped
Reviewed-on: #12
2026-10-25 21:18:40 +00:00
gregandClaude Opus 5.5 0c868f7bac fix(worker): start with a repository-only token
Validate game templates / validate (push) Successful in 20s
Validate game templates / boot-test (push) Skipped
Validate game templates / publish (push) Skipped
The start-up check read the token's account with GET /user, which needs the
read:user scope. A token with only repository scope, which is all the worker
needs, got 403 and the worker exited in a restart loop. On 403 it now
names the commit author from BOT_NAME (default gbr-bot) and still checks
push access on the games repo.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 17:18:22 -04:00
greg 425c242ae7 Merge pull request 'fix(worker): commit as the token's account and check it can push' (#11) from fix/worker-bot-identity into main
Builder image / publish (push) Successful in 21s
Validate game templates / validate (push) Successful in 24s
Validate game templates / boot-test (push) Skipped
Validate game templates / publish (push) Skipped
Reviewed-on: #11
2026-10-25 21:07:49 +00:00
gregandClaude Opus 5.5 f3a2a1f099 fix(worker): commit as the token's account and check it can push
Validate game templates / validate (push) Successful in 21s
Validate game templates / boot-test (push) Skipped
Validate game templates / publish (push) Skipped
The worker committed as a hard-coded "gbr-bot", and a token without Write
access only showed up when a build finished and its push failed. On start it
now reads the token's account (GET /user) for the commit author, and
refuses to run if that account can't push to the games repo.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 16:28:54 -04:00
greg 929e7d68d0 Merge pull request 'feat(builder): research, build and a worker for the AI builder' (#6) from feat/builder-worker into main
Validate game templates / validate (push) Successful in 31s
Validate game templates / boot-test (push) Skipped
Validate game templates / publish (push) Skipped
Builder image / publish (push) Successful in 42s
Reviewed-on: #6
2026-10-25 20:22:45 +00:00
gregandClaude Opus 5.5 5dfc0cc794 fix(builder): drafts don't use CI secrets, and a missing one is fed back
Validate game templates / validate (push) Successful in 20s
Validate game templates / boot-test (push) Skipped
Validate game templates / publish (push) Skipped
The second Valheim build stopped before its boot test: told that
test.yaml's password "looks like a credential; map it under 'secrets'",
the model mapped it to a CI secret nobody created, and boottest-payload's
missing-secret exit ended the build.

- The validator now says to remove a test password first (boot tests fill
  password settings with a throwaway value); secrets only when the server
  can't start without a real one.
- Drafts with test.yaml 'secrets' fail the draft checks.
- build turns boottest-payload's missing-secret exit into feedback for the
  model instead of an error.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 15:52:18 -04:00
gregandClaude Opus 5.5 c2b22d3955 feat(draft): catch split text settings and owner-editable game ports
Validate game templates / validate (push) Successful in 19s
Validate game templates / boot-test (push) Skipped
Validate game templates / publish (push) Skipped
Two problems a draft can boot fine with but break once an owner changes a
setting, both in the builder's Valheim draft:

- splitSettings: text settings used unquoted on the command line, directly
  or through ARGS="-name ${SERVER_NAME}"; ./server $ARGS, so "GBRHosting -
  My Server" reaches the game as several arguments. Suggests quoting or a
  bash array.
- portSettings: game-port settings whose default isn't in defaultPorts, or
  that owners can change although nodes always publish the same container
  port. Internal ports (RCON, REST) and {PUBLIC_PORT_n} values are left out.

Both run on drafts only; AUTHORING.md gets the matching rules.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 15:43:27 -04:00
gregandClaude Opus 5.5 c75190d8c4 feat(builder): research, build and a worker for the AI builder
Validate game templates / validate (push) Successful in 19s
Validate game templates / boot-test (push) Skipped
Validate game templates / publish (push) Skipped
- research: searches SearXNG, reads the best pages through the reader, has the
  model list the server's variants, then checks every Docker image and Steam
  app it named for real before an admin sees it.
- build: first boot of the variant's images (skipping ones that need root),
  a draft by the model, then the draft deployed with the node-agent's
  BootTest like CI does; crashes, error lines and saves outside /server go
  back to the model, three boots at most.
- worker: polls the panel's builder queue (outbound only), runs research or
  build in a fresh clone, streams the output as the job log, and opens the
  result as a pull request from the bot account.
- Dockerfile.builder, a workflow publishing gbr-builder:latest, and
  BUILDER.md. Everything about where it runs comes from environment
  variables; deployment files live outside this public repo.

draft now keeps its conversation in a drafter, so build can send boot
failures back to the same model session. The boot-test runner comment no
longer names its VM.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 12:51:29 -04:00
greg 05bfc9b061 Merge pull request 'ci: stop waiting ~9 minutes on an unreachable cache' (#5) from ci/no-go-cache into main
Validate game templates / validate (push) Successful in 19s
Validate game templates / boot-test (push) Skipped
Validate game templates / publish (push) Skipped
2026-10-25 15:24:23 +00:00
greg e8216809d4 Merge branch 'main' into ci/no-go-cache
Validate game templates / validate (push) Successful in 19s
Validate game templates / boot-test (push) Skipped
Validate game templates / publish (push) Skipped
2026-10-25 15:20:41 +00:00
greg 07e8fd93f6 Merge pull request 'feat: draft new game templates with an AI model' (#4) from feat/ai-draft into main
Validate game templates / validate (push) Successful in 9m37s
Validate game templates / boot-test (push) Skipped
Validate game templates / publish (push) Skipped
2026-10-25 15:20:23 +00:00
gregandClaude Opus 5.5 d02ed01d26 ci: stop waiting ~9 minutes on an unreachable cache
Validate game templates / validate (push) Successful in 14s
Validate game templates / boot-test (push) Skipped
Validate game templates / publish (push) Skipped
Validate took ~10 minutes, of which ~10 seconds was work: setup-go's
cache restore and save each waited ~4.7 minutes for a connect timeout,
because the runners' built-in cache server sits on a network job
containers can't reach. Turn off setup-go caching (three small modules
aren't worth it) and the game-test runner's cache server, so any cache
step skips at once.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 11:12:55 -04:00
greg 43727f8284 Merge branch 'main' into feat/ai-draft
Validate game templates / validate (push) Successful in 9m41s
Validate game templates / boot-test (push) Skipped
Validate game templates / publish (push) Skipped
2026-10-25 15:10:22 +00:00
greg c23442e8fa Merge pull request 'fix(ark): retry the install; ready when advertising for join' (#3) from fix/ark-install-retry into main
Validate game templates / validate (push) Successful in 9m37s
Validate game templates / boot-test (push) Successful in 15m9s
Validate game templates / publish (push) Successful in 9m32s
2026-10-25 15:10:18 +00:00
greg ba09fe35d7 Merge branch 'main' into fix/ark-install-retry
Validate game templates / validate (push) Successful in 9m33s
Validate game templates / boot-test (push) Successful in 15m20s
Validate game templates / publish (push) Skipped
2026-10-25 07:09:33 +00:00
greg 8f4adb733e Merge branch 'main' into feat/ai-draft
Validate game templates / validate (push) Successful in 9m37s
Validate game templates / boot-test (push) Skipped
Validate game templates / publish (push) Skipped
2026-10-25 07:06:35 +00:00
greg a8394abe05 Merge pull request 'feat: inspect-image reads what a game's image needs' (#2) from feat/inspect-image into main
Validate game templates / validate (push) Successful in 9m33s
Validate game templates / boot-test (push) Skipped
Validate game templates / publish (push) Skipped
2026-10-25 07:06:11 +00:00
gregandClaude Opus 5.5 da4ffc86d2 feat: draft new game templates with an AI model
Validate game templates / validate (push) Successful in 9m35s
Validate game templates / boot-test (push) Skipped
Validate game templates / publish (push) Skipped
`gbrgames draft -name <game> -image <image> [-steam-app ID]
[-first-boot report.json]` has a model write games/<id>/game.yaml and
test.yaml, then checks them like any template and sends problems back
for up to three fix rounds. Ollama (default qwen3.8:27b, OLLAMA_URL) or
Gemini (GEMINI_API_KEY).

The model gets AUTHORING.md (new: the house rules, from how nodes really
run servers and today's bugs: x-generate passwords, no published RCON
ports, containerUser, heap below the limit, env var naming, ready lines),
the inspect-image facts, the first-boot report and the two smallest
templates as examples. With Ollama the answer is forced into the
template schema, tightened for drafts so ports, install config, settings
and their descriptions can't be left out or null.

On top of validation and the image checks, drafts must:
- be complete: player ports, >=3 settings each described, real memory,
  a readyPattern or settleSec
- name settings so they reach the container as variables the image reads
  (ServerPassword -> SERVER_PASSWORD when the image reads SERVER_PASS)
- not leave files first boot saw outside /server (lost on every start)
A first boot showing the image dies within seconds on permission errors
(it needs root) stops the draft before any model call. A missing
readyPattern is filled from first boot's verified suggestion.

Valheim, which we have no template for: lloesche/valheim-server was
rejected as root-only; via SteamCMD (app 896660) qwen3.8:27b on a local
3090 Ti wrote a passing template in two rounds (~1 min). It is about
70% there: it chose "--save-dir /server", which Valheim doesn't have
(-savedir), and missed -crossplay and 2457/udp. The save check is a text
check; booting the draft itself is the next step.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 03:01:22 -04:00
gregandClaude Opus 5.5 65cbb8cfd4 feat(ark): ready when advertising for join
Validate game templates / validate (push) Successful in 9m31s
Validate game templates / boot-test (push) Successful in 15m9s
Validate game templates / publish (push) Skipped
First boot with the install fix ran ARK for ~10 minutes and found, in
ShooterGame.log: "Server: ... has successfully started!", "EOS ownership
validation initialized: Success", "Full Startup: 36.26 seconds" and,
about two minutes later, "Server has completed startup and is now
advertising for join. (9.96GB Mem)". That last line is when players,
console players through EOS included, can join, so it is the
readyPattern; the real line is test.yaml's readyExample. Boot tests now
wait for it instead of only checking ARK stays up for 10 minutes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 02:35:52 -04:00
gregandClaude Opus 5.5 9fef27cd40 fix(ark): retry the server install before handing over to the image
The image's start_server runs SteamCMD once and carries on even when it
fails; SteamCMD's intermittent "Missing configuration" error then left
no server installed, so ARK exited and only the node's restart policy
saved it (a boot test would fail on the restart). First boot showed it.

The startup command now downloads SteamCMD if missing, runs the usual
"+login anonymous +quit" warm-up and installs app 2430930, retrying up
to three times until ArkAscendedServer.exe exists. start_server's own
install step then only validates.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 02:25:45 -04:00
gregandClaude Opus 5.5 c9d9cd6ff5 feat: first-boot records what a server does with no settings
Validate game templates / validate (push) Successful in 9m34s
Validate game templates / boot-test (push) Skipped
Validate game templates / publish (push) Skipped
`gbrgames first-boot -game <id>` (or -image for a game with no template)
starts the server once like the node-agent does (same volumes, user,
SteamCMD install and startup prefix) but with none of the template's
settings and no restart policy, in the isolated gbr-boottest network.
It watches the console until the server exits, goes quiet or hits -max,
stops it gracefully (many servers write their settings on shutdown) and
records:
- the console with timings, plus ready and error lines; the last strong
  ready line before the stop becomes a readyPattern / readyExample pair
- every file created; config files are copied out and parsed into
  settings with their defaults (INI, properties, JSON, YAML, Unreal
  OptionSettings=(...) lists); log files are scanned for ready lines too
- files written outside the volumes, which a recreated container loses

Minecraft: ready line `Done \([0-9.]+s\)! For help, type "help"` and 76
settings (69 from server.properties) found with no template input. ARK:
showed its image retries nothing when SteamCMD fails with "Missing
configuration" and starts a server that was never installed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 02:18:21 -04:00
gregandClaude Opus 5.5 40e7372dab feat: inspect-image reads what a game's image needs
Validate game templates / validate (push) Successful in 9m33s
Validate game templates / boot-test (push) Skipped
Validate game templates / publish (push) Skipped
`gbrgames inspect-image -game <id>` pulls the image and reads, without
starting the game (probe runs with --network none and bypasses the
entrypoint): its user, accounts, home folder owners and modes, tools
(java, steamcmd, proton...), startup scripts and the variables they read.

It then checks the template against those facts:
- an image built around its own user (a locked home owned by another uid,
  or a declared USER) needs a matching containerUser
- the startup command must read settings under the names the node gives
  them (the agent's toUpperSnakeCase), and must not read unset variables
  that have no default

On the template from the first commit it reports both ARK bugs found by
boot tests today (uid 25000; ${RCON_PORT} vs RCONPORT); the current five
templates pass. Boot tests now run it first, so such templates fail in
seconds instead of after a boot. -json prints the facts for tooling.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 01:42:55 -04:00
greg 309c667735 Merge pull request 'ci: publish templates to the control panel on main' (#1) from feat/publish-to-panel into main
Validate game templates / validate (push) Successful in 9m31s
Validate game templates / boot-test (push) Successful in 25m46s
Validate game templates / publish (push) Successful in 9m31s
2026-10-25 05:13:26 +00:00
gregandClaude Opus 5.5 b5b7712c87 ci: re-run push checks with the containerUser-capable agent
Validate game templates / validate (push) Successful in 9m32s
Validate game templates / boot-test (push) Successful in 25m47s
Validate game templates / publish (push) Skipped
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 00:11:47 -04:00
gregandClaude Opus 5.5 2ad445ffdd fix(ark): run as the image's own user; honour custom RCON ports
Validate game templates / validate (push) Successful in 9m32s
Validate game templates / boot-test (push) Failing after 11m8s
Validate game templates / publish (push) Skipped
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>
2026-10-24 22:17:03 -04:00
gregandClaude Opus 5.5 944b5fdd3e fix(boot-test): never overwrite non-password settings
Validate game templates / validate (push) Successful in 9m32s
Validate game templates / boot-test (push) Failing after 11m5s
Validate game templates / publish (push) Skipped
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>
2026-10-24 21:33:29 -04:00
gregandClaude Opus 5.5 e8edf853f7 fix(minecraft): 3G heap so the server fits its 4 GB minimum
Validate game templates / validate (push) Successful in 9m33s
Validate game templates / boot-test (push) Failing after 11m34s
Validate game templates / publish (push) Skipped
With MEMORY=4G and requiredMemoryMb 4096, Java's heap plus overhead
exceeded the container limit and the server was killed on start; the
boot test failed every time. With 3G it is ready in about 18s at 4 GB.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 20:36:24 -04:00
gregandClaude Opus 5.5 e9ff989246 ci: boot-test changed games before publishing
Validate game templates / validate (push) Successful in 9m32s
Validate game templates / publish (push) Canceled after 0s
Validate game templates / boot-test (push) Canceled after 5m15s
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>
2026-10-24 17:49:19 -04:00
gregandClaude Opus 5.5 5fb7736be2 ci: publish templates to the control panel on main
Validate game templates / validate (push) Successful in 9m31s
Adds `gbrgames export`, which builds the games_published payload from
every game.yaml, and a CI step that posts it to the panel webhook after
validation on main. Unlike the node-agent notify, a failed publish fails
the run so stale templates in the panel never go unnoticed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 17:12:50 -04:00
gregandClaude Opus 5.5 822b44e2e5 feat: game templates, schemas and validator
Validate game templates / validate (push) Successful in 10m6s
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>
2026-10-24 16:54:21 -04:00