Files
mesh-controller/internal/testbus/testbus_test.go
T
jschoubben 01f615aa0a
mesh/check failed: unit: ..test: node:internal/modules/esm/resolve:241 | 01f615aa0ad6 on aa9da942606d | unit 3345 run, 0 kept, 7 skipped | integration…
mesh/repo-check head 01f615aa0ad6 merged into trunk aa9da942606d — pass: its merge-check.sh passed
mesh/merge-gate head 01f615aa0ad6 merged into trunk aa9da942606d — pass: group feat/r4d composed: every machine composes with the change as it did without …
mesh/delivery delivered
mesh/delivery-group group feat/r4d delivered: every member is delivered
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).
2026-10-22 13:38:00 +02:00

100 lines
3.8 KiB
Go

package testbus
import (
"os"
"path/filepath"
"regexp"
"strings"
"testing"
"encoding/json"
"github.com/novox/mesh-controller/internal/beside"
)
// **The bus the tests run is the bus the mesh runs** (novox/hq ADR 0227 rule 9, to-be 45 §9). The server
// linked into the tests is held to the release the catalogue's bus image is — the catalogue a merge check
// clones beside this one, or the copy captured in testdata/beside (internal/beside, novox/hq issue 432) —
// and, in a merge check that has the facts snapshot, to the release the mesh's bus server says it runs. A
// 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) {
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 == "" {
t.Logf("no MESH_FACTS: the bus the mesh runs is compared in a merge check, which has it")
return
}
body, err := os.ReadFile(path)
if err != nil {
t.Fatal(err)
}
// Read as little of the snapshot as this needs (internal/facts holds the whole shape).
var f struct {
Taken string `json:"taken"`
Versions struct {
Bus string `json:"bus"`
} `json:"versions"`
}
if err := json.Unmarshal(body, &f); err != nil {
t.Fatal(err)
}
if f.Versions.Bus != "" && strings.TrimPrefix(f.Versions.Bus, "v") != Version {
t.Errorf("the tests run bus %s and the mesh's bus runs %s (facts of %s)", Version, f.Versions.Bus, f.Taken)
}
}
// 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:<release>-alpine@sha256:…`);
// before it, an image built from the module's Dockerfile, whose `upstream: nats <release>-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:<x.y.z>-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
}