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, scenarios: Record): { 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(); } });