Judge a pull request by the base branch's merge-check.sh, not its own copy
mesh/delivery superseded: a newer delivery to the same trunk took over its walk
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

A change could delete or gut its merge-check.sh and skip its own tests, and a
branch cut before the script escaped them. Where the base branch holds one, its
script, declared parts and toolchain run against the change's tree, and the
verdict says when the change lacks or alters the check (novox/hq issue 310).
This commit is contained in:
jochen
2026-10-08 10:58:19 +02:00
parent 1a50d6e5ab
commit cb0327de7f
4 changed files with 420 additions and 3 deletions
+24 -3
View File
@@ -43,7 +43,9 @@ import (
// <script>`, one line each, among the same first lines): each named script is run from the root in
// its own toolchain's container, after merge-check.sh, and the layer passes only when every part
// does (novox/hq issue 302 — the lab's Go replays went unchecked because its script runs in the
// TypeScript toolchain, which holds no Go compiler).
// TypeScript toolchain, which holds no Go compiler). **The script, its parts and its toolchain are
// the base branch's when it holds one** (novox/hq issue 310, check_base.go): a pull request cannot
// skip its own tests by deleting or weakening them, and one that alters them is said so.
//
// One check:
//
@@ -264,8 +266,16 @@ func Check(ctx context.Context, run Runner, spec CheckSpec, workspace, registry
return CheckVerdict{}, err
}
tree := filepath.Join(root, name)
script, scriptErr := os.ReadFile(filepath.Join(tree, CheckScript))
hasScript := scriptErr == nil
// **The base branch's check judges the change** (novox/hq issue 310), never the one the change brings.
judging, err := TheCheckThatJudges(ctx, tree, spec.Base)
if err != nil {
return CheckVerdict{}, err
}
script := judging.Script
hasScript := script != nil
if judging.Said != "" {
say("check", "%s", judging.Said)
}
gated := spec.Gated()
if !gated && !hasScript {
// Nothing to run: said, never passed silently.
@@ -447,12 +457,23 @@ func Check(ctx context.Context, run Runner, spec CheckSpec, workspace, registry
case timedOut():
v.Repo = &Layer{Verdict: "error", Summary: fmt.Sprintf("the check ran past %s before its %s ran", CheckTimeout, CheckScript)}
default:
// The base branch's scripts in place of the change's, in the change's tree — after the gate, which
// composes the change as it is.
if err := judging.Put(tree); err != nil {
return v, err
}
if judging.Said != "" {
fmt.Fprintf(&out, "--- %s\n", judging.Said)
}
v.Repo = ownCheck(ctx, spec, ScriptParts(script), tree, &out, timedOut, func(image string, script string) *exec.Cmd {
return exec.CommandContext(ctx, "docker", LabelledArgs("docker", in(image, tree, env, "sh", script), spec.ID)...)
}, say)
if v.Repo == nil {
return v, ctx.Err()
}
if judging.Said != "" {
v.Repo.Summary = judging.Said + "; " + v.Repo.Summary
}
}
v.Verdict, v.Summary = v.Gate.Verdict, v.Gate.Summary