Files
mesh-lab/test/rebuild.test.ts
jschoubben f2d29491b2 The receipt claims the catalogue the beds read
A bed installs a catalogue module by reading its manifest from MESH_LAB_CATALOG at
run time, so a receipt naming no catalogue commit cannot say whether a catalogue
change was ever proven. Claimed under either spelling of the variable; not built,
because a manifest is read, not compiled (novox/hq 04-ISSUES/073).
2026-09-21 14:14:54 +02:00

132 lines
6.8 KiB
TypeScript

import { test } from "node:test";
import assert from "node:assert/strict";
import { planned, carriedImage } from "../src/rebuild.ts";
import { repositories } from "../src/repos.ts";
import { loadScenario } from "../src/declaration/parse.ts";
// The control plane's image and the builder are one step, not two.
//
// Both parse manifests. On 2026-08-30 a rename was built into the image and not the binary, and
// the run that found out was a full lab raise. novox/hq 04-ISSUES/005.
test("the control plane's image and builder are always built together", () => {
const builds = planned({
MESH_LAB_MODULES: "/repo/control/examples/modules",
MESH_LAB_BUILDER: "/repo/control/build/mesh-builder",
});
const what = builds.map((b) => b.what);
assert.ok(what.includes("images"), "the images were not built");
assert.ok(what.includes("builder"), "the builder was not built");
for (const build of builds) assert.equal(build.in, "/repo/control");
});
// Every image the lab runs, not only the control plane's.
//
// On 2026-09-01 a run had a control-plane image built that minute and a provisioner image built
// the day before. A test against a real database failed, and it looked exactly like the change
// under test being wrong: the provisioner was creating logins by a naming rule that had been
// replaced hours earlier. novox/hq 04-ISSUES/005 again, one target along.
//
// Named individually rather than by counting, because the failure this guards is a target that
// exists and is not run — which a count would not notice.
test("every image the lab runs is rebuilt, not only the control plane's", () => {
const builds = planned({ MESH_LAB_MODULES: "/repo/control/examples/modules" });
const images = builds.find((b) => b.what === "images");
assert.ok(images, "no image build at all");
for (const target of [
"image", "builder-image", "provisioner-image", "objectstore-image",
"redis-provisioner-image", "proxy-image",
]) {
assert.ok(images.argv.includes(target), `${target} is never built, so the lab runs a stale one`);
}
});
// The installer is built, and it is built AFTER the image it carries.
//
// `make bootstrap` embeds the output of `docker save <image>`, so an installer built before the
// control plane's image is one carrying whatever was lying around — 04-ISSUES/005 again, this time
// sealed inside a binary where nothing would ever notice. The bed raises its anchor by running this
// program (novox/hq ADR 0067), so a stale one is a bed proving something about last week.
test("the installer is built, carrying the image built in the same run", () => {
const builds = planned({
MESH_LAB_HOST_BINARY: "/repo/host/mesh-host",
MESH_LAB_MODULES: "/repo/control/examples/modules",
MESH_LAB_BOOTSTRAP_BINARY: "/repo/host/mesh-bootstrap",
});
const what = builds.map((b) => b.what);
assert.ok(what.includes("installer"), "the installer is never built, so the bed carries a stale one");
assert.ok(
what.indexOf("images") < what.indexOf("installer"),
`the installer is built before the image it embeds: ${what.join(", ")}`,
);
const installer = builds.find((b) => b.what === "installer")!;
assert.equal(installer.in, "/repo/host");
assert.ok(installer.argv.includes(`IMAGE=${carriedImage({})}`), installer.argv.join(" "));
assert.ok(installer.argv.includes("BOOTSTRAP_OUT=/repo/host/mesh-bootstrap"), installer.argv.join(" "));
});
// The anchor must NOT be handed the control plane's image.
//
// The installer carries it, which is the whole reason a machine that can reach no registry can
// raise a mesh (novox/hq ADR 0067). Hand it over from the workstation as well and the installer's
// load says "already held", the carrying is never exercised, and the bed goes green on a fiction —
// the same class of thing the lab's own registry used to hide. Asserted on the file rather than
// remembered, because a list of images is exactly the kind of thing somebody tops up.
test("the whole-mesh bed hands its anchor no control-plane image", () => {
const scenario = loadScenario("scenarios/whole-mesh-full.yml");
const named = [
...(scenario.images ?? []),
...Object.values(scenario.machines).flatMap((m) => m.images ?? []),
];
assert.deepEqual(
named.filter((i) => i.startsWith("mesh-controller")),
[],
"the anchor is handed mesh-controller, so genesis would never find out whether the installer " +
"really carries it",
);
});
// A repository this run was not pointed at is not built, and not claimed.
test("only what this run was pointed at is built", () => {
assert.deepEqual(planned({}), []);
const hostOnly = planned({ MESH_LAB_HOST_BINARY: "/repo/host/mesh-host" });
assert.deepEqual(hostOnly.map((b) => b.what), ["host"]);
assert.equal(hostOnly[0]!.in, "/repo/host");
});
// What the receipt claims and what the run built come from one derivation.
//
// They are separate concerns that must agree: a receipt naming a repository the run did not build
// is false coverage arriving by nobody's decision — just two derivations drifting apart.
// novox/hq 04-ISSUES/005.
test("every repository the receipt claims was built by the run", () => {
const env = {
MESH_LAB_HOST_BINARY: "/repo/host/mesh-host",
MESH_LAB_MODULES: "/repo/control/examples/modules",
MESH_LAB_BUILDER: "/repo/control/build/mesh-builder",
MESH_LAB_CATALOG: "/repo/catalog/modules",
};
const built = new Set(planned(env).map((b) => b.in));
for (const [name, directory] of Object.entries(repositories(env))) {
// mesh-lab is the exception, and it is not an omission: it is TypeScript run from source, so
// the code under test *is* the code running. There is nothing to build and nothing to go stale.
if (name === "mesh-lab") continue;
// mesh-catalog is the other exception, for the other reason: what a bed takes from it is a
// manifest, read from disk when the bed runs. There is nothing built from it that could go
// stale — and claiming it is the whole point, since a bed that carried its own copy of the
// manifest was proving the copy (novox/hq 04-ISSUES/073).
if (name === "mesh-catalog") continue;
assert.ok(built.has(directory), `${name} (${directory}) is claimed but never built`);
}
});
// The catalogue is claimed by the receipt, under either spelling the beds accept.
//
// A bed reads the manifest it installs from the catalogue checkout (novox/hq 04-ISSUES/073), so a
// receipt that names no catalogue commit cannot say whether a change there was ever proven.
test("the receipt claims the catalogue the beds read, however it was named", () => {
assert.equal(repositories({ MESH_LAB_CATALOG: "/repo/catalog/modules" })["mesh-catalog"], "/repo/catalog");
assert.equal(repositories({ MESH_LAB_CATALOG: "/repo/catalog" })["mesh-catalog"], "/repo/catalog");
assert.equal(repositories({})["mesh-catalog"], undefined);
});