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 stopped: covered: its merge e7dca6c280bd is contained in cec797e996b2 which is delivered (walk plan-1791499975016484055); closed on the ope…
The delivery plan said a merge adding a module builds it, sent nowhere; the merge built nothing, so the module was never registered and assign refused it. The merge now asks for the build of every directory it adds, outside the plan, and the take-in registers it like a hand build.
95 lines
3.9 KiB
Go
95 lines
3.9 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/novox/mesh-controller/internal/catalogue"
|
|
"github.com/novox/mesh-controller/internal/inventory"
|
|
"github.com/novox/mesh-controller/internal/link"
|
|
)
|
|
|
|
// asksWithPaths records every build a merge asks for, as repository, path and ref.
|
|
func asksWithPaths(t *testing.T) *[][3]string {
|
|
t.Helper()
|
|
var asked [][3]string
|
|
was := askABuild
|
|
askABuild = func(_ context.Context, source buildSource, path, ref string) (string, error) {
|
|
asked = append(asked, [3]string{source.Repository, path, ref})
|
|
return "b-" + path, nil
|
|
}
|
|
t.Cleanup(func() { askABuild = was })
|
|
return &asked
|
|
}
|
|
|
|
// The live case of 2026-10-07 (novox/hq issue 300), replayed: a merge of the catalogue adds one module's
|
|
// directory and touches nothing else the mesh holds. Its delivery plan said "builds new: …, sent nowhere";
|
|
// the merge said it changed nothing any module the mesh holds is built from, and built nothing, so the
|
|
// module was never registered and `assign` refused it. The merge asks for its build, at the branch merged
|
|
// into, from the repository as the mesh spells it — and opens no plan, since nothing it holds moved.
|
|
func TestAMergeBuildsTheNewModuleItAdds(t *testing.T) {
|
|
open := aMesh(t)
|
|
ctx := t.Context()
|
|
inv := open.inventory
|
|
asked := asksWithPaths(t)
|
|
if err := inv.RegisterModule(ctx, catalogue.Manifest{Module: "networkmanager", Version: "1"},
|
|
inventory.Source{Repository: "novox/mesh-catalog", Seat: "git", Path: "modules/networkmanager", Ref: "main",
|
|
BuiltFrom: "c0", Head: "c0"}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
m := link.SourceMoved{Owner: "novox", Repo: "mesh-catalog", Base: "main", Commit: "3da80a4b00",
|
|
Paths: []string{"modules/systemd-resolved/module.json", "modules/systemd-resolved/cmd/main.go"},
|
|
ModuleDirs: []string{"modules/systemd-resolved"}, ModuleDirsSaid: true}
|
|
if err := (following{open: open}).SourceMoved(ctx, m); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
want := [3]string{"novox/mesh-catalog", "modules/systemd-resolved", "main"}
|
|
if len(*asked) != 1 || (*asked)[0] != want {
|
|
t.Fatalf("the merge adding modules/systemd-resolved asked for %v, not %v", *asked, want)
|
|
}
|
|
if plans, err := inv.OpenPlans(ctx); err != nil || len(plans) != 0 {
|
|
t.Fatalf("a merge moving nothing the mesh holds opened a plan: %+v %v", plans, err)
|
|
}
|
|
}
|
|
|
|
// A merge that changes a held module and adds a new one does both: the held one walks its plan, the new
|
|
// one is asked for beside it. A merge adding nothing builds nothing new.
|
|
func TestAMergeBuildsItsNewModuleBesideItsPlan(t *testing.T) {
|
|
open := aMesh(t)
|
|
ctx := t.Context()
|
|
inv := open.inventory
|
|
asked := asksWithPaths(t)
|
|
if err := inv.RegisterModule(ctx, catalogue.Manifest{Module: "app", Version: "1"},
|
|
inventory.Source{Repository: "novox/mesh-catalog", Seat: "git", Path: "modules/app", Ref: "main",
|
|
BuiltFrom: "c0", Head: "c0"}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
m := link.SourceMoved{Owner: "novox", Repo: "mesh-catalog", Base: "main", Commit: "c1aaaaaaaa",
|
|
Paths: []string{"modules/app/index.ts", "modules/fresh/module.json"},
|
|
ModuleDirs: []string{"modules/app", "modules/fresh"}, ModuleDirsSaid: true}
|
|
if err := (following{open: open}).SourceMoved(ctx, m); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
paths := map[string]bool{}
|
|
for _, a := range *asked {
|
|
paths[a[1]] = true
|
|
}
|
|
if !paths["modules/fresh"] || !paths["modules/app"] || len(*asked) != 2 {
|
|
t.Fatalf("asked %v; want the new module and the plan's first tier", *asked)
|
|
}
|
|
plans, err := inv.OpenPlans(ctx)
|
|
if err != nil || len(plans) != 1 || plans[0].Modules["fresh"] != nil || plans[0].Modules["app"] == nil {
|
|
t.Fatalf("the plan should walk app alone: %+v %v", plans, err)
|
|
}
|
|
|
|
*asked = nil
|
|
m2 := link.SourceMoved{Owner: "novox", Repo: "mesh-catalog", Base: "main", Commit: "c2aaaaaaaa",
|
|
Paths: []string{"README.md"}, ModuleDirsSaid: true}
|
|
if err := (following{open: open}).SourceMoved(ctx, m2); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(*asked) != 0 {
|
|
t.Fatalf("a merge adding no module asked for %v", *asked)
|
|
}
|
|
}
|