From 01f615aa0ad60fff783c4580ea8f3f84a6ff023b Mon Sep 17 00:00:00 2001 From: jochen Date: Thu, 22 Oct 2026 13:38:00 +0200 Subject: [PATCH] Read the bus release from the nats module's upstream artifact, so the tests' bus is still held to the mesh's once the Dockerfile is gone (issue 1640) mesh-catalog #434 runs the nats server as the upstream image named in module.json (ADR 0497) and deletes modules/nats/Dockerfile, so the check failed opening it. The manifest's upstream nats artifact is read first; the Dockerfile only for a catalogue from before the move (the captured copy). --- internal/testbus/testbus_test.go | 64 ++++++++++++++++++++++++++------ 1 file changed, 52 insertions(+), 12 deletions(-) diff --git a/internal/testbus/testbus_test.go b/internal/testbus/testbus_test.go index c851d459..b26ee64c 100644 --- a/internal/testbus/testbus_test.go +++ b/internal/testbus/testbus_test.go @@ -19,18 +19,10 @@ import ( // bus upgrade moves the catalogue's pin; this then fails in the merge check until the tests' pin moves // with it, so the controller is never tested against a bus the mesh no longer runs, or not yet. func TestTheBusTheTestsRunIsTheBusTheMeshRuns(t *testing.T) { - dockerfile := filepath.Join(beside.Catalogue(t), "nats", "Dockerfile") - raw, err := os.ReadFile(dockerfile) - if err != nil { - t.Fatal(err) - } - pinned := regexp.MustCompile(`upstream: nats ([0-9.]+)-alpine`).FindSubmatch(raw) - if pinned == nil { - t.Fatalf("%s says no release its digest is", dockerfile) - } - if string(pinned[1]) != Version { - t.Errorf("the tests run bus %s and the catalogue's bus image is %s: move go.mod's nats-server pin "+ - "(and `go mod vendor`) with the image", Version, pinned[1]) + release, from := catalogueBusRelease(t, filepath.Join(beside.Catalogue(t), "nats")) + if release != Version { + t.Errorf("the tests run bus %s and the catalogue's bus image is %s (%s): move go.mod's nats-server pin "+ + "(and `go mod vendor`) with the image", Version, release, from) } path := os.Getenv("MESH_FACTS") if path == "" { @@ -57,3 +49,51 @@ func TestTheBusTheTestsRunIsTheBusTheMeshRuns(t *testing.T) { } // A test's bus is its own: what one test makes, the next never sees. + +// catalogueBusRelease is the server release the catalogue's nats module runs, and where it was read. Since +// ADR 0497 the server is an upstream artifact in the module's manifest (`nats:-alpine@sha256:…`); +// before it, an image built from the module's Dockerfile, whose `upstream: nats -alpine` line said +// the release its digest is. The manifest is read first; the Dockerfile only where the manifest names no +// upstream nats image (a catalogue from before that move, such as the captured copy). Neither is a failure. +func catalogueBusRelease(t *testing.T, module string) (release, from string) { + t.Helper() + manifest := filepath.Join(module, "module.json") + raw, err := os.ReadFile(manifest) + if err != nil { + t.Fatal(err) + } + var m struct { + Build struct { + Artifacts []struct { + Name string `json:"name"` + Kind string `json:"kind"` + From string `json:"from"` + } `json:"artifacts"` + } `json:"build"` + } + if err := json.Unmarshal(raw, &m); err != nil { + t.Fatalf("%s: %v", manifest, err) + } + upstream := regexp.MustCompile(`^(?:[^/]+/)*nats:([0-9]+\.[0-9]+\.[0-9]+)-alpine(?:@sha256:[0-9a-f]{64})?$`) + for _, a := range m.Build.Artifacts { + if a.Kind != "upstream" || !strings.HasPrefix(a.From[strings.LastIndex(a.From, "/")+1:], "nats:") { + continue + } + pinned := upstream.FindStringSubmatch(a.From) + if pinned == nil { + t.Fatalf("%s: the upstream artifact %q is %q, which says no release in the form nats:-alpine", + manifest, a.Name, a.From) + } + return pinned[1], manifest + } + dockerfile := filepath.Join(module, "Dockerfile") + raw, err = os.ReadFile(dockerfile) + if err != nil { + t.Fatalf("%s names no upstream nats image, and the image built before it is not there either: %v", manifest, err) + } + pinned := regexp.MustCompile(`upstream: nats ([0-9.]+)-alpine`).FindSubmatch(raw) + if pinned == nil { + t.Fatalf("%s says no release its digest is", dockerfile) + } + return string(pinned[1]), dockerfile +}