The run rebuilds the module runtimes its beds stock

A per-module bed stocks mesh-runtime-<module>:development from the workstation's
image store, built by hand by a script the suite never called; six were two weeks
older than the manifests they served. For the beds named, every runtime their
scenarios stock is compared against the module's source and the tool runtime and
SDK it is built on, and rebuilt where older, missing or uncommitted; a failed
build stops the suite (novox/hq 04-ISSUES/075).
This commit is contained in:
2026-09-21 19:26:59 +02:00
parent be58bd96f6
commit d7959001dd
5 changed files with 252 additions and 8 deletions
+88
View File
@@ -0,0 +1,88 @@
import { test } from "node:test";
import assert from "node:assert/strict";
import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { ageOfImage, ageOfSource, isStale, plannedRuntimes, runtimesStockedBy, type Ask } from "../src/runtimes.ts";
// The module runtimes a run stocks are rebuilt by the run (novox/hq 04-ISSUES/075): what a bed's
// scenario stocks is found, compared against its source, and built where older.
function aLabWith(beds: Record<string, string>, scenarios: Record<string, string[]>): { root: string; done: () => void } {
const root = mkdtempSync(join(tmpdir(), "mesh-lab-runtimes-"));
mkdirSync(join(root, "scenarios"));
mkdirSync(join(root, "test", "integration"), { recursive: true });
for (const [name, images] of Object.entries(scenarios)) {
writeFileSync(join(root, "scenarios", `${name}.yml`), `scenario: ${name}\nimages:\n${images.map((i) => ` - ${i}\n`).join("")}`);
}
for (const [file, scenario] of Object.entries(beds)) {
writeFileSync(join(root, "test", "integration", file), `const SCENARIO = "${scenario}";\n`);
}
return { root, done: () => rmSync(root, { recursive: true, force: true }) };
}
test("what a bed's scenario stocks is found, by module, once", () => {
const lab = aLabWith(
{ "a.test.ts": "one", "b.test.ts": "two", "c.test.ts": "one" },
{ one: ["mesh-controller:development", "mesh-runtime-gitlab:development", "postgres:16"],
two: ["mesh-runtime-gitlab:development", "mesh-runtime-audit:development"] });
try {
const found = runtimesStockedBy(["test/integration/a.test.ts", "test/integration/b.test.ts", "test/integration/c.test.ts"], lab.root);
assert.deepEqual(found, [
{ tag: "mesh-runtime-gitlab:development", module: "gitlab" },
// The audit logger's runtime is stocked under its slug, and the module is named for it.
{ tag: "mesh-runtime-audit:development", module: "audit-logger" },
]);
} finally { lab.done(); }
});
test("an image is stale when missing, older than its source, or when the source is uncommitted", () => {
assert.equal(isStale({ image: null, source: 0 }), true);
assert.equal(isStale({ image: 100, source: 200 }), true);
assert.equal(isStale({ image: 200, source: 100 }), false);
assert.equal(isStale({ image: 200, source: Infinity }), true);
});
test("the image's age comes from the store and the source's from the newest commit in any part", () => {
const answers: Ask = (command, args) => {
if (command === "docker") return { status: 0, stdout: "2026-09-21T12:00:00.000000000Z\n" };
if (args.includes("status")) return { status: 0, stdout: "" };
if (args.includes("modules/gitlab")) return { status: 0, stdout: "1000\n" };
return { status: 0, stdout: args[1] === "/tools" ? "3000\n" : "2000\n" };
};
assert.equal(ageOfImage("mesh-runtime-gitlab:development", answers), Date.parse("2026-09-21T12:00:00Z") / 1000);
assert.equal(ageOfSource("/catalogue", "gitlab", ["/tools", "/sdk"], answers), 3000);
// No such image is null, not zero: "never built" and "built at the epoch" are different answers.
assert.equal(ageOfImage("mesh-runtime-nothing:development", () => ({ status: 1, stdout: "" })), null);
// Uncommitted changes anywhere in the source are newer than every commit.
const dirtyTools: Ask = (command, args) =>
args.includes("status") && args[1] === "/tools" ? { status: 0, stdout: " M src/x.ts\n" } : answers(command, args);
assert.equal(ageOfSource("/catalogue", "gitlab", ["/tools", "/sdk"], dirtyTools), Infinity);
});
test("only a stale runtime is planned, built by the lab's own script under the tag the scenario stocks", () => {
const lab = aLabWith({ "a.test.ts": "one" },
{ one: ["mesh-runtime-gitlab:development", "mesh-runtime-audit:development"] });
try {
const answers: Ask = (command, args) => {
if (command === "docker") {
// gitlab's image is from yesterday; the audit logger has none.
return args.includes("mesh-runtime-gitlab:development")
? { status: 0, stdout: "2026-09-21T12:00:00Z\n" } : { status: 1, stdout: "" };
}
if (args.includes("status")) return { status: 0, stdout: "" };
return { status: 0, stdout: `${Date.parse("2026-09-20T00:00:00Z") / 1000}\n` };
};
const env = { MESH_LAB_CATALOG: "/catalogue/modules", MESH_TOOLS: "/tools", MESH_SDK: "/sdk" };
const builds = plannedRuntimes(["test/integration/a.test.ts"], env, lab.root, answers);
assert.equal(builds.length, 1);
assert.equal(builds[0]!.what, "runtime mesh-runtime-audit:development");
assert.equal(builds[0]!.argv[0], "scripts/build-module-runtime.sh");
assert.equal(builds[0]!.argv[1], "audit-logger");
assert.equal(builds[0]!.env?.["MESH_CATALOG"], "/catalogue");
assert.equal(builds[0]!.env?.["RUNTIME_TAG"], "mesh-runtime-audit:development");
// No catalogue named: nothing is planned, because no bed will read one either.
assert.deepEqual(plannedRuntimes(["test/integration/a.test.ts"], {}, lab.root, answers), []);
} finally { lab.done(); }
});