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:
@@ -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");
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user