feat(builder): research, build and a worker for the AI builder #6
No files matched your search
+11
-2
@@ -235,9 +235,18 @@ func bootCheck(gamesDir, id, agentImage string, wantOutside bool) (problems, ver
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
payload, err := exec.Command(self, "boottest-payload", "-games", gamesDir, id).Output()
|
payloadCmd := exec.Command(self, "boottest-payload", "-games", gamesDir, id)
|
||||||
|
var stderr bytes.Buffer
|
||||||
|
payloadCmd.Stderr = &stderr
|
||||||
|
payload, err := payloadCmd.Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("boottest-payload: %w", err)
|
var exitErr *exec.ExitError
|
||||||
|
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 []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, nil
|
||||||
|
}
|
||||||
|
return nil, nil, fmt.Errorf("boottest-payload: %v: %s", err, strings.TrimSpace(stderr.String()))
|
||||||
}
|
}
|
||||||
if out, err := runCmd("docker", "pull", "-q", agentImage); err != nil {
|
if out, err := runCmd("docker", "pull", "-q", agentImage); err != nil {
|
||||||
return nil, nil, fmt.Errorf("docker pull %s: %v: %s", agentImage, err, out)
|
return nil, nil, fmt.Errorf("docker pull %s: %v: %s", agentImage, err, out)
|
||||||
|
|||||||
@@ -270,6 +270,11 @@ func draftCompleteness(game, test map[string]any) []string {
|
|||||||
} else if v, _ := n.Int64(); v < 1024 {
|
} else if v, _ := n.Int64(); v < 1024 {
|
||||||
problems = append(problems, "requiredMemoryMb is below 1024")
|
problems = append(problems, "requiredMemoryMb is below 1024")
|
||||||
}
|
}
|
||||||
|
// Secrets only exist as CI settings a person adds; a draft with one can't be boot-tested anywhere
|
||||||
|
if secrets, _ := test["secrets"].(map[string]any); len(secrets) > 0 {
|
||||||
|
problems = append(problems, "test.yaml has 'secrets' ("+strings.Join(sortedKeys(secrets), ", ")+"), which no boot test of a "+
|
||||||
|
"new game has: remove them. Password settings get a throwaway value in boot tests automatically")
|
||||||
|
}
|
||||||
if _, ok := game["readyPattern"]; !ok {
|
if _, ok := game["readyPattern"]; !ok {
|
||||||
if _, ok := test["settleSec"]; !ok {
|
if _, ok := test["settleSec"]; !ok {
|
||||||
problems = append(problems, "no readyPattern and no test.settleSec: boot tests need one of them")
|
problems = append(problems, "no readyPattern and no test.settleSec: boot tests need one of them")
|
||||||
|
|||||||
@@ -84,3 +84,12 @@ func TestImageUnusable(t *testing.T) {
|
|||||||
t.Errorf("long run flagged: %q", why)
|
t.Errorf("long run flagged: %q", why)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDraftCompletenessRejectsSecrets(t *testing.T) {
|
||||||
|
// The Valheim draft that couldn't be boot-tested: the password mapped to a CI secret nobody created
|
||||||
|
test := map[string]any{"settleSec": json.Number("120"), "secrets": map[string]any{"Password": "VALHEIM_TEST_PASSWORD"}}
|
||||||
|
problems := strings.Join(draftCompleteness(map[string]any{}, test), "\n")
|
||||||
|
if !strings.Contains(problems, "test.yaml has 'secrets' (Password)") {
|
||||||
|
t.Errorf("got:\n%s", problems)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -168,7 +168,8 @@ func validateGame(dir, folder string, gameSchema, testSchema *jsonschema.Schema)
|
|||||||
add("test.yaml config.%s is not a key of this game", key)
|
add("test.yaml config.%s is not a key of this game", key)
|
||||||
}
|
}
|
||||||
if sensitiveKey.MatchString(key) {
|
if sensitiveKey.MatchString(key) {
|
||||||
add("test.yaml config.%s looks like a credential; map it under 'secrets' to a Gitea secret instead", key)
|
add("test.yaml config.%s looks like a credential; remove it (boot tests fill password settings with a throwaway "+
|
||||||
|
"value), or, only if the server can't start without a real one, map it under 'secrets' to a CI secret", key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, key := range sortedKeys(secrets) {
|
for _, key := range sortedKeys(secrets) {
|
||||||
|
|||||||
Reference in new issue
Block a user