Feature 57 (config and provisioning): modules declare config and provisions, their files rendered from templates; synced with main (issues of feature 57, 874)

This commit is contained in:
2026-10-16 07:37:43 +00:00
parent 1a2c917abf
commit 9652b2d5ce
771 changed files with 52063 additions and 1774 deletions
+124 -1
View File
@@ -5,7 +5,7 @@ import { spawnSync } from "node:child_process";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { installPlan, installStep, NPM_REPOSITORIES, REPOSITORIES, script } from "../tools/runs.ts";
import { installPlan, installStep, NPM_REPOSITORIES, outcomeOf, readStatus, REPOSITORIES, script } from "../tools/runs.ts";
// Defends novox/hq issue 624: lab_run ran `npm ci` at the root of every checkout it installs, and
// mesh-tools keeps its package in node-tools/ with no lock file at its root, so every run failed at its
@@ -381,3 +381,126 @@ test("a forge setting that is not http(s) trusts no origin of its own", async ()
packument("ftp://novox.internal/api/packages/novox/npm/x.tgz")).get, root);
assert.match(viaRoot.problem ?? "", /neither/);
});
// The runtime's env file keeps its text once, in files/ as its template (novox/hq ADR 0349 §2, issue 656): no
// file resource carries its text inline, and the build packs files/ into the one archive the controller reads
// the templates back from.
test("every file takes its text from a template in files/", () => {
const dir = join(import.meta.dirname, "..");
const m = JSON.parse(readFileSync(join(dir, "module.json"), "utf8")) as {
resources: Record<string, unknown>[]; build: { artifacts: { name: string; kind?: string; from?: string }[] };
};
for (const r of m.resources) {
assert.equal("content" in r, false, `${String(r.id)} keeps its text inline`);
if (r.type === "file") assert.ok(existsSync(join(dir, String(r.template))), `${String(r.id)} names ${String(r.template)}`);
}
const packs = m.build.artifacts.filter((a) => a.kind === "archive" && a.from === "files");
assert.deepEqual(packs.map((a) => a.name), ["files"]);
const env = m.resources.find((r) => r.id === "runtime-env");
assert.match(readFileSync(join(dir, String(env?.template)), "utf8"), /^MESH_LAB_FORGE=\$\{config:forge\}\n/);
});
// Defends novox/hq issue 693: a run whose only test skipped as NOT REACHED read "0 passed, 0 failed", exit 0,
// and lab_status said passed. The log's tail, as run-2026-10-14T00-21-44-014Z on shanks wrote it.
const oldLog = [
"STOPPED at step 16 of 24, base: \t\t\t\tMake sure you have all the referenced content and try again.",
"\ufe63 genesis adopts its bus as the nats module in place: one bus, its streams kept, the node connected (588152.016874ms) # ADR 0333 §5 NOT REACHED: the first run stopped at step 16 of 24, base, before the broker step:",
" \t\t\t\tMake sure you have all the referenced content and try again.",
"NotFound: content digest sha256:e2de96513ba9: not found",
"ℹ tests 1", "ℹ suites 0", "ℹ pass 0", "ℹ fail 0", "ℹ cancelled 0", "ℹ skipped 1", "ℹ todo 0",
"ℹ duration_ms 590254.163993",
"",
"recorded: test/integration/genesis-keeps-its-bus.test.ts — 0 passed, 0 failed, against mesh-lab 7ed7da1",
].join("\n");
// The same run, as the lab's suite says it once it names its skips (mesh-lab, issue 693).
const newLog = [
"ℹ tests 1", "ℹ pass 0", "ℹ fail 0", "ℹ skipped 1",
"",
"recorded: test/integration/genesis-keeps-its-bus.test.ts — 0 passed, 0 failed, 1 skipped, against mesh-lab 7ed7da1",
"NOT PASSED: no test passed: 1 skipped, 1 of them as NOT REACHED",
"skipped: genesis adopts its bus — one bus (test/integration/genesis-keeps-its-bus.test.ts) # ADR 0333 §5 NOT REACHED: the first run stopped at step 16 of 24, base: NotFound: content digest",
].join("\n");
function anEndedRun(log: string, state: "passed" | "failed", exit: number): { work: string; id: string } {
const work = mkdtempSync(join(tmpdir(), "lab-runs-"));
const id = "run-2026-10-14T00-21-44-014Z";
mkdirSync(join(work, id));
writeFileSync(join(work, id, "run.log"), log);
writeFileSync(join(work, id, "status.json"), JSON.stringify({
id, state, exit, started: "2026-10-14T00:21:44.014Z", ended: "2026-10-14T00:33:11.179Z",
tests: ["test/integration/genesis-keeps-its-bus.test.ts"], refs: {},
}));
return { work, id };
}
test("a run whose only test skipped as NOT REACHED, from a lab of before, reads as failed with the reason", () => {
const { work, id } = anEndedRun(oldLog, "passed", 0);
const s = readStatus(work, id);
assert.equal(s?.state, "failed", JSON.stringify(s));
assert.equal(s?.exit, 0);
assert.equal(s?.outcome?.passed, 0);
assert.equal(s?.outcome?.skipped, 1);
assert.equal(s?.outcome?.notPassed, "no test passed: 1 skipped, 1 of them as NOT REACHED");
assert.match(s?.outcome?.skips[0]?.reason ?? "", /^ADR 0333 §5 NOT REACHED: the first run stopped at step 16 of 24, base, before the broker step:$/);
// Kept in the run's record, not only answered.
const kept = JSON.parse(readFileSync(join(work, id, "status.json"), "utf8"));
assert.equal(kept.state, "failed");
assert.equal(kept.outcome.notPassed, "no test passed: 1 skipped, 1 of them as NOT REACHED");
rmSync(work, { recursive: true, force: true });
});
test("the lab's own NOT PASSED and skipped lines are read, a test name's punctuation and all", () => {
const { work, id } = anEndedRun(newLog, "failed", 1);
const s = readStatus(work, id);
assert.equal(s?.state, "failed");
assert.equal(s?.outcome?.notPassed, "no test passed: 1 skipped, 1 of them as NOT REACHED");
assert.deepEqual(s?.outcome?.skips, [{
file: "test/integration/genesis-keeps-its-bus.test.ts",
test: "genesis adopts its bus — one bus",
reason: "ADR 0333 §5 NOT REACHED: the first run stopped at step 16 of 24, base: NotFound: content digest",
}]);
rmSync(work, { recursive: true, force: true });
});
test("a run that passed tests and skipped one for a declared reason stays passed, its skip listed", () => {
const log = [
"✔ a module lands (12ms)",
"﹣ a builder builds (0.1ms) # set MESH_LAB_BUILDER to a built mesh-builder",
"ℹ tests 2", "ℹ pass 1", "ℹ fail 0", "ℹ skipped 1",
].join("\n");
const { work, id } = anEndedRun(log, "passed", 0);
const s = readStatus(work, id);
assert.equal(s?.state, "passed");
assert.equal(s?.outcome?.notPassed, undefined);
assert.equal(s?.outcome?.skips[0]?.reason, "set MESH_LAB_BUILDER to a built mesh-builder");
rmSync(work, { recursive: true, force: true });
});
test("a run that ran no test at all is not passed", () => {
assert.equal(outcomeOf("ℹ tests 0\nℹ pass 0\nℹ fail 0\nℹ skipped 0\n").notPassed, "no test passed: none ran");
});
// Review 254 on issue 693: a test's own output, printed before the suite reports, is not the suite's verdict.
test("a line a test printed that looks like the suite's is not read as the suite's", () => {
const log = [
"NOT PASSED: a test printed this",
"skipped: a forged skip (test/integration/x.test.ts) # FORGED NOT REACHED",
"✔ a module lands (12ms)",
"ℹ tests 1", "ℹ pass 1", "ℹ fail 0", "ℹ skipped 0",
"",
"recorded: test/integration/x.test.ts — 1 passed, 0 failed, 0 skipped, against mesh-lab 7ed7da1",
].join("\n");
const o = outcomeOf(log);
assert.equal(o.notPassed, undefined, JSON.stringify(o));
assert.deepEqual(o.skips, []);
});
test("not reached is matched in any case", () => {
const log = [
"✔ a module lands (12ms)",
"﹣ the broker step (0.1ms) # the broker step was not reached",
"ℹ tests 2", "ℹ pass 1", "ℹ fail 0", "ℹ skipped 1",
].join("\n");
assert.equal(outcomeOf(log).notPassed, "1 test(s) skipped as NOT REACHED: their subject was not reached");
});