E1 moves the module's source for real
Reading the branch head and telling the mesh the source had moved there named the commit it had just built, so the mesh correctly answered that everything was current. Naming a different commit would not work either: staleness compares artifacts, not commits, deliberately, so that editing a comment in a shared base does not rebuild everything standing on it to arrive back where it started. So the step makes a real change and pushes it, and asserts the module comes back on a DIFFERENT artifact than it had. A test that writes to a branch is worth knowing about; the alternative is proving the loop by telling the mesh something untrue. Claude-Session: https://claude.ai/code/session_01D6qtiYU3P9jk3pnAXyAFyx
This commit is contained in:
@@ -38,7 +38,8 @@
|
||||
*/
|
||||
import { test, before, after } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { existsSync, writeFileSync } from "node:fs";
|
||||
import { existsSync, writeFileSync, appendFileSync } from "node:fs";
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { resolve } from "node:path";
|
||||
import { loadScenario } from "../../src/declaration/parse.ts";
|
||||
import { raise } from "../../src/lifecycle/raise.ts";
|
||||
@@ -133,7 +134,7 @@ const CATALOGUED = "the catalogue holds every module this mesh built";
|
||||
const NETWORK = "the machine's networking is what the modules asked for";
|
||||
const FOLLOWS = "a change to a module's source reaches the machine on its own";
|
||||
const SURVIVES = "the mesh comes back after the machine reboots";
|
||||
const MODULE = { module: "amqp-ping", repo: "mesh-catalog", path: "modules/amqp-ping" };
|
||||
const MODULE = { module: "amqp-ping", repo: "mesh-catalog", path: "modules/amqp-ping", container: "amqp-ping" };
|
||||
|
||||
const capability = await labIsUsable();
|
||||
const binary = hostBinaryPath();
|
||||
@@ -833,26 +834,51 @@ before(async () => {
|
||||
// machinery; this is what the machinery is for.
|
||||
await step("E1", FOLLOWS, NETWORK, async () => {
|
||||
const before = await mesh(`builds ${MODULE.module}`);
|
||||
const wasPinned = before.match(/sha256:[0-9a-f]{64}/)?.[0] ?? "";
|
||||
assert.ok(wasPinned, `nothing is pinned to rebuild from:\n${before}`);
|
||||
const was = before.match(/sha256:[0-9a-f]{64}/)?.[0] ?? "";
|
||||
assert.ok(was, `nothing is pinned to rebuild from:\n${before}`);
|
||||
|
||||
// The mesh is told its copy is older than the source. In life a push does this; here it is
|
||||
// stated, because what is under test is what the mesh does next, not how it hears.
|
||||
const head = (await must(CONTROL, `git ls-remote ${forgeUrl(MODULE.repo)} ` +
|
||||
`${refFor(MODULE.repo)} | cut -f1`, 120_000)).trim();
|
||||
assert.match(head, /^[0-9a-f]{40}$/, `could not read the source's head: ${head}`);
|
||||
// **The source has to actually move, and it cannot be faked.**
|
||||
//
|
||||
// The first version of this read the branch head and told the mesh the source had moved there
|
||||
// — the same commit it had just built. The mesh answered, correctly, that everything was
|
||||
// current. Naming some other commit would not work either: staleness compares ARTIFACTS, not
|
||||
// commits, which is a deliberate choice so that editing a comment in a shared base does not
|
||||
// rebuild everything standing on it to arrive back where it started.
|
||||
//
|
||||
// So this makes a real change to the module's source and pushes it. It is a test that writes
|
||||
// to a branch, which is worth knowing about; the alternative is a test that proves the loop by
|
||||
// telling the mesh something untrue.
|
||||
const checkout = resolve(catalogDir, "..");
|
||||
const marker = `// changed by the one-node test at build ${was.slice(7, 19)}\n`;
|
||||
const file = resolve(catalogDir, MODULE.module, "index.ts");
|
||||
await must(CONTROL, `true`); // keep the shape uniform; the change is made on this workstation
|
||||
appendFileSync(file, marker);
|
||||
// Path-scoped: `commit -am` would sweep whatever else is in the working tree into a commit
|
||||
// this test is about to push.
|
||||
execFileSync("git", ["-C", checkout, "add", file], { stdio: "pipe" });
|
||||
execFileSync("git", ["-C", checkout, "commit", "-q", "-m",
|
||||
`Move ${MODULE.module}'s source, so the mesh has something to notice`], { stdio: "pipe" });
|
||||
execFileSync("git", ["-C", checkout, "push", "-q", "origin", refFor(MODULE.repo)],
|
||||
{ stdio: "pipe" });
|
||||
const head = execFileSync("git", ["-C", checkout, "rev-parse", "HEAD"],
|
||||
{ encoding: "utf8" }).trim();
|
||||
|
||||
// Now the mesh is told. In life a push notices itself; what is under test here is what the
|
||||
// mesh does NEXT, not how it hears.
|
||||
await mesh(`module moved ${MODULE.module} ${head}`);
|
||||
|
||||
const behind = await mesh(`status`);
|
||||
assert.match(behind, /behind|build --behind/,
|
||||
`the mesh does not report a module behind its source:\n${behind}`);
|
||||
`the source moved and the mesh does not report the module behind it:\n${behind}`);
|
||||
|
||||
await mesh(`build --behind --wait 1200s`, 1_500_000);
|
||||
const rolled = await mesh(`upgrade ${MODULE.module} roll-out`, 900_000);
|
||||
await waitForContainer(CONTROL, MODULE.module);
|
||||
await waitForContainer(CONTROL, MODULE.container);
|
||||
|
||||
const after = await mesh(`builds ${MODULE.module}`);
|
||||
assert.match(after, /sha256:[0-9a-f]{64}/, `nothing was pinned after the rebuild:\n${after}`);
|
||||
const now = after.match(/sha256:[0-9a-f]{64}/)?.[0] ?? "";
|
||||
assert.notEqual(now, was,
|
||||
`the module was rebuilt and came back on the same artifact, so nothing reached the machine:` +
|
||||
`\n${after}`);
|
||||
return `${behind}\n${rolled}\n${after}`;
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user