Files
gbr-games/RUNNER.md
T
gregandClaude Opus 5.5 6baf4796fa
Validate game templates / validate (push) Successful in 21s
Validate game templates / boot-test (push) Skipped
Validate game templates / publish (push) Skipped
feat(boot-test): CI boot tests use the Steam download cache, updated once a day
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>
2026-10-26 19:12:20 -04:00

3.0 KiB

Boot-test runner setup

Boot tests run on a dedicated Gitea Actions runner labelled game-test. It deploys each changed game with the node-agent's real deploy code, inside a Docker network that can reach the internet (Steam, Mojang, plugin downloads) but not private networks or the host. scripts/boot-test.sh refuses to run if that network is missing, so a half-configured runner can't boot servers on the LAN.

Everything here runs on the runner VM as root.

1. Isolated network

mkdir -p /opt/gbr-boottest
cp scripts/runner/setup-boottest-network.sh /opt/gbr-boottest/
chmod +x /opt/gbr-boottest/setup-boottest-network.sh
cp scripts/runner/gbr-boottest-network.service /etc/systemd/system/
systemctl daemon-reload
systemctl enable --now gbr-boottest-network

Check it from a throwaway container: the first command should print an IP, the second should time out.

docker run --rm --network gbr-boottest curlimages/curl -s --max-time 5 https://ifconfig.me
docker run --rm --network gbr-boottest curlimages/curl -s --max-time 5 http://192.168.1.1 || echo blocked

2. The runner

  1. In Gitea: gbreed-public → Settings → Actions → Runners → Create new runner, and copy the token.
  2. On the VM:
mkdir -p /opt/gitea-game-test-runner && cd /opt/gitea-game-test-runner
cp <repo>/scripts/runner/docker-compose.yml <repo>/scripts/runner/config.yaml .
echo "GITEA_RUNNER_REGISTRATION_TOKEN=<token>" > .env
docker compose up -d

The runner shows up as game-test in the org's runner list. It takes one job at a time; the build runner keeps handling everything else.

3. Secrets

Games whose test.yaml maps a value under secrets are skipped until that Actions secret exists in the org or repo, and the workflow passes it through (see the env: of the boot-test step).

Secret Game What
DRAGONWILDS_OWNER_ID RuneScape: Dragonwilds A Player ID; the server won't start without one

Housekeeping

Game images and SteamCMD downloads add up; each test removes its own container and volume. Clean up weekly (cron or a systemd timer) with:

docker container prune -f
docker image prune -af --filter "until=168h"
docker volume prune -af --filter "label!=gbr.cache"

Not docker system prune: it also deletes the gbr-boottest network whenever no container is using it, and boot tests then refuse to run until systemctl restart gbr-boottest-network.

Steam download cache

Boot tests of Steam games (installMethod: STEAMCMD) start from a cached install, one Docker volume per app (gbr-steamcache-<app id>, label gbr.cache=steam), the same cache the AI builder uses. The cache is updated at most once a day; the node-agent's own install then only checks the files and fetches what changed. So Steam isn't asked for the whole game on every run, which keeps traffic from this machine's address low. The prune above keeps these volumes. To drop one game's cache: docker volume rm gbr-steamcache-<app id>; STEAM_CACHE=off turns the cache off.