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.
51 lines
2.4 KiB
Go
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)
|
|
}
|
|
}
|
|
}
|