105 lines
3.6 KiB
JavaScript
105 lines
3.6 KiB
JavaScript
"use strict";
|
|
|
|
const assert = require("node:assert/strict");
|
|
const crypto = require("node:crypto");
|
|
const fs = require("node:fs");
|
|
const os = require("node:os");
|
|
const path = require("node:path");
|
|
const test = require("node:test");
|
|
const { processForgejoMergeWebhook } = require("./forgejo-merge-deployment");
|
|
|
|
const secret = "s".repeat(64);
|
|
const commit = "a".repeat(40);
|
|
|
|
function signed(payload, overrides = {}) {
|
|
const rawBody = Buffer.from(JSON.stringify(payload));
|
|
return {
|
|
rawBody,
|
|
signature: crypto.createHmac("sha256", secret).update(rawBody).digest("hex"),
|
|
eventName: "pull_request",
|
|
delivery: "delivery-12345678",
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
function mergedPayload(overrides = {}) {
|
|
return {
|
|
action: "closed",
|
|
repository: { full_name: "bingshuo/guanghu-ice-heart" },
|
|
pull_request: {
|
|
number: 42,
|
|
merged: true,
|
|
merge_commit_sha: commit,
|
|
merged_by: { login: "bingshuo" },
|
|
base: { ref: "main" },
|
|
...overrides,
|
|
},
|
|
};
|
|
}
|
|
|
|
test("human merged pull request queues only changed deployment manifests", async () => {
|
|
const calls = [];
|
|
const result = await processForgejoMergeWebhook(signed(mergedPayload()), {
|
|
secret,
|
|
allowedMergers: ["bingshuo"],
|
|
deploymentRepositories: { "bingshuo/guanghu-ice-heart": {} },
|
|
queueDir: "/not-used",
|
|
listFiles: async () => [
|
|
{ filename: "server-tools/lake-lamp-authz/server.js", status: "modified" },
|
|
{ filename: "deployment/requests/HLCC-MERGE-DEPLOY-20260806.json", status: "added" },
|
|
],
|
|
enqueue: (...args) => {
|
|
calls.push(args);
|
|
return { state: "queued_for_resident_agent", event_id: args[3].event_id };
|
|
},
|
|
});
|
|
assert.equal(result.state, "queued_for_resident_agent");
|
|
assert.equal(result.queued, 1);
|
|
assert.equal(calls[0][0].resource, `HLCC-MERGE-DEPLOY-20260806@${commit}`);
|
|
assert.equal(calls[0][3].authorizer_id, "ICE-GL∞");
|
|
assert.equal(calls[0][3].target, "JD-FD-PRIMARY");
|
|
});
|
|
|
|
test("ordinary push or closed unmerged request never queues", async () => {
|
|
const push = await processForgejoMergeWebhook(signed(mergedPayload(), { eventName: "push" }), {
|
|
secret,
|
|
allowedMergers: ["bingshuo"],
|
|
});
|
|
assert.equal(push.state, "ignored");
|
|
const closed = await processForgejoMergeWebhook(signed(mergedPayload({ merged: false })), {
|
|
secret,
|
|
allowedMergers: ["bingshuo"],
|
|
});
|
|
assert.equal(closed.state, "ignored");
|
|
});
|
|
|
|
test("unregistered merger and invalid signature fail closed", async () => {
|
|
const merger = await processForgejoMergeWebhook(signed(mergedPayload({ merged_by: { login: "robot" } })), {
|
|
secret,
|
|
allowedMergers: ["bingshuo"],
|
|
});
|
|
assert.equal(merger.diagnostic_code, "human_merger_not_allowed");
|
|
const signature = await processForgejoMergeWebhook(signed(mergedPayload(), { signature: "0".repeat(64) }), {
|
|
secret,
|
|
allowedMergers: ["bingshuo"],
|
|
});
|
|
assert.equal(signature.status, 401);
|
|
});
|
|
|
|
test("delivery retries are idempotent in the real queue", async () => {
|
|
const queueDir = fs.mkdtempSync(path.join(os.tmpdir(), "merge-deploy-"));
|
|
const options = {
|
|
secret,
|
|
allowedMergers: ["bingshuo"],
|
|
deploymentRepositories: { "bingshuo/guanghu-ice-heart": {} },
|
|
queueDir,
|
|
listFiles: async () => [
|
|
{ filename: "deployment/requests/HLCC-MERGE-DEPLOY-20260806.json", status: "added" },
|
|
],
|
|
};
|
|
const first = await processForgejoMergeWebhook(signed(mergedPayload()), options);
|
|
const second = await processForgejoMergeWebhook(signed(mergedPayload()), options);
|
|
assert.equal(first.queued, 1);
|
|
assert.equal(second.state, "duplicate");
|
|
assert.equal(fs.readdirSync(queueDir).filter(name => name.endsWith(".json")).length, 1);
|
|
});
|