package main // The shapes of what the module's steps end on in the steps state (novox/hq ADR 0487 ยง1, issue 1703e), kept as fixtures in // testdata/captured for the builder's tests (mesh-delivery-builder copies them): the stored step of a fetch, of a // candidate's build (no publish) and of a trunk build (publish). They are the step exactly as buildstep writes it to the // state, with what differs between runs (ids, times, the workspace, the commit, digests, the registry's address) put // to fixed words. This unit test regenerates them from the fake runner and compares (MESH_UPDATE_CAPTURED=1 rewrites // them); the integration test through the real bus (bus_integration_test.go) compares the steps the real bus holds with // the same files, so a change of shape fails in both places. import ( "encoding/json" "os" "path/filepath" "regexp" "strings" "testing" "time" "git.novox.be/novox/mesh-sdk/go/delivery" ) const capturedDir = "testdata/captured" var hexDigest = regexp.MustCompile(`sha256:[0-9a-f]{64}`) // normalized is a stored step with the words that differ between runs put to fixed ones. func normalized(t *testing.T, st delivery.Step, workspace, commit, registry string) []byte { t.Helper() raw, err := json.Marshal(st) if err != nil { t.Fatal(err) } var v map[string]any if err := json.Unmarshal(raw, &v); err != nil { t.Fatal(err) } v["id"] = "STEPID" if _, ok := v["owner"]; ok { v["owner"] = "OWNER" // the process that ran it (issue 1890), differs per run } v["started"], v["ended"] = "2026-10-22T08:00:00Z", "2026-10-22T08:00:01Z" out, _ := json.MarshalIndent(v, "", " ") s := string(out) for from, to := range map[string]string{workspace: "WORKSPACE", commit: "COMMIT", registry: "REGISTRY"} { if from != "" { s = strings.ReplaceAll(s, from, to) } } s = hexDigest.ReplaceAllString(s, imageDigest) // The result is stored as a JSON string of an object in some encodings: keep the file readable by decoding it once. var back map[string]any if err := json.Unmarshal([]byte(s), &back); err != nil { t.Fatal(err) } pretty, _ := json.MarshalIndent(back, "", " ") return append(pretty, '\n') } func compareCaptured(t *testing.T, name string, got []byte) { t.Helper() path := filepath.Join(capturedDir, name) if os.Getenv("MESH_UPDATE_CAPTURED") == "1" { if err := os.WriteFile(path, got, 0o644); err != nil { t.Fatal(err) } return } want, err := os.ReadFile(path) if err != nil { t.Fatalf("%s: %v (MESH_UPDATE_CAPTURED=1 writes it)", path, err) } if string(want) != string(got) { t.Errorf("%s differs from what the step ended on:\n--- want\n%s--- got\n%s", name, want, got) } } func workspaceOf(t *testing.T, st delivery.Step) string { var r struct { Workspace string `json:"workspace"` } json.Unmarshal(st.Result, &r) return r.Workspace } func TestTheStoredStepsHaveTheCapturedShapes(t *testing.T) { _ = time.Now // fetch { f := newFake(t) states := newStates() m := moduleWith(t, f, states) if _, err := tool(t, m, FetchTool)(map[string]any{"repository": "novox/mesh-catalog", "commit": commitSHA}); err != nil { t.Fatal(err) } st := states.waitEnd(t) compareCaptured(t, "fetch.json", normalized(t, st, workspaceOf(t, st), commitSHA, "")) } // a candidate's build and a trunk build for name, extra := range map[string]map[string]any{"build-candidate.json": nil, "build-trunk.json": {"publish": true}} { m, f, states := setup(t, same) _, st := runBuild(t, m, states, extra) compareCaptured(t, name, normalized(t, st, "", "", f.address())) } }