Merge pull request 'mesh-issues stops listening to the removed module's transition, which every controller merge check now refuses (issue 1406)' (#382) from fix/1406-drop-the-old-transition-name into main
This commit was merged in pull request #382.
This commit is contained in:
@@ -13,10 +13,9 @@ import (
|
|||||||
// issue 1351; how it is checked). Today's module `modules/mesh-delivery` was removed by a pull request of its own after the
|
// issue 1351; how it is checked). Today's module `modules/mesh-delivery` was removed by a pull request of its own after the
|
||||||
// handover, so the claimants are exactly one. And no manifest but the gate's and mesh-issues' names the old module in what it
|
// handover, so the claimants are exactly one. And no manifest but the gate's and mesh-issues' names the old module in what it
|
||||||
// reads or hears, but through the seat's name (`mesh-delivery` as a seat or a repository, `seat:mesh-delivery.<verb>`) and the
|
// reads or hears, but through the seat's name (`mesh-delivery` as a seat or a repository, `seat:mesh-delivery.<verb>`) and the
|
||||||
// names below: the three buckets the gate carries over (ADR 0450 §6) and the event the trackers hear (issue 1350).
|
// names below: the three buckets the gate carries over (ADR 0450 §6). The event `mesh-delivery.transition` is no longer heard by anyone (issue 1406).
|
||||||
var oldModuleNames = map[string][]string{
|
var oldModuleNames = map[string][]string{
|
||||||
"mesh-delivery-gate": {"mesh-delivery.deliveries", "mesh-delivery.groups", "mesh-delivery.pulls"},
|
"mesh-delivery-gate": {"mesh-delivery.deliveries", "mesh-delivery.groups", "mesh-delivery.pulls"},
|
||||||
"mesh-issues": {"mesh-delivery.transition"},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// seatClaimants are the modules that claim the seat: the gate alone.
|
// seatClaimants are the modules that claim the seat: the gate alone.
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import (
|
|||||||
// the forge's holder, asked through its tools). Owed, never lost: kept with the delivery before anything is
|
// the forge's holder, asked through its tools). Owed, never lost: kept with the delivery before anything is
|
||||||
// tried, and tried again until done.
|
// tried, and tried again until done.
|
||||||
|
|
||||||
// transitionEvent is what `mesh-delivery.transition` says: no secret, no address. opened is when its pull
|
// transitionEvent is what `mesh-delivery-gate.transition` says: no secret, no address. opened is when its pull
|
||||||
// request was first heard (zero when not known); with its class and its merge's moment it is what the issue
|
// request was first heard (zero when not known); with its class and its merge's moment it is what the issue
|
||||||
// tracker measures a fix's time by (novox/hq ADR 0313 §2, §4).
|
// tracker measures a fix's time by (novox/hq ADR 0313 §2, §4).
|
||||||
func transitionEvent(d *Delivery, t Transition, opened time.Time) map[string]any {
|
func transitionEvent(d *Delivery, t Transition, opened time.Time) map[string]any {
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ still read as that issue's verdict.
|
|||||||
|
|
||||||
**Ready.** An issue is ready when it is not resolved or wontfix and every issue it depends on is wontfix, or
|
**Ready.** An issue is ready when it is not resolved or wontfix and every issue it depends on is wontfix, or
|
||||||
resolved with every pull request its `fixed-by` names (`<repository>#<number>`) delivered. The module consumes
|
resolved with every pull request its `fixed-by` names (`<repository>#<number>`) delivered. The module consumes
|
||||||
`mesh-delivery.transition` and marks a pull request delivered on every issue naming it; at its own `moved` to
|
`mesh-delivery-gate.transition` and marks a pull request delivered on every issue naming it; at its own `moved` to
|
||||||
resolved it asks `seat:mesh-delivery.checks` once for what it has not heard. An issue made ready gains a note and
|
resolved it asks `seat:mesh-delivery.checks` once for what it has not heard. An issue made ready gains a note and
|
||||||
the event `ready`. `get` answers `waits-for`, `needed-by` and `ready`; `list` filters on `severity`, `needs` and
|
the event `ready`. `get` answers `waits-for`, `needed-by` and `ready`; `list` filters on `severity`, `needs` and
|
||||||
`ready` — an agent looking for work asks `severity=minor`, `needs=none`, `ready=true`. `set` changes severity,
|
`ready` — an agent looking for work asks `severity=minor`, `needs=none`, `ready=true`. `set` changes severity,
|
||||||
@@ -100,7 +100,7 @@ key-value state has no schema to migrate.
|
|||||||
|
|
||||||
## Whether the fix is delivered (hq ADR 0281)
|
## Whether the fix is delivered (hq ADR 0281)
|
||||||
|
|
||||||
For each pull request an issue's `fixed-by` names, the module keeps what `mesh-delivery.transition` last said —
|
For each pull request an issue's `fixed-by` names, the module keeps what `mesh-delivery-gate.transition` last said —
|
||||||
state, why, merged and when — or asks `seat:mesh-delivery.checks` once (at its own `moved`) for one it has not
|
state, why, merged and when — or asks `seat:mesh-delivery.checks` once (at its own `moved`) for one it has not
|
||||||
heard of. Nothing sets it by hand. `get` and every `list` row carry `delivery`, one line derived from it, worst
|
heard of. Nothing sets it by hand. `get` and every `list` row carry `delivery`, one line derived from it, worst
|
||||||
first: "fix not delivered: …", "held: …", "fix merged, not delivered: …", "fix not merged: …", "nothing heard from
|
first: "fix not delivered: …", "held: …", "fix merged, not delivered: …", "fix not merged: …", "nothing heard from
|
||||||
|
|||||||
@@ -46,10 +46,10 @@ func (n *notified) notify(key, severity, summary, headline, explanation, resolve
|
|||||||
|
|
||||||
func transition(t *testing.T, h *harness, number int, to, why, mergedAs string, at time.Time) {
|
func transition(t *testing.T, h *harness, number int, to, why, mergedAs string, at time.Time) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
transitionOn(t, h, "mesh-delivery.transition", number, to, why, mergedAs, at)
|
transitionOn(t, h, "mesh-delivery-gate.transition", number, to, why, mergedAs, at)
|
||||||
}
|
}
|
||||||
|
|
||||||
// transitionOn is a delivery's transition said under an event's name: today's module's, or the gate's.
|
// transitionOn is a delivery's transition said under an event's name.
|
||||||
func transitionOn(t *testing.T, h *harness, event string, number int, to, why, mergedAs string, at time.Time) {
|
func transitionOn(t *testing.T, h *harness, event string, number int, to, why, mergedAs string, at time.Time) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
raw, _ := json.Marshal(map[string]any{"repository": "novox/mesh-catalog", "number": number, "to": to, "why": why,
|
raw, _ := json.Marshal(map[string]any{"repository": "novox/mesh-catalog", "number": number, "to": to, "why": why,
|
||||||
@@ -340,8 +340,8 @@ func TestAResolvedIssueEndsItsStuckWarningAndIsNeverSaidStuck(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Issue 1350 AC1: the handler takes a transition under either name, today's module's or the gate's, and keeps the same fact.
|
// Issue 1350 AC1, issue 1406: the handler takes a transition under every name it hears (the gate's alone) and keeps the fact.
|
||||||
func TestATransitionIsTakenUnderEitherNameOfTheDeliverysOwner(t *testing.T) {
|
func TestATransitionIsTakenUnderEveryNameTheTrackerHears(t *testing.T) {
|
||||||
for _, event := range transitionEvents {
|
for _, event := range transitionEvents {
|
||||||
t.Run(event, func(t *testing.T) {
|
t.Run(event, func(t *testing.T) {
|
||||||
h := newHarness(t)
|
h := newHarness(t)
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ func (c *fixClock) delivery(t *testing.T, number int, to, class string, opened,
|
|||||||
body["opened"] = *opened
|
body["opened"] = *opened
|
||||||
}
|
}
|
||||||
raw, _ := json.Marshal(body)
|
raw, _ := json.Marshal(body)
|
||||||
if err := c.OnTransition(stdio.Envelope{Key: "mesh-delivery.transition", Body: raw}); err != nil {
|
if err := c.OnTransition(stdio.Envelope{Key: "mesh-delivery-gate.transition", Body: raw}); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -145,12 +145,12 @@ func start(t *Tracker) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// transitionEvents are the events a delivery's transitions are said under: today's module's, and the gate's that takes its place
|
// transitionEvents are the events a delivery's transitions are said under: the gate's (novox/hq ADR 0450 §8, issues 1350 and
|
||||||
// (novox/hq ADR 0450 §8, issue 1350). The old name stays until today's module is forgotten; the handler takes either.
|
// 1406). Today's module, which said mesh-delivery.transition, is forgotten.
|
||||||
var transitionEvents = []string{"mesh-delivery.transition", "mesh-delivery-gate.transition"}
|
var transitionEvents = []string{"mesh-delivery-gate.transition"}
|
||||||
|
|
||||||
// hearOpened subscribes the triage to the tracker's own `opened` and `moved` events and to mesh-delivery's
|
// hearOpened subscribes the triage to the tracker's own `opened` and `moved` events and to the gate's
|
||||||
// `transition`, and the gate's (ADR 0278 §1, ADR 0279 §3), each asked again until the runtime takes it: the runtime answers only
|
// `transition` (ADR 0278 §1, ADR 0279 §3), each asked again until the runtime takes it: the runtime answers only
|
||||||
// once Serve runs.
|
// once Serve runs.
|
||||||
func hearOpened(t *Tracker) {
|
func hearOpened(t *Tracker) {
|
||||||
type hearing struct {
|
type hearing struct {
|
||||||
|
|||||||
@@ -103,14 +103,14 @@ func TestItDeclaresAndHoldsTheIssueTrackerSeatOnceForTheMesh(t *testing.T) {
|
|||||||
d[3].Name != ReservationsState || d[3].History > 1 || d[3].TTLSeconds != 0 {
|
d[3].Name != ReservationsState || d[3].History > 1 || d[3].TTLSeconds != 0 {
|
||||||
t.Fatalf("state %+v", d)
|
t.Fatalf("state %+v", d)
|
||||||
}
|
}
|
||||||
// The delivery's transitions are heard from today's module and from the gate that takes its place (novox/hq ADR 0450 §8,
|
// The delivery's transitions are heard from the gate alone (novox/hq ADR 0450 §8, issues 1350 and 1406): today's module is
|
||||||
// issue 1350); the old name stays until today's module is forgotten. The subscriptions are the same list.
|
// forgotten, so nothing says mesh-delivery.transition. The subscriptions are the same list.
|
||||||
if !reflect.DeepEqual(transitionEvents, []string{"mesh-delivery.transition", "mesh-delivery-gate.transition"}) {
|
if !reflect.DeepEqual(transitionEvents, []string{"mesh-delivery-gate.transition"}) {
|
||||||
t.Fatalf("the triage subscribes to %v", transitionEvents)
|
t.Fatalf("the triage subscribes to %v", transitionEvents)
|
||||||
}
|
}
|
||||||
// The duplicate check hears the tracker's own opens and asks the agent module on its node (ADR 0278 §1, §5);
|
// The duplicate check hears the tracker's own opens and asks the agent module on its node (ADR 0278 §1, §5);
|
||||||
// the import and a reservation read the record through the records module (issue 424).
|
// the import and a reservation read the record through the records module (issue 424).
|
||||||
if !reflect.DeepEqual(m.Consumes, []string{"mesh-issues." + EventOpened, "mesh-issues." + EventMoved, "mesh-delivery.transition", "mesh-delivery-gate.transition"}) ||
|
if !reflect.DeepEqual(m.Consumes, []string{"mesh-issues." + EventOpened, "mesh-issues." + EventMoved, "mesh-delivery-gate.transition"}) ||
|
||||||
!reflect.DeepEqual(m.Invokes, []string{"claude-code.claude_code_judge", "seat:mesh-delivery.checks", "seat:operator-channel.notify",
|
!reflect.DeepEqual(m.Invokes, []string{"claude-code.claude_code_judge", "seat:mesh-delivery.checks", "seat:operator-channel.notify",
|
||||||
"gitea.gitea_pull_reviews", "records.records_status", "records.records_list", "records.records_read", "mesh-knowledge.knowledge_highest"}) {
|
"gitea.gitea_pull_reviews", "records.records_status", "records.records_list", "records.records_read", "mesh-knowledge.knowledge_highest"}) {
|
||||||
t.Fatalf("consumes %v, invokes %v", m.Consumes, m.Invokes)
|
t.Fatalf("consumes %v, invokes %v", m.Consumes, m.Invokes)
|
||||||
|
|||||||
@@ -472,7 +472,7 @@ func TestAnIssueIsReadyOnlyWhenWhatItDependsOnIsDelivered(t *testing.T) {
|
|||||||
if asked != 1 || ready(h, w) {
|
if asked != 1 || ready(h, w) {
|
||||||
t.Fatalf("ready before its fix is delivered (asked %d)", asked)
|
t.Fatalf("ready before its fix is delivered (asked %d)", asked)
|
||||||
}
|
}
|
||||||
tr := stdio.Envelope{Key: "mesh-delivery.transition", Body: json.RawMessage(`{"repository":"novox/mesh-catalog","number":9,"to":"delivered"}`)}
|
tr := stdio.Envelope{Key: "mesh-delivery-gate.transition", Body: json.RawMessage(`{"repository":"novox/mesh-catalog","number":9,"to":"delivered"}`)}
|
||||||
for i := 0; i < 2; i++ {
|
for i := 0; i < 2; i++ {
|
||||||
if err := h.OnTransition(tr); err != nil {
|
if err := h.OnTransition(tr); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|||||||
@@ -57,7 +57,6 @@
|
|||||||
"consumes": [
|
"consumes": [
|
||||||
"mesh-issues.opened",
|
"mesh-issues.opened",
|
||||||
"mesh-issues.moved",
|
"mesh-issues.moved",
|
||||||
"mesh-delivery.transition",
|
|
||||||
"mesh-delivery-gate.transition"
|
"mesh-delivery-gate.transition"
|
||||||
],
|
],
|
||||||
"invokes": [
|
"invokes": [
|
||||||
|
|||||||
Reference in New Issue
Block a user