diff --git a/bin/reviewer-poll.ts b/bin/reviewer-poll.ts index 5b7f590..925f73c 100644 --- a/bin/reviewer-poll.ts +++ b/bin/reviewer-poll.ts @@ -532,6 +532,19 @@ const PR_ACTIONS = new Set([ "synchronize", "synchronized", "closed", "merged", ]); +// Every drop is a 202, which the forge records as a successful delivery -- so +// without this line a misconfigured filter looks identical to no traffic. +function drop(forge: string, event: string, why: string): Response { + log(`webhook ${forge} ${event}: dropped, ${why}`); + return new Response("ignored", { status: 202 }); +} + +function watched(repo: string): boolean { + return config.repos.some( + (r) => r.repo === "*" || r.repo === repo || (r.repo.endsWith("/*") && repo.startsWith(r.repo.slice(0, -1))), + ); +} + function verify(forge: string, body: string, headers: Headers): boolean { const env = config.forges[forge]?.webhookSecretEnv; const secret = env ? process.env[env] : undefined; @@ -573,12 +586,12 @@ function serveWebhooks(): void { const repo = payload.repository?.full_name; // An issue_comment on a real issue carries a number too, and it is not // one of ours -- only the ones with a pull_request link are. - const number = payload.pull_request?.number ?? (payload.issue?.pull_request ? payload.issue.number : undefined); - if (!repo || !number) return new Response("ignored", { status: 202 }); + // gitea marks a PR comment with is_pull; github nests a pull_request link. + const isPr = Boolean(payload.issue?.pull_request) || payload.is_pull === true; + const number = payload.pull_request?.number ?? (isPr ? payload.issue?.number : undefined); + if (!repo || !number) return drop(forge, event, `no pull request in payload (repo=${repo ?? "?"})`); // Allowlist, so an unrelated repo pointed at this endpoint does nothing. - if (!config.repos.some((r) => r.repo === repo || (r.repo.endsWith("/*") && repo.startsWith(r.repo.slice(0, -1))))) { - return new Response("not watched", { status: 202 }); - } + if (!watched(repo)) return drop(forge, event, `${repo} not in the watched set`); const actionable = (event === "pull_request" && PR_ACTIONS.has(payload.action ?? "")) || event.startsWith("pull_request_review") || @@ -588,7 +601,7 @@ function serveWebhooks(): void { event === "check_suite" || event === "check_run" || event === "status"; - if (!actionable) return new Response("filtered", { status: 202 }); + if (!actionable) return drop(forge, event, `${repo}#${number} action=${payload.action ?? "-"}`); // The payload only ever selects which PR to look at. Everything acted on // is re-read from the API in the next tick.