A merge older than the watching is history, not news

An old merge past the first page of the forge's listing surfaced as newer pull requests were
updated, and was announced as if it had just happened; the mesh then rebuilt everything built from
that repository, once per old merge. The moment the watching began is kept with the record, and
only a merge made since is announced.
This commit is contained in:
2026-09-28 05:08:20 +02:00
parent 1c995fa9fc
commit 2b8a668d06
+15 -3
View File
@@ -61,9 +61,17 @@ import { join } from "node:path";
const mergedRecord = process.env.MESH_GITEA_STATE_DIR ? join(process.env.MESH_GITEA_STATE_DIR, "merged-announced.json") : null; const mergedRecord = process.env.MESH_GITEA_STATE_DIR ? join(process.env.MESH_GITEA_STATE_DIR, "merged-announced.json") : null;
const announced = new Set<string>(); const announced = new Set<string>();
let primedMerges = false; let primedMerges = false;
// since is the moment the watching began: a merge made before it is history, whatever page of the
// forge's listing it surfaces on. Without it, an old merge past the first page — pushed into view
// as newer pull requests were updated — was announced as if it had just happened, and the mesh
// rebuilt everything built from that repository, once per old merge (2026-09-28).
let since = "";
if (mergedRecord && existsSync(mergedRecord)) { if (mergedRecord && existsSync(mergedRecord)) {
try { try {
for (const sha of JSON.parse(readFileSync(mergedRecord, "utf8")) as string[]) announced.add(sha); const kept = JSON.parse(readFileSync(mergedRecord, "utf8")) as string[] | { announced: string[]; since: string };
const list = Array.isArray(kept) ? kept : kept.announced;
for (const sha of list) announced.add(sha);
since = Array.isArray(kept) ? new Date().toISOString() : kept.since;
primedMerges = true; primedMerges = true;
} catch { } catch {
// An unreadable record is treated as no record: prime again rather than re-announce history. // An unreadable record is treated as no record: prime again rather than re-announce history.
@@ -73,7 +81,7 @@ function keepAnnounced(): void {
if (!mergedRecord) return; if (!mergedRecord) return;
mkdirSync(join(mergedRecord, ".."), { recursive: true }); mkdirSync(join(mergedRecord, ".."), { recursive: true });
const tmp = mergedRecord + ".tmp"; const tmp = mergedRecord + ".tmp";
writeFileSync(tmp, JSON.stringify([...announced].slice(-2000))); writeFileSync(tmp, JSON.stringify({ announced: [...announced].slice(-2000), since }));
renameSync(tmp, mergedRecord); renameSync(tmp, mergedRecord);
} }
async function pollMerged(client: GiteaClient): Promise<void> { async function pollMerged(client: GiteaClient): Promise<void> {
@@ -83,7 +91,10 @@ async function pollMerged(client: GiteaClient): Promise<void> {
const pulls = await client.listPullRequests(repo.owner, repo.name, { state: "closed", sort: "recentupdate", limit: "20" }); const pulls = await client.listPullRequests(repo.owner, repo.name, { state: "closed", sort: "recentupdate", limit: "20" });
for (const pull of pulls) { for (const pull of pulls) {
if (!pull.merged || !pull.merge_commit_sha || announced.has(pull.merge_commit_sha)) continue; if (!pull.merged || !pull.merge_commit_sha || announced.has(pull.merge_commit_sha)) continue;
if (primedMerges) { // Announced only if merged since the watching began; recorded either way, so it is looked
// at once.
const fresh = !!pull.merged_at && !!since && pull.merged_at > since;
if (primedMerges && fresh) {
await emit("pull.merged", { await emit("pull.merged", {
owner: repo.owner, owner: repo.owner,
repo: repo.name, repo: repo.name,
@@ -101,6 +112,7 @@ async function pollMerged(client: GiteaClient): Promise<void> {
changed = true; changed = true;
} }
} }
if (!primedMerges) since = new Date().toISOString();
if (!primedMerges || changed) keepAnnounced(); if (!primedMerges || changed) keepAnnounced();
primedMerges = true; primedMerges = true;
} }