import assert from "node:assert/strict"; import { test } from "node:test"; // A branch's protection (novox/hq ADR 0237): what the operator's agent sets so a pull request waits for the // mesh's merge check before it merges. test("a rule's body requires no status, whatever the rule required (ADR 0534 §5)", async () => { const { protectionBody } = await import("../dist/protection.js"); assert.deepEqual(protectionBody({}, false), { enable_status_check: false, status_check_contexts: [] }, "an edited rule keeps its pushes as they are, and requires no status"); }); test("a new rule refuses direct pushes unless asked; an administrator's override only when said", async () => { const { protectionBody } = await import("../dist/protection.js"); assert.equal(protectionBody({}, true).enable_push, false); assert.equal(protectionBody({ push: true }, true).enable_push, true); assert.equal(protectionBody({}, true).block_admin_merge_override, undefined); assert.equal(protectionBody({ blockAdminOverride: true }, false).block_admin_merge_override, true); }); // Issue 948 (novox/hq ADR 0398 §2): main takes no push, and only the tools' account merges; it requires no status // (ADR 0534 §1). test("main's body always refuses pushes and lets only the tools' account merge, whatever is asked", async () => { const { protectionBody } = await import("../dist/protection.js"); const { TOOLS_ACCOUNT } = await import("../dist/tools-account.js"); for (const creating of [true, false]) { for (const want of [{}, { push: true }, { push: false }]) { const body = protectionBody(want, creating, "main"); assert.equal(body.enable_push, false, "main takes no push, an edit and a push=true included"); assert.equal(body.enable_merge_whitelist, true); assert.deepEqual(body.merge_whitelist_usernames, [TOOLS_ACCOUNT]); assert.equal(body.enable_status_check, false); assert.deepEqual(body.status_check_contexts, []); } } assert.deepEqual(TOOLS_ACCOUNT, "mesh-tools"); }); test("another branch's body carries no merge whitelist", async () => { const { protectionBody } = await import("../dist/protection.js"); const body = protectionBody({}, false, "release/1"); assert.equal(body.enable_merge_whitelist, undefined); assert.equal(body.merge_whitelist_usernames, undefined); }); test("the rule main is put right in the forge's own words: no push, the tools' account merges, no status required", async () => { const { mainRuleBody } = await import("../dist/protection.js"); assert.deepEqual(mainRuleBody(), { enable_push: false, enable_merge_whitelist: true, merge_whitelist_usernames: ["mesh-tools"], enable_status_check: false, status_check_contexts: [] }); }); // The operator's own login stays on main's merge whitelist beside the tools' account (novox/hq ADR 0534 §2): read from // the module's config value main-mergers, in the runtime config file; nothing there leaves the tools' account alone. test("main's merge whitelist is the tools' account, then the configured mergers once each", async () => { const { mainMergers, mainRuleBody } = await import("../dist/protection.js"); const { mkdtempSync, writeFileSync } = await import("node:fs"); const { join } = await import("node:path"); const { tmpdir } = await import("node:os"); const file = join(mkdtempSync(join(tmpdir(), "gitea-mergers-")), "config.json"); writeFileSync(file, JSON.stringify({ url: "", "main-mergers": ["jschoubben", "mesh-tools", "jschoubben", "../x", "a b"] })); assert.deepEqual(mainMergers({ MESH_GITEA_CONFIG_FILE: file }), ["mesh-tools", "jschoubben"]); assert.deepEqual(mainMergers({}), ["mesh-tools"]); assert.deepEqual(mainMergers({ MESH_GITEA_CONFIG_FILE: join(tmpdir(), "no-such-gitea-config.json") }), ["mesh-tools"]); assert.deepEqual(mainRuleBody(["mesh-tools", "jschoubben"]).merge_whitelist_usernames, ["mesh-tools", "jschoubben"]); });