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>
This commit is contained in:
gregandClaude Opus 5.5 committed 2026-10-24 17:49:19 -04:00
1 parent 5fb7736be2
commit e9ff989246
21 files changed
+585 -18

No files matched your search

+19
View File
@@ -94,6 +94,17 @@ func validateGame(dir, folder string, gameSchema, testSchema *jsonschema.Schema)
}
scanPrivateIPs(raw, "game.yaml", add)
// Go's regexp is a subset of Java's, which the node-agent uses; anything that compiles here works there
patterns, _ := g["failPatterns"].([]any)
if p, ok := g["readyPattern"].(string); ok {
patterns = append(patterns, p)
}
for _, p := range patterns {
if _, err := regexp.Compile(fmt.Sprint(p)); err != nil {
add("pattern %q does not compile: %v", p, err)
}
}
defaults, _ := g["defaultConfig"].(map[string]any)
props := schemaProperties(g)
known := map[string]bool{}
@@ -165,6 +176,14 @@ func validateGame(dir, folder string, gameSchema, testSchema *jsonschema.Schema)
add("test.yaml secrets.%s is not a key of this game", key)
}
}
if example, ok := t["readyExample"].(string); ok {
pattern, _ := g["readyPattern"].(string)
if re, err := regexp.Compile(pattern); pattern == "" || err != nil {
add("test.yaml has a readyExample but the game has no valid readyPattern")
} else if !re.MatchString(example) {
add("readyPattern %q does not match test.yaml readyExample %q", pattern, example)
}
}
return problems
}