Run each part of a repository's own check in the toolchain it declares (hq issue 302)
mesh/merge-gate pass: builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step; every machine composes with the change as it…
mesh/repo-check pass: its merge-check.sh passed
mesh/delivery held for a person: merged, and the controller opened no walk for it within 10m0s — nothing it holds follows that branch, or the merge was…

mesh-lab's merge-check.sh runs in the TypeScript toolchain, which holds no Go
compiler, so its replays register was never compiled before a merge and a
broken one would have merged green. A script now declares a further part with
'# mesh-check-also: <toolchain> <script>'; the build seat runs it in that
toolchain's own container, and mesh/repo-check passes only when every part does.
This commit is contained in:
jochen
2026-10-08 00:09:30 +02:00
parent db953e7da8
commit 98ef7bac6e
2 changed files with 168 additions and 25 deletions
+73
View File
@@ -480,3 +480,76 @@ func TestARedeliveredCheckRemovesWhatItsEarlierDeliveryLeft(t *testing.T) {
t.Errorf("the check left %d container(s) behind", len(left))
}
}
// **A repository in two languages checks both, each in its own toolchain** (novox/hq issue 302): the lab's
// merge-check.sh runs in the TypeScript toolchain, and its Go replays were said "NOT CHECKED HERE" on every
// pull request, so a register that did not compile would have merged green. Its script declares the Go
// part; the check runs it in the Go toolchain's container after the script, and the layer passes only
// when both do.
func TestARepositoryInTwoLanguagesIsCheckedInBoth(t *testing.T) {
script := "#!/bin/sh\n# mesh-check-toolchain: typescript\n# mesh-check-also: go replays/merge-check.sh\nnpm test\n"
parts := ScriptParts([]byte(script))
if len(parts) != 2 || parts[0] != (ScriptPart{"typescript", CheckScript}) ||
parts[1] != (ScriptPart{"go", "replays/merge-check.sh"}) {
t.Fatalf("the parts read as %+v", parts)
}
if got := ScriptParts([]byte("#!/bin/sh\nset -eu\n")); len(got) != 1 || got[0] != (ScriptPart{"go", CheckScript}) {
t.Fatalf("a script declaring nothing reads as %+v", got)
}
// Each part run where its toolchain is: here, the image the part was given is what the command says.
held := CheckSpec{Toolchain: "go-image", Toolchains: map[string]string{"typescript": "ts-image", "go": "go-image"}}
run := func(t *testing.T, spec CheckSpec, files map[string]string, parts []ScriptPart) (*Layer, []string) {
t.Helper()
tree := t.TempDir()
for name, body := range files {
if err := os.MkdirAll(filepath.Dir(filepath.Join(tree, name)), 0o755); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(tree, name), []byte(body), 0o755); err != nil {
t.Fatal(err)
}
}
var images []string
var out tail
layer := ownCheck(t.Context(), spec, parts, tree, &out, func() bool { return false },
func(image, script string) *exec.Cmd {
images = append(images, image+" "+script)
cmd := exec.CommandContext(t.Context(), "sh", script)
cmd.Dir = tree
return cmd
}, func(string, string, ...any) {})
return layer, images
}
twoParts := []ScriptPart{{"typescript", CheckScript}, {"go", "replays/merge-check.sh"}}
layer, images := run(t, held, map[string]string{CheckScript: "exit 0\n", "replays/merge-check.sh": "exit 0\n"}, twoParts)
if layer.Verdict != "pass" || !strings.Contains(layer.Summary, "replays/merge-check.sh (go)") ||
strings.Join(images, ", ") != "ts-image merge-check.sh, go-image replays/merge-check.sh" {
t.Errorf("both parts passing answered %+v, ran %v", layer, images)
}
layer, _ = run(t, held, map[string]string{CheckScript: "exit 0\n",
"replays/merge-check.sh": "echo 'not gofmt'\"'\"'d:'; echo register.go; exit 1\n"}, twoParts)
if layer.Verdict != "fail" || !strings.Contains(layer.Summary, "replays/merge-check.sh failed") ||
!strings.Contains(layer.Summary, "register.go") || !strings.Contains(layer.Summary, "merge-check.sh (typescript) passed") {
t.Errorf("a failing Go part answered %+v", layer)
}
layer, images = run(t, held, map[string]string{CheckScript: "exit 2\n", "replays/merge-check.sh": "exit 0\n"}, twoParts)
if layer.Verdict != "fail" || len(images) != 1 {
t.Errorf("a failing first part answered %+v and ran %v", layer, images)
}
layer, _ = run(t, held, map[string]string{CheckScript: "exit 0\n"}, twoParts)
if layer.Verdict != "fail" || !strings.Contains(layer.Summary, "does not hold") {
t.Errorf("a declared part the repository lacks answered %+v", layer)
}
layer, _ = run(t, held, map[string]string{CheckScript: "exit 0\n"}, []ScriptPart{{"typescript", CheckScript},
{"go", "../elsewhere.sh"}})
if layer.Verdict != "fail" || !strings.Contains(layer.Summary, "not a path inside") {
t.Errorf("a part outside the repository answered %+v", layer)
}
layer, _ = run(t, CheckSpec{Toolchains: map[string]string{"typescript": "ts-image"}},
map[string]string{CheckScript: "exit 0\n", "replays/merge-check.sh": "exit 0\n"}, twoParts)
if layer.Verdict != "error" || !strings.Contains(layer.Summary, "go toolchain") {
t.Errorf("a part in a toolchain the mesh does not hold answered %+v — never a pass", layer)
}
}