diff --git a/modules/mesh-delivery-gate/cmd/mesh-delivery-gate/bus_test.go b/modules/mesh-delivery-gate/cmd/mesh-delivery-gate/bus_test.go index 377ac130..79e1c42f 100644 --- a/modules/mesh-delivery-gate/cmd/mesh-delivery-gate/bus_test.go +++ b/modules/mesh-delivery-gate/cmd/mesh-delivery-gate/bus_test.go @@ -584,6 +584,8 @@ func TestAPassingVerdictAsksTheApproveAndItsApproveMergesWithinSecondsOverARealB // The bridge says it merged; the mesh's source then holds the merge, in one write. b.forgeSays(t, sdk.Forge{Kind: sdk.ForgeMerged, Repository: "novox/app", Number: 7, Head: head, Merge: strings.Repeat("b", 40), Root: "r", Trees: map[string]string{"app": "t"}}) + // The forge's own word that the pull request merged follows the bridge's (its webhook): the delivery ends merged. + b.publish(t, "mesh.mod.gitea.event.pull.merged", merged("novox/app", 7, head, strings.Repeat("b", 40))) rt.until("source.main to hold the merge", eventWithin, func() bool { e, err := b.kvs["source"].Get(ctx, sdk.SourceMainKey) if err != nil { @@ -742,6 +744,7 @@ func TestAGroupOfTwoWithGreenChecksGetsOneAskAndOnItsApproveBothMergeOneAfterThe one := first.Pulls[0] b.forgeSays(t, sdk.Forge{Kind: sdk.ForgeMerged, Repository: one.Repository, Number: one.Number, Head: one.Head.Head, Merge: strings.Repeat("a", 40), Root: "r", Trees: map[string]string{"x": "t"}}) + b.publish(t, "mesh.mod.gitea.event.pull.merged", merged(one.Repository, one.Number, one.Head.Head, strings.Repeat("a", 40))) var both sdk.Merge rt.until("the second member to be handed", eventWithin, func() bool { both = mergeAt(b, "feat/x"); return len(both.Pulls) == 2 }) if both.Pulls[0].State != sdk.MergeMerged || both.Pulls[1].State != sdk.MergeMerging || both.Pulls[1].Repository == one.Repository { @@ -750,6 +753,7 @@ func TestAGroupOfTwoWithGreenChecksGetsOneAskAndOnItsApproveBothMergeOneAfterThe two := both.Pulls[1] b.forgeSays(t, sdk.Forge{Kind: sdk.ForgeMerged, Repository: two.Repository, Number: two.Number, Head: two.Head.Head, Merge: strings.Repeat("b", 40), Root: "r", Trees: map[string]string{"x": "t"}}) + b.publish(t, "mesh.mod.gitea.event.pull.merged", merged(two.Repository, two.Number, two.Head.Head, strings.Repeat("b", 40))) rt.until("source.main to hold both merges", eventWithin, func() bool { e, err := b.kvs["source"].Get(ctx, sdk.SourceMainKey) if err != nil { diff --git a/modules/mesh-delivery-gate/cmd/mesh-delivery-gate/catalogue_test.go b/modules/mesh-delivery-gate/cmd/mesh-delivery-gate/catalogue_test.go index fbc0e656..3f46a2fd 100644 --- a/modules/mesh-delivery-gate/cmd/mesh-delivery-gate/catalogue_test.go +++ b/modules/mesh-delivery-gate/cmd/mesh-delivery-gate/catalogue_test.go @@ -12,11 +12,10 @@ import ( // **The gate is the only claimant of the seat `mesh-delivery` in the catalogue** (novox/hq ADR 0437 §1, ADR 0449 §4, ADR 0454, // 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 -// reads or hears, but through the seat's name (`mesh-delivery` as a seat or a repository, `seat:mesh-delivery.`) and the -// 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{ - "mesh-delivery-gate": {"mesh-delivery.deliveries", "mesh-delivery.groups", "mesh-delivery.pulls"}, -} +// reads or hears, but through the seat's name (`mesh-delivery` as a seat or a repository, `seat:mesh-delivery.`). The +// three buckets the gate once carried over (ADR 0450 §6) went with the carry (ADR 0539 §17), and the event +// `mesh-delivery.transition` is heard by no one (issue 1406). +var oldModuleNames = map[string][]string{} // seatClaimants are the modules that claim the seat: the gate alone. var seatClaimants = []string{"mesh-delivery-gate"} diff --git a/modules/mesh-delivery-gate/cmd/mesh-delivery-gate/holder.go b/modules/mesh-delivery-gate/cmd/mesh-delivery-gate/holder.go index ac19da4d..6bc8f298 100644 --- a/modules/mesh-delivery-gate/cmd/mesh-delivery-gate/holder.go +++ b/modules/mesh-delivery-gate/cmd/mesh-delivery-gate/holder.go @@ -877,9 +877,6 @@ func (h *Holder) plan() []func() { return asks } -// askedCheck is whether a proposed delivery's own check stands asked: a kept ask with no id is none. -func askedCheck(d *Delivery) bool { return d.CheckAsk != nil && d.CheckAsk.ID != "" } - // askChecks reads the forge's open pull requests once for the proposed deliveries with no verdict (issue 1115), and takes the // checker's mesh/check where one stands on a head (issue 1302); the base's required statuses are kept. Nothing is asked of // the controller: the checker checks every head on every move (ADR 0447 §4, issue 1318). Under the lock; the read runs outside it. @@ -1088,9 +1085,3 @@ func containsString(xs []string, x string) bool { } return false } - -// refusedAfter is whether a member's merge, not yet merged, was refused by the merge tool in a try made at or after at. -func refusedAfter(d *Delivery, at time.Time) bool { - r := d.Ready - return r != nil && r.Merged == nil && d.MergedAs == "" && r.RefusedSince != nil && !r.LastTry.Before(at) -} diff --git a/modules/mesh-delivery-gate/cmd/mesh-delivery-gate/holder_test.go b/modules/mesh-delivery-gate/cmd/mesh-delivery-gate/holder_test.go index ef33cabf..49e8c2a0 100644 --- a/modules/mesh-delivery-gate/cmd/mesh-delivery-gate/holder_test.go +++ b/modules/mesh-delivery-gate/cmd/mesh-delivery-gate/holder_test.go @@ -359,14 +359,3 @@ func TestGroupsNamesEachMembersPullRequestHeadBaseAndOpen(t *testing.T) { } } } - -// composed are the asks of a group's composed check among the checks asked: a member's own check has no group before its colon. -func composed(checks []string) []string { - var out []string - for _, c := range checks { - if !strings.HasPrefix(c, ":") { - out = append(out, c) - } - } - return out -} diff --git a/modules/mesh-delivery-gate/cmd/mesh-delivery-gate/manifest_test.go b/modules/mesh-delivery-gate/cmd/mesh-delivery-gate/manifest_test.go index 2a23ea58..aea23e81 100644 --- a/modules/mesh-delivery-gate/cmd/mesh-delivery-gate/manifest_test.go +++ b/modules/mesh-delivery-gate/cmd/mesh-delivery-gate/manifest_test.go @@ -10,6 +10,8 @@ import ( "strings" "testing" "time" + + "git.novox.be/novox/mesh-sdk/go/catalogue" ) // The manifest says what the code does: the seat it claims and the verbs it serves, the events it follows @@ -202,3 +204,40 @@ func TestARowWrittenWithTheReadyMarkStillReads(t *testing.T) { t.Fatalf("the old row is not read: %+v", d.Ready) } } + +// R6-C3 (ADR 0539 §17): the gate holds the seat as the SDK's table of release 6 has it. Every verb of the table that is not +// optional is served; the verbs release 6 removed are optional rows the SDK answers by name, and the gate serves none of them; +// and the SDK's own test of whether a module can hold a seat (CanHold) finds nothing missing or unpromised. +func TestTheGateHoldsTheSeatAsTheSDKsTableOfRelease6HasIt(t *testing.T) { + _, raw := readManifest(t) + manifest, err := catalogue.ParseManifest([]byte(raw)) + if err != nil { + t.Fatalf("the SDK this module pins cannot read its manifest: %v", err) + } + seat, ok := catalogue.SeatNamed("mesh-delivery") + if !ok { + t.Fatal("the SDK this module pins names no seat mesh-delivery") + } + if err := catalogue.CanHold(manifest, seat); err != nil { + t.Fatalf("the gate cannot hold the seat of the SDK it pins: %v", err) + } + served := map[string]bool{} + for _, tool := range tools(&Holder{}, &listening{}) { + if _, verb, ok := strings.Cut(tool.Name, "."); ok { + served[verb] = true + } + } + for removed := range catalogue.RemovedDeliveryVerbs { + if served[removed] { + t.Errorf("the gate serves %s, which release 6 removed: the SDK answers it by name", removed) + } + if slices.Contains(manifest.Claims[0].Serves, removed) { + t.Errorf("the manifest serves %s, which release 6 removed", removed) + } + } + for _, verb := range []string{"deliveries", "show", "groups", "checks", "table", "stalled", "recheck", "close"} { + if !served[verb] { + t.Errorf("the gate does not serve %s, which the seat keeps", verb) + } + } +} diff --git a/modules/mesh-delivery-gate/go.mod b/modules/mesh-delivery-gate/go.mod index 6d836fc2..280f4735 100644 --- a/modules/mesh-delivery-gate/go.mod +++ b/modules/mesh-delivery-gate/go.mod @@ -3,7 +3,7 @@ module mesh-delivery-gate go 1.26.0 require ( - git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261022190740-104533e8c0c9 + git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261024143211-d506f2196a7c github.com/nats-io/nats-server/v2 v2.11.17 github.com/nats-io/nats.go v1.54.0 ) diff --git a/modules/mesh-delivery-gate/go.sum b/modules/mesh-delivery-gate/go.sum index db1ea18c..f67974cd 100644 --- a/modules/mesh-delivery-gate/go.sum +++ b/modules/mesh-delivery-gate/go.sum @@ -1,5 +1,5 @@ -git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261022190740-104533e8c0c9 h1:Ufmd2cYEXICQ817IGflccP9bexABE4WhIO49HPbaoSo= -git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261022190740-104533e8c0c9/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY= +git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261024143211-d506f2196a7c h1:WwOv9KGSaZh38Pbz2tGVXFMn5girjUZvjHG+8xYSY0o= +git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261024143211-d506f2196a7c/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY= github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op h1:Z/MZK75wC/NSrkgqeNIa7jexam9uWzhLmFTSCPI/kn0= github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op/go.mod h1:FQyySiasQQM8735Ddel3MRojmy4dA1IqCeyJ5jmPMbI= github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo=