feat(continuity): automate publish and cache finalization
This commit is contained in:
parent
03a376a100
commit
0756ec4258
4 changed files with 792 additions and 0 deletions
|
|
@ -0,0 +1,78 @@
|
|||
import assert from "node:assert/strict";
|
||||
import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import test from "node:test";
|
||||
import {
|
||||
normalizeBranch,
|
||||
normalizeCodeChannelRepository,
|
||||
normalizeReceipt,
|
||||
parseArgs,
|
||||
safeCacheRelative,
|
||||
selfTest,
|
||||
} from "./finalize-development.mjs";
|
||||
|
||||
test("the finalizer accepts only the registered Fifth Domain code channel", () => {
|
||||
assert.equal(
|
||||
normalizeCodeChannelRepository(
|
||||
"https://guanghulab.com/code/bingshuo/guanghu-ice-heart.git",
|
||||
).identity,
|
||||
"repo://guanghulab.com/code/bingshuo/guanghu-ice-heart",
|
||||
);
|
||||
for (const invalid of [
|
||||
"https://guanghulab.com/fifth-domain/bingshuo/fifth-domain.git",
|
||||
"https://example.com/code/bingshuo/guanghu-ice-heart.git",
|
||||
"https://user:secret@guanghulab.com/code/bingshuo/guanghu-ice-heart.git",
|
||||
]) {
|
||||
assert.throws(() => normalizeCodeChannelRepository(invalid));
|
||||
}
|
||||
});
|
||||
|
||||
test("receipt and branch validation fail closed", () => {
|
||||
assert.equal(normalizeBranch("main"), "main");
|
||||
assert.equal(
|
||||
normalizeReceipt("deployment/receipts/EXACT.json"),
|
||||
"deployment/receipts/EXACT.json",
|
||||
);
|
||||
assert.throws(() => normalizeReceipt("../EXACT.json"));
|
||||
assert.throws(() => normalizeReceipt("docs/EXACT.json"));
|
||||
assert.throws(() => normalizeBranch("../main"));
|
||||
});
|
||||
|
||||
test("repeated receipts and cleanup paths are retained", () => {
|
||||
const parsed = parseArgs([
|
||||
"--development-id",
|
||||
"DEV-20260805-003",
|
||||
"--receipt",
|
||||
"deployment/receipts/A.json",
|
||||
"--receipt",
|
||||
"deployment/receipts/B.json",
|
||||
"--cleanup-path",
|
||||
"target",
|
||||
]);
|
||||
assert.deepEqual(parsed.receipts, [
|
||||
"deployment/receipts/A.json",
|
||||
"deployment/receipts/B.json",
|
||||
]);
|
||||
assert.deepEqual(parsed.cleanupPaths, ["target"]);
|
||||
});
|
||||
|
||||
test("cache deletion scope accepts only exact allowlisted descendants", () => {
|
||||
const root = fs.mkdtempSync(path.join(os.tmpdir(), "finalizer-cache-test-"));
|
||||
try {
|
||||
assert.equal(safeCacheRelative(root, "target").relative, "target");
|
||||
assert.equal(
|
||||
safeCacheRelative(root, "src/__pycache__").relative,
|
||||
"src/__pycache__",
|
||||
);
|
||||
assert.throws(() => safeCacheRelative(root, "."));
|
||||
assert.throws(() => safeCacheRelative(root, "../outside"));
|
||||
assert.throws(() => safeCacheRelative(root, "outputs"));
|
||||
} finally {
|
||||
fs.rmSync(root, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test("embedded finalizer self-test passes", () => {
|
||||
assert.deepEqual(selfTest(), { result: "PASS_100" });
|
||||
});
|
||||
Loading…
Reference in a new issue