Build a merge's modules of a tier at once, and beside the check's tests where the judge cache allows (hq issue 716)
mesh/merge-gate head bbee20adf9b9 merged into trunk 622fb1e9cbac — pass: builds build-agent, mesh-controller → ace, g14, novox, shanks; no bus step; every …
mesh/repo-check head bbee20adf9b9 merged into trunk 622fb1e9cbac — pass: its merge-check.sh passed
mesh/delivery delivered

A check built its images one after another, after merge-check.sh. With a judge cache the
builds run during the tests, out of their reach; a failed check lets go of them.
This commit is contained in:
2026-10-14 20:20:49 +02:00
parent afed887217
commit bbee20adf9
4 changed files with 440 additions and 88 deletions
+36 -7
View File
@@ -15,6 +15,7 @@ import (
"regexp"
"sort"
"strings"
"sync"
"time"
"github.com/novox/mesh-controller/internal/artifacts"
@@ -300,7 +301,17 @@ func ScriptToolchain(script []byte) string {
// Check runs one merge check. An error is that it could not run; the verdict is then "error".
func Check(ctx context.Context, run Runner, spec CheckSpec, workspace, registry string, forge GitCredential,
log Log) (CheckVerdict, error) {
// Everything a check says goes to the build's log, which the bus keeps: said redacted (novox/hq issue 462).
// Everything a check says goes to the build's log, which the bus keeps: said redacted (novox/hq issue 462). A line
// at a time: its builds for the merge say theirs while its tests run (novox/hq issue 716).
if log != nil {
var saying sync.Mutex
inner := log
log = func(step, message string) {
saying.Lock()
defer saying.Unlock()
inner(step, message)
}
}
redact := redactorFor(forge)
say := logging(func(step, message string) {
if log != nil {
@@ -532,6 +543,25 @@ func Check(ctx context.Context, run Runner, spec CheckSpec, workspace, registry
// Every clone is made: the credential is gone before anything of the check runs (novox/hq issue 462).
forget()
// **What the merge moves is built beside the tests** (novox/hq issue 716) when the build agent has a judge cache to
// build it in, where no container of the check reaches; without one, after the check has judged.
logged := func(step, message string) {
if log != nil {
log(step, redact.redact(message))
}
}
var beside *besideTheTests
if buildingTree != "" {
place, err := buildsBesideTheTests(spec.JudgeCache, workspace, spec.ID)
if err != nil {
return CheckVerdict{}, err
}
if place != "" {
beside = startBesideTheTests(ctx, run, spec, place, buildingTree, judged, forge, logged, say)
defer beside.abandon()
}
}
// The facts, and the versions they say the mesh runs.
if registry == "" {
return CheckVerdict{}, errors.New("no artifact store to read the facts snapshot from")
@@ -752,12 +782,11 @@ func Check(ctx context.Context, run Runner, spec CheckSpec, workspace, registry
// **What the merge would move, built once, here** (novox/hq ADR 0350 §1): after the judging, from the merge it
// judged, into the scratch namespace — so the walk of the merge commit takes it rather than building again.
if len(spec.Builds) > 0 && spec.BuildWith != nil && len(spec.Group) == 0 {
v.Built = forTheMerge(ctx, run, spec, v, workspace, buildingTree, judged, forge, func(step, message string) {
if log != nil {
log(step, redact.redact(message))
}
}, say)
switch {
case beside != nil:
v.Built = beside.settle(ctx, v)
case len(spec.Builds) > 0 && spec.BuildWith != nil && len(spec.Group) == 0:
v.Built = forTheMerge(ctx, run, spec, v, workspace, buildingTree, judged, forge, logged, say)
}
return named(v), nil
}