diff --git a/README.md b/README.md index e69ad53..a6f682b 100644 --- a/README.md +++ b/README.md @@ -164,7 +164,10 @@ export MESH_LAB_ROUTE_PROXY=/route-proxy `MESH_LAB_HOST_BINARY` and `MESH_LAB_MODULES` do double duty: the repository each sits in is what `suite` rebuilds and what the receipt claims. Point the run at a repository and it is built and -claimed; leave it out and it is neither. +claimed; leave it out and it is neither. `MESH_LAB_CATALOG` is claimed without being built: a bed +installs a catalogue module by reading its manifest from that checkout when it runs, so the +receipt names the catalogue's commit too, and a run taken before a manifest changed says so +(novox/hq 04-ISSUES/073). Check before running a long suite — it says which of these are missing rather than skipping quietly: diff --git a/src/repos.ts b/src/repos.ts index c0330e0..4e9ce50 100644 --- a/src/repos.ts +++ b/src/repos.ts @@ -10,7 +10,7 @@ * pointed at is neither built nor claimed. */ -import { dirname } from "node:path"; +import { basename, dirname } from "node:path"; export interface Repositories { /** Absolute path to the repository root, by name. */ @@ -24,5 +24,16 @@ export function repositories(env: NodeJS.ProcessEnv = process.env): Repositories if (host) found["mesh-host"] = dirname(host); const modules = env["MESH_LAB_MODULES"]; if (modules) found["mesh-controller"] = dirname(dirname(modules)); + // The catalogue is read, not built: a bed installs a module by reading its manifest from this + // checkout at run time (novox/hq 04-ISSUES/073). A receipt that did not name the catalogue's + // commit could not say whether a catalogue change had been proven — the beds used to carry + // their own copies of the manifests, and then it could not. + const catalogue = env["MESH_LAB_CATALOG"]; + if (catalogue) found["mesh-catalog"] = catalogueRoot(catalogue); return found; } + +/** MESH_LAB_CATALOG is accepted under either spelling — the checkout, or its `modules` directory. */ +export function catalogueRoot(catalogue: string): string { + return basename(catalogue) === "modules" ? dirname(catalogue) : catalogue; +} diff --git a/test/rebuild.test.ts b/test/rebuild.test.ts index 32af5f5..8d7855c 100644 --- a/test/rebuild.test.ts +++ b/test/rebuild.test.ts @@ -104,12 +104,28 @@ test("every repository the receipt claims was built by the run", () => { 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); +});