A member's own merge gate sees a move through the core clones beside it (issue 1043)
mesh/merge-gate out of date: judged beside mesh-catalog#350 at c47d94925811, it is now at 795806efa7ad; judged again on a recheck or when it is merged
mesh/repo-check out of date: judged beside mesh-catalog#350 at c47d94925811, it is now at 795806efa7ad; judged again on a recheck or when it is merged
mesh/delivery-group group feat/whole-modules checking: composed check out of date: novox/mesh-controller@0125ccd7d200 was judged against trunk c43772fd94eb, th…
mesh/delivery superseded: a newer head of the same pull request

This commit is contained in:
2026-10-17 18:40:34 +02:00
parent fe5472bab4
commit 0125ccd7d2
2 changed files with 105 additions and 2 deletions
+79
View File
@@ -588,3 +588,82 @@ func TestTheGateRefusesAnArtifactContextNamingAnotherRepository(t *testing.T) {
}
}
}
// **A member of a delivery group judged alone sees a move** through the core clones beside its check
// (novox/hq ADR 0420 §6, issue 1043): the controller's own gate, with the catalogue beside having removed the
// module, is not refused for a second definition (issue 239); the catalogue's own gate, with the controller
// beside defining it, is not refused for a removal (ADR 0236). A clone beside at main finds no move.
func TestAMemberJudgedAloneSeesAMoveThroughTheClonesBeside(t *testing.T) {
const catalogueRepo, controllerRepo = "novox/mesh-catalog", "novox/mesh-controller"
raw := `{"module":"mover","version":"1"}`
sources := map[string]inventory.Source{"mover": {Repository: "http://forge.internal:20000/" + catalogueRepo + ".git",
Path: "modules/mover", BuiltFrom: "c0ffee"}}
// A tree is written into dir: defining mover, or holding only another module.
write := func(dir string, defines bool) string {
name, body := "other", `{"module":"other","version":"1"}`
if defines {
name, body = "mover", raw
}
if err := os.MkdirAll(filepath.Join(dir, "modules", name), 0o755); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(dir, "modules", name, "module.json"), []byte(body), 0o644); err != nil {
t.Fatal(err)
}
return dir
}
defining := func() string { return write(t.TempDir(), true) }
without := func() string { return write(t.TempDir(), false) }
// beside lays out a MESH_CHECK_BESIDE directory holding the named repositories' trees, each defining mover or not.
beside := func(trees map[string]bool) string {
root := t.TempDir()
for name, defines := range trees {
write(filepath.Join(root, name), defines)
}
return root
}
moves := func(repository, tree, besideRoot string) map[string]moveOfModule {
t.Helper()
got, err := movesOfChange(mergeCheckInput{repository: repository, tree: tree, beside: besideRoot}, sources)
if err != nil {
t.Fatal(err)
}
return got
}
// The controller's member: defines mover; the catalogue beside has removed it.
if got := moves(controllerRepo, defining(), beside(map[string]bool{"mesh-catalog": false})); got["mover"].To != controllerRepo {
t.Errorf("the controller's change defining mover, the catalogue beside without it: moves %v", got)
}
// The sources the gate then judges with: built from the controller, the definition is not a second one (issue 239);
// unmoved, it still is.
judge := func(at map[string]inventory.Source) []string {
t.Helper()
_, failures, err := shelfWithChange(map[string]catalogue.Manifest{}, at, snapshot.Facts{}, controllerRepo, defining(),
map[string]string{}, nil)
if err != nil {
t.Fatal(err)
}
return failures
}
mv := moves(controllerRepo, defining(), beside(map[string]bool{"mesh-catalog": false}))["mover"]
moved := map[string]inventory.Source{"mover": {Repository: mv.To, Path: mv.Dir, BuiltFrom: "c0ffee"}}
if f := judge(moved); len(f) != 0 {
t.Errorf("a definition of a module the catalogue beside removed was refused: %v", f)
}
if f := judge(sources); len(f) != 1 || !strings.Contains(f[0], "issue 239") {
t.Errorf("with the catalogue beside at main, the definition: %v, want the issue 239 refusal", f)
}
if got := moves(controllerRepo, defining(), beside(map[string]bool{"mesh-catalog": true})); len(got) != 0 {
t.Errorf("the catalogue beside at main still defines mover, yet moves %v", got)
}
// The catalogue's member: removes mover; the controller beside defines it.
if got := moves(catalogueRepo, without(), beside(map[string]bool{"mesh-controller": true})); got["mover"].To != controllerRepo {
t.Errorf("the catalogue's change removing mover, the controller beside defining it: moves %v", got)
}
if got := moves(catalogueRepo, without(), beside(map[string]bool{"mesh-controller": false})); len(got) != 0 {
t.Errorf("the controller beside at main does not define mover, yet moves %v", got)
}
if got := moves(catalogueRepo, without(), ""); len(got) != 0 {
t.Errorf("nothing beside, yet moves %v", got)
}
}