fix(boot-test): run every boot test with exactly what a new server gets
Validate game templates / validate (push) Successful in 22s
Validate game templates / boot-test (push) Skipped
Validate game templates / publish (push) Skipped

CI's boot test gave every blank password-like setting a throwaway value. A
real deploy only fills x-generate fields, so a template whose server won't
start without one passed CI and failed for the first owner who deployed it.

boottest-payload now fills only x-generate fields, for CI and the builder
alike. The old behaviour is kept as -fill-blank-passwords, used only by
the builder's second boot to tell whether an empty setting is why a draft
fails. Messages and AUTHORING.md no longer say boot tests fill passwords;
a server that needs a join password gets x-generate.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
gregandClaude Opus 5.5 committed 2026-10-25 22:01:16 -04:00
1 parent 98ba043bec
commit fe790ad223
6 files changed
+35 -32

No files matched your search

+11 -11
View File
@@ -236,7 +236,7 @@ func bootCheck(gamesDir, id, agentImage string, wantOutside bool) (problems, ver
if out, err := runCmd("docker", "pull", "-q", agentImage); err != nil {
return nil, nil, fmt.Errorf("docker pull %s: %v: %s", agentImage, err, out)
}
output, passed, problems, err := agentBoot(gamesDir, id, agentImage, true)
output, passed, problems, err := agentBoot(gamesDir, id, agentImage, false)
if err != nil || problems != nil {
return problems, nil, err
}
@@ -246,7 +246,7 @@ func bootCheck(gamesDir, id, agentImage string, wantOutside bool) (problems, ver
if blank := blankRequiredLooking(gamesDir, id); len(blank) > 0 {
fmt.Printf("[build] it failed with the defaults; booting again with %s filled to see whether empty settings are the cause\n",
strings.Join(blank, ", "))
if _, filledPassed, _, err := agentBoot(gamesDir, id, agentImage, false); err == nil && filledPassed {
if _, filledPassed, _, err := agentBoot(gamesDir, id, agentImage, true); err == nil && filledPassed {
return []string{emptySettingsProblem(blank, bootVerdict(output))}, nil, nil
}
}
@@ -271,10 +271,10 @@ func bootCheck(gamesDir, id, agentImage string, wantOutside bool) (problems, ver
return nil, verified, nil
}
// agentBoot runs one boot test with the node-agent's BootTest: with the settings a new server gets
// (asDeployed), or with blank password-like settings filled with throwaway values as CI's boot test does.
// problems is set when the template can't be boot-tested at all.
func agentBoot(gamesDir, id, agentImage string, asDeployed bool) (output string, passed bool, problems []string, err error) {
// agentBoot runs one boot test with the node-agent's BootTest, with the settings a new server gets, like
// CI. fillBlank also fills blank password-like settings, only to find out whether they are why a draft
// fails. problems is set when the template can't be boot-tested at all.
func agentBoot(gamesDir, id, agentImage string, fillBlank bool) (output string, passed bool, problems []string, err error) {
self, err := os.Executable()
if err != nil {
return "", false, nil, err
@@ -284,8 +284,8 @@ func agentBoot(gamesDir, id, agentImage string, asDeployed bool) (output string,
runCmd("docker", "rm", "-f", "boottest-"+id)
runCmd("docker", "volume", "rm", "-f", "boottest-"+id+"-data")
args := []string{"boottest-payload", "-games", gamesDir, id}
if asDeployed {
args = []string{"boottest-payload", "-as-deployed", "-games", gamesDir, id}
if fillBlank {
args = []string{"boottest-payload", "-fill-blank-passwords", "-games", gamesDir, id}
}
payloadCmd := exec.Command(self, args...)
var stderr bytes.Buffer
@@ -296,7 +296,7 @@ func agentBoot(gamesDir, id, agentImage string, asDeployed bool) (output string,
if errors.As(err, &exitErr) && exitErr.ExitCode() == exitMissingSecret {
// The builder has no CI secrets: that's the template's problem to fix, not a reason to stop
return "", false, []string{"the boot test can't run: " + strings.TrimSpace(stderr.String()) + ". Remove 'secrets' from " +
"test.yaml; boot tests fill password settings with a throwaway value"}, nil
"test.yaml; boot tests run with exactly what a new server gets"}, nil
}
return "", false, nil, fmt.Errorf("boottest-payload: %v: %s", err, strings.TrimSpace(stderr.String()))
}
@@ -317,8 +317,8 @@ func agentBoot(gamesDir, id, agentImage string, asDeployed bool) (output string,
return out.String(), true, nil, nil
}
// blankRequiredLooking lists the settings a new server gets empty that CI's boot test would fill with a
// throwaway value: password-like keys with an empty default and no x-generate.
// blankRequiredLooking lists the settings a new server gets empty that look like a server might need a
// value: password-like keys with an empty default and no x-generate.
func blankRequiredLooking(gamesDir, id string) []string {
g, err := loadMap(filepath.Join(gamesDir, id, "game.yaml"))
if err != nil {