From 98d494619f5a55f5049252a45396119f12b354a2 Mon Sep 17 00:00:00 2001 From: jochen Date: Sun, 11 Oct 2026 19:24:23 +0200 Subject: [PATCH] mesh-issues: take a delivery's id as mesh-delivery forms it, owner/repo@commit (hq issue 475) The delivery link's own pattern refused the slash and the @ every delivery id carries, so no delivery could be linked either. Mirror mesh-delivery's IDOf. --- modules/mesh-issues/cmd/mesh-issues/check.go | 8 +++-- .../cmd/mesh-issues/conditionkey_test.go | 36 +++++++++++++++++++ modules/mesh-issues/cmd/mesh-issues/main.go | 2 +- .../cmd/mesh-issues/tracker_test.go | 2 +- 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/modules/mesh-issues/cmd/mesh-issues/check.go b/modules/mesh-issues/cmd/mesh-issues/check.go index db590940..0b362672 100644 --- a/modules/mesh-issues/cmd/mesh-issues/check.go +++ b/modules/mesh-issues/cmd/mesh-issues/check.go @@ -222,7 +222,10 @@ var LinkKinds = []string{LinkDuplicates, LinkRelatesTo, LinkDependsOn, LinkPullR var ( pullRequest = regexp.MustCompile(`^[a-z0-9][a-z0-9._-]{0,99}#[1-9][0-9]{0,6}$`) decision = regexp.MustCompile(`^[0-9]{4}$`) - deliveryID = regexp.MustCompile(`^[A-Za-z0-9][A-Za-z0-9._:-]{0,99}$`) + // deliveryID mirrors mesh-delivery's `IDOf` (modules/mesh-delivery/cmd/mesh-delivery/model.go): the forge's + // repository as owner/name, lower-cased, `@` and at most twelve characters of its commit. The pattern this + // replaced took neither the slash nor the `@`, so no delivery could be linked (novox/hq issue 475). + deliveryID = regexp.MustCompile(`^[a-z0-9][a-z0-9._-]{0,99}/[a-z0-9][a-z0-9._-]{0,99}@[0-9a-f]{1,12}$`) issueNumber = regexp.MustCompile(`^[1-9][0-9]{0,8}$`) ) @@ -274,7 +277,8 @@ func checkTarget(kind, target string) (string, error) { ok, shape = isConditionKey(t), "a condition's key as the controller names it: .., "+ "the scope one of "+strings.Join(conditionScopes, ", ")+", each part of letters, digits and _=/-" case LinkDelivery: - ok, shape = deliveryID.MatchString(t), "a delivery's id as the controller names it" + ok, shape = deliveryID.MatchString(t), "a delivery's id as mesh-delivery names it: the repository as owner/name, @ and twelve "+ + "characters of its commit, such as novox/mesh-controller@d2e9dc61590f" default: return "", fmt.Errorf("kind %q is not a kind of link: one of %s", kind, strings.Join(LinkKinds, ", ")) } diff --git a/modules/mesh-issues/cmd/mesh-issues/conditionkey_test.go b/modules/mesh-issues/cmd/mesh-issues/conditionkey_test.go index 72bb7fd3..649abb4d 100644 --- a/modules/mesh-issues/cmd/mesh-issues/conditionkey_test.go +++ b/modules/mesh-issues/cmd/mesh-issues/conditionkey_test.go @@ -53,3 +53,39 @@ func TestAConditionLinkRefusesWhatTheControllerNeverRaises(t *testing.T) { } } } + +// A delivery link takes every id mesh-delivery gives (novox/hq issue 475): the ids are real, as +// `mesh-delivery.deliveries` answered on 2026-10-11. +var realDeliveryIDs = []string{ + "novox/mesh-controller@0f853e93fa11", + "novox/mesh-catalog@7714f164c33f", + "novox/hq@34bdb1a34f5a", + "novox/mesh-media-catalog@dd3f0abb3f78", + "novox/mesh-tools@82aefe1988c2", +} + +func TestADeliveryLinkTakesEveryIdMeshDeliveryGives(t *testing.T) { + h := newHarness(t) + n := h.open(t, "a delivery stalls", "mesh-catalog") + for _, id := range realDeliveryIDs { + if _, err := h.Link(LinkAsk{Number: n, Kind: LinkDelivery, Target: id}); err != nil { + t.Errorf("%s: %v", id, err) + } + } + for _, id := range []string{ + "", + "mesh-controller@0f853e93fa11", // no owner + "novox/mesh-controller", // no commit + "novox/mesh-controller@0f853e93fa11aa", // more than twelve characters of the commit + "Novox/Mesh-Controller@0f853e93fa11", // mesh-delivery lower-cases the repository + "novox/mesh-controller@0F853E93FA11", // a commit is lower-case hex + "novox/mesh-controller@main", // a branch, not a commit + "novox/mesh/controller@0f853e93fa11", // a repository is owner/name, no deeper + "novox/mesh-controller_d2e9dc61590f", // a condition key's form of it, not the id + "novox/mesh-controller@0f853e93fa11\nmore", // a second line + } { + if _, err := checkTarget(LinkDelivery, id); err == nil { + t.Errorf("%q was taken as a delivery's id", id) + } + } +} diff --git a/modules/mesh-issues/cmd/mesh-issues/main.go b/modules/mesh-issues/cmd/mesh-issues/main.go index 30e1353e..a98bef56 100644 --- a/modules/mesh-issues/cmd/mesh-issues/main.go +++ b/modules/mesh-issues/cmd/mesh-issues/main.go @@ -506,7 +506,7 @@ func Tools(t *Tracker) []stdio.Tool { Description: "Link an issue to something, or with remove, take a link away. Kinds: duplicates or relates-to " + "another issue (its number), pull-request (such as mesh-controller#246), decision (a decision record's " + "number, such as 0275), design (a design document's path), condition (a condition's key) and delivery " + - "(a delivery's id). Refused: a target not of its kind's shape, an issue that does not exist, a link it " + + "(a delivery's id, such as novox/mesh-controller@d2e9dc61590f). Refused: a target not of its kind's shape, an issue that does not exist, a link it " + "already has.", Input: schema([]string{"number", "kind", "target"}, map[string]any{ "number": number("the issue's number"), diff --git a/modules/mesh-issues/cmd/mesh-issues/tracker_test.go b/modules/mesh-issues/cmd/mesh-issues/tracker_test.go index 0528ffa7..1b0c8d15 100644 --- a/modules/mesh-issues/cmd/mesh-issues/tracker_test.go +++ b/modules/mesh-issues/cmd/mesh-issues/tracker_test.go @@ -474,7 +474,7 @@ func TestLinksAreTypedAddedOnceAndRemoved(t *testing.T) { {Kind: LinkDecision, Target: "0275"}, {Kind: LinkDesign, Target: "03-DESIGN/01-to-be/53-the-issue-tracker.md"}, {Kind: LinkCondition, Target: "mesh.hand-acts.backup.healer-wanted"}, - {Kind: LinkDelivery, Target: "d-2026-10-10.3"}, + {Kind: LinkDelivery, Target: "novox/mesh-controller@0f853e93fa11"}, } for _, l := range good { l.Number = a