issue 976: the forge's announcements get a deterministic message id; the announcement files go, the poll's watermark is kept in the module's state

This commit is contained in:
2026-10-17 13:52:47 +02:00
parent 2c8c1543ba
commit add91ff048
6 changed files with 274 additions and 59 deletions
+63
View File
@@ -0,0 +1,63 @@
import assert from "node:assert/strict";
import { test } from "node:test";
// **The forge's announcements carry a message id** (novox/hq ADR 0406 §6, §7, issue 976): the same announcement,
// however many paths make it — the poll, the forge's event, the merge tool's ask — has one id, which the runtime makes
// the bus's message id, so the bus stores it once. This replaces the files of what was announced.
const merged = { owner: "novox", repo: "app", number: 7, head_sha: "aaa111", merge_commit_sha: "mmm222", base: "main" };
const updated = { owner: "novox", repo: "app", number: 7, head_sha: "aaa111", base_sha: "ttt333", base: "main" };
const closed = { owner: "novox", repo: "app", number: 7, head_sha: "aaa111", base: "main" };
test("the same merge, head or close announced twice has the same id, and another has another", async () => {
const { announcementId } = await import("../announce.ts");
assert.equal(announcementId("pull.merged", merged), "merged:novox/app#7@mmm222");
assert.equal(announcementId("pull.merged", { ...merged, title: "worded differently" }), announcementId("pull.merged", merged));
assert.notEqual(announcementId("pull.merged", { ...merged, merge_commit_sha: "other" }), announcementId("pull.merged", merged));
assert.equal(announcementId("pull.updated", updated), "updated:novox/app#7@aaa111:ttt333");
assert.notEqual(announcementId("pull.updated", { ...updated, base_sha: "moved" }), announcementId("pull.updated", updated),
"the check asked again against a new trunk commit is another announcement");
assert.notEqual(announcementId("pull.updated", { ...updated, head_sha: "bbb" }), announcementId("pull.updated", updated));
assert.equal(announcementId("pull.updated", { ...updated, base_sha: undefined }), "updated:novox/app#7@aaa111:");
assert.equal(announcementId("pull.closed", closed), "closed:novox/app#7@aaa111");
});
test("an announcement is published through the broker with its id as the event id, and the provenance emit stamps", async () => {
const { useBroker } = await import("@novox/mesh-sdk/messaging");
const published: any[] = [];
useBroker(() => ({ publish: async (env: any) => { published.push(env); } }) as any);
process.env.MESH_MODULE = "gitea";
process.env.MESH_NODE = "anchor";
const { announce } = await import("../announce.ts");
await announce("pull.merged", merged);
await announce("pull.merged", { ...merged });
assert.equal(published.length, 2);
assert.equal(published[0].key, "pull.merged");
assert.equal(published[0].headers["x-event-id"], "merged:novox/app#7@mmm222");
assert.equal(published[1].headers["x-event-id"], published[0].headers["x-event-id"], "one id for one announcement");
assert.equal(published[0].headers["x-source"], "gitea");
assert.equal(published[0].headers["x-node"], "anchor");
assert.equal(published[0].headers["content-type"], "application/json");
assert.ok(published[0].headers["x-time"]);
assert.equal(published[0].node, "anchor");
assert.deepEqual(published[0].body, merged);
});
test("an announcement of a kind it has no id for is refused, never published with a made-up one", async () => {
const { announce, announcementId } = await import("../announce.ts");
assert.equal(announcementId("repo.created", { owner: "a" }), undefined);
await assert.rejects(() => announce("repo.created", { owner: "a" }), /not an announcement with a message id/);
});
test("the watermark is kept in the module's state, and an unreachable state is no record", async () => {
const { readWatermark, keepWatermark } = await import("../announce.ts");
const kept = new Map<string, unknown>();
const store = { get: async (k: string) => (kept.has(k) ? { key: k, value: kept.get(k), revision: 1 } : null),
put: async (k: string, v: unknown) => { kept.set(k, v); return 1; } };
assert.equal(await readWatermark(store as any), "", "none yet");
await keepWatermark("2026-10-17T12:00:00.000Z", store as any);
assert.equal(await readWatermark(store as any), "2026-10-17T12:00:00.000Z");
const away = { get: async () => { throw new Error("no runtime"); }, put: async () => { throw new Error("no runtime"); } };
assert.equal(await readWatermark(away as any), "", "a state that cannot be reached is no record");
await keepWatermark("2026-10-17T12:01:00.000Z", away as any); // said, not thrown
});