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>
49 lines
1.4 KiB
Go
49 lines
1.4 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
"reflect"
|
|
"testing"
|
|
)
|
|
|
|
// Whatever the panel exports must come back unchanged after import and export.
|
|
func TestImportRoundTrip(t *testing.T) {
|
|
game := map[string]any{
|
|
"id": "round-trip", "name": "Round Trip", "defaultDockerImage": "debian:12", "installMethod": "NONE",
|
|
"defaultStartupCommand": "./start.sh -log",
|
|
"requiredMemoryMb": float64(4096),
|
|
"configFormatOptions": map[string]any{
|
|
"separator": "\n", "footer": "\n", "header": "[Section]\n", "assignment": "=", "space": " ",
|
|
"multi": "[A]\nOptionSettings=(", "quoteStrings": true,
|
|
},
|
|
"installConfig": map[string]any{"script": "#!/bin/bash\nset -e\necho hi\n"},
|
|
"defaultConfig": map[string]any{"Rate": "1.000000", "Port": float64(7777), "Empty": "", "Ratio": 0.5},
|
|
}
|
|
|
|
dir := t.TempDir()
|
|
path := filepath.Join(dir, "game.yaml")
|
|
if err := writeGame(path, game); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
raw, err := os.ReadFile(path)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
loaded, err := loadYAML(raw)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// Compare as JSON, the way the panel receives it
|
|
var got, want any
|
|
gotJSON, _ := json.Marshal(loaded)
|
|
wantJSON, _ := json.Marshal(game)
|
|
json.Unmarshal(gotJSON, &got)
|
|
json.Unmarshal(wantJSON, &want)
|
|
if !reflect.DeepEqual(got, want) {
|
|
t.Fatalf("round trip changed the template\n got: %s\nwant: %s\nyaml:\n%s", gotJSON, wantJSON, raw)
|
|
}
|
|
}
|