A check judged the head alone, so two pull requests that each passed could break the trunk together (node-engine #66 on 2026-10-09), and a recheck after the trunk moved judged the same head again. The build seat now merges the head into the trunk's head in its own clone, never pushed, fails a head that does not merge cleanly naming the files, and the verdict names the head, the trunk commit and the commits read beside it, for the forge and mesh-delivery to weigh against the trunk's next move (novox/hq ADR 0323, issue 341).
140 lines
5.6 KiB
Go
140 lines
5.6 KiB
Go
package builder
|
|
|
|
import (
|
|
"net"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// TestReplay341 is the replay of novox/hq issue 341, written with only what the build agent had before its fix,
|
|
// so mesh-lab's prover can lay it over the commit before. On 2026-10-09 node-engine #64/#65 merged at 00:15 and
|
|
// added Applied.Declared, under the JSON key `declared`, to the store record. #66, checked at 00:49 at its head,
|
|
// had added its own Applied.Declared under the same key on other lines. Its check passed; git merged the two
|
|
// edits without a conflict, and the trunk no longer compiled: "Declared redeclared". Before the fix the check
|
|
// judged the head alone and passed. After it (novox/hq ADR 0323), the check judges the head merged into the
|
|
// trunk commit that held the other field, and fails saying the trunk does not compile.
|
|
//
|
|
// It runs the check whole, with a container runtime that runs each container's command on this machine
|
|
// (aRuntimeOnThisMachine): the repository's own check is `go build ./...`.
|
|
func TestReplay341(t *testing.T) {
|
|
origin, head := theNinthOfOctober(t)
|
|
registry := aFactsRegistry(t)
|
|
aRuntimeOnThisMachine(t)
|
|
|
|
v, err := Check(t.Context(), Command, CheckSpec{ID: "replay-341", Repository: origin, Ref: head, Owner: "novox",
|
|
Repo: "mesh-host", Number: 66, Base: "main", Toolchain: "golang"}, t.TempDir(), registry, GitCredential{}, nil)
|
|
if err != nil {
|
|
t.Fatalf("the check could not run: %v", err)
|
|
}
|
|
if v.Repo == nil || v.Repo.Verdict != "fail" {
|
|
t.Fatalf("node-engine #66 at its head was answered %+v: the merge it makes into the trunk that holds #65's "+
|
|
"field does not compile, and the check let it merge", v.Repo)
|
|
}
|
|
if said := v.Repo.Summary + "\n" + v.Repo.Failed + "\n" + v.Report; !strings.Contains(said, "Declared redeclared") {
|
|
t.Fatalf("the check failed without saying the trunk does not compile:\n%s", said)
|
|
}
|
|
}
|
|
|
|
// theNinthOfOctober is the node-engine's repository as it stood at 00:49 on 2026-10-09, in miniature: a trunk
|
|
// holding #65's Applied.Declared (a string, key `declared`), and #66's head, branched before it, holding its own
|
|
// Applied.Declared (a *FoundUnit, the same key) on other lines. Each compiles alone; their merge does not.
|
|
func theNinthOfOctober(t *testing.T) (string, string) {
|
|
t.Helper()
|
|
origin := t.TempDir()
|
|
git := func(args ...string) string {
|
|
t.Helper()
|
|
cmd := exec.Command("git", args...)
|
|
cmd.Dir = origin
|
|
cmd.Env = append(os.Environ(), "GIT_AUTHOR_NAME=t", "GIT_AUTHOR_EMAIL=t@example.org",
|
|
"GIT_COMMITTER_NAME=t", "GIT_COMMITTER_EMAIL=t@example.org")
|
|
out, err := cmd.CombinedOutput()
|
|
if err != nil {
|
|
t.Fatalf("git %v: %v\n%s", args, err, out)
|
|
}
|
|
return strings.TrimSpace(string(out))
|
|
}
|
|
write := func(name, body string) {
|
|
t.Helper()
|
|
if err := os.MkdirAll(filepath.Dir(filepath.Join(origin, name)), 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(filepath.Join(origin, name), []byte(body), 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
store := func(declared65, declared66 string) string {
|
|
return "package store\n\n// FoundUnit is a unit found on the machine.\ntype FoundUnit struct{ Name string }\n\n" +
|
|
"// Applied is what the node-engine applied.\ntype Applied struct {\n\tGeneration int `json:\"generation\"`\n" +
|
|
declared66 + "\tModules []string `json:\"modules\"`\n\tFiles []string `json:\"files\"`\n" +
|
|
"\tUnits []string `json:\"units\"`\n\tAt string `json:\"at\"`\n" + declared65 + "}\n"
|
|
}
|
|
git("init", "--quiet", "-b", "main")
|
|
write("go.mod", "module example.org/mesh-host\n\ngo 1.21\n")
|
|
write("internal/store/store.go", store("", ""))
|
|
write(CheckScript, "# mesh-check-toolchain: go\nset -e\nGOFLAGS= GOWORK=off GOTOOLCHAIN=local GOPROXY=off go build ./...\n")
|
|
git("add", "-A")
|
|
git("commit", "--quiet", "-m", "#63: the store record")
|
|
git("checkout", "--quiet", "-b", "adr-0269")
|
|
write("internal/store/store.go", store("", "\tDeclared *FoundUnit `json:\"declared\"`\n"))
|
|
git("commit", "--quiet", "-am", "#66: the unit a declaration names")
|
|
head := git("rev-parse", "HEAD")
|
|
git("checkout", "--quiet", "main")
|
|
write("internal/store/store.go", store("\tDeclared string `json:\"declared\"`\n", ""))
|
|
git("commit", "--quiet", "-am", "#65: the declaration applied")
|
|
return origin, head
|
|
}
|
|
|
|
// aRuntimeOnThisMachine puts a container runtime on PATH that runs a container's command on this machine, in the
|
|
// directory and with the environment the check gives it: a store and a bus that answer, a judge that is never
|
|
// built, and the repository's own check run as written. Only for a check whose code is the test's own.
|
|
func aRuntimeOnThisMachine(t *testing.T) {
|
|
t.Helper()
|
|
bus, err := net.Listen("tcp", "127.0.0.1:0")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t.Cleanup(func() { bus.Close() })
|
|
go func() {
|
|
for {
|
|
c, err := bus.Accept()
|
|
if err != nil {
|
|
return
|
|
}
|
|
c.Close()
|
|
}
|
|
}()
|
|
dir := t.TempDir()
|
|
runtime := `#!/bin/sh
|
|
cmd="$1"; shift
|
|
case "$cmd" in
|
|
ps|rm|exec) exit 0 ;;
|
|
port) echo "` + bus.Addr().String() + `"; exit 0 ;;
|
|
run)
|
|
workdir=""; detached=""
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
-d) detached=1; shift ;;
|
|
--rm) shift ;;
|
|
--workdir) workdir="$2"; shift 2 ;;
|
|
--env) export "$2"; shift 2 ;;
|
|
--network|--volume|--user|--label|--name|-p|-e) shift 2 ;;
|
|
*) break ;;
|
|
esac
|
|
done
|
|
if [ -n "$detached" ]; then echo replay-container; exit 0; fi
|
|
shift
|
|
if [ "$1" = "sh" ] && [ -n "$workdir" ]; then cd "$workdir" && exec "$@"; fi
|
|
echo "no such image on this machine" >&2
|
|
exit 1 ;;
|
|
esac
|
|
exit 1
|
|
`
|
|
if err := os.WriteFile(filepath.Join(dir, "docker"), []byte(runtime), 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t.Setenv("PATH", dir+string(os.PathListSeparator)+os.Getenv("PATH"))
|
|
}
|