Files
mesh-controller/cmd/mesh-controller/replay309_test.go
T
jochen c5a2edf04a
mesh/delivery delivered
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
Resolve a group's order rules by precedence, not as a cycle (hq issue 309)
The group feat/a-machine-joins-through-the-tunnel was refused: the
controller's member moved the build agent, which builds the node-engine
(built by: controller first), and the node-engine goes before the
controller (engine before controller: engine first). Both rules applied
to one pair in opposite directions, and every two-way pair was a cycle.

Rules now have a precedence (hq ADR 0249): a declared after: line, then
what the graph and the change say (built by, version skew), then the
rollout default engine-before-controller. The higher rule decides the
pair, which says what it won over. Rules of one rank both ways are still
refused, as a contradiction naming both rules and how to declare the
order. TestReplay309 replays the group with only what orderOf had before.
2026-10-08 10:43:42 +02:00

51 lines
2.4 KiB
Go

package main
import (
"reflect"
"testing"
"github.com/novox/mesh-controller/internal/inventory"
)
// novox/hq issue 309, replayed with only what orderOf had before its fix, so it can be laid over the older
// commit. The group `feat/a-machine-joins-through-the-tunnel` (2026-10-08): the controller's pull request
// moved the controller and the build agent, the node-engine's moved the node-engine, the lab's moved
// nothing. The build agent builds the node-engine (built by: the controller's member first), and the
// node-engine goes before the controller (engine before controller: the node-engine's member first). Both
// rules applied to one pair in opposite directions, and the group was rejected as a cycle; the person merged
// the controller first by hand. A rule read from the graph outranks the rollout default, so the group is
// ordered, the controller's member first.
func TestReplay309(t *testing.T) {
members := []orderMember{
{ID: "novox/mesh-controller@8bbfdb53db2b", Repository: "novox/mesh-controller", Number: 132},
{ID: "novox/mesh-host@86cbebd10f8a", Repository: "novox/mesh-host", Number: 52},
{ID: "novox/mesh-lab@e80a4b1642bf", Repository: "novox/mesh-lab", Number: 61},
}
reach := map[string]orderReach{
"novox/mesh-controller@8bbfdb53db2b": {Moved: []string{"build-agent", "mesh-controller", "route-proxy"},
Manifests: []string{"module.json"}},
"novox/mesh-host@86cbebd10f8a": {Moved: []string{"mesh-host"}},
"novox/mesh-lab@e80a4b1642bf": {},
}
// Every source-built module is built by the build seat's holder; the holder follows the controller.
edges := []inventory.Edge{
{From: "build-agent", To: "mesh-controller", Kind: inventory.EdgeWorkerOf},
{From: "mesh-controller", To: "build-agent", Kind: inventory.EdgeBuiltBy},
{From: "mesh-host", To: "build-agent", Kind: inventory.EdgeBuiltBy},
{From: "route-proxy", To: "build-agent", Kind: inventory.EdgeBuiltBy},
}
got := orderOf(members, reach, edges)
if len(got.Cycle) > 0 {
t.Fatalf("the group is refused as a cycle %v; pairs %+v", got.Cycle, got.Pairs)
}
want := []string{"novox/mesh-controller@8bbfdb53db2b", "novox/mesh-host@86cbebd10f8a", "novox/mesh-lab@e80a4b1642bf"}
if !reflect.DeepEqual(got.Order, want) {
t.Fatalf("ordered %v, wanted %v; pairs %+v", got.Order, want, got.Pairs)
}
for _, p := range got.Pairs {
if p.Before == want[1] && p.After == want[0] {
t.Fatalf("a pair that lost still stands: %+v", p)
}
}
}