From 6aa091ca92747e089626bf54ca7699ef8bfa9667 Mon Sep 17 00:00:00 2001 From: web-ppanel Date: Sun, 9 Aug 2026 03:40:27 +0000 Subject: [PATCH] fix(automation): make webhook dry runs side-effect free --- scripts/triage-context.mjs | 1 + scripts/triage-context.test.mjs | 40 +++++++++++++++++++++++++++++++++ scripts/triage-webhook.mjs | 10 ++++++--- scripts/triage-webhook.test.mjs | 26 +++++++++++++++++++++ 4 files changed, 74 insertions(+), 3 deletions(-) diff --git a/scripts/triage-context.mjs b/scripts/triage-context.mjs index 47bfc62..4cc7296 100644 --- a/scripts/triage-context.mjs +++ b/scripts/triage-context.mjs @@ -73,6 +73,7 @@ const report = { url: event.issue.html_url, labels: labelsFor(event.issue), user: event.issue.user?.login, + isPullRequest: Boolean(event.issue.pull_request), } : null, ...(isPullRequestEvent && { diff --git a/scripts/triage-context.test.mjs b/scripts/triage-context.test.mjs index 8829cb8..5387a4c 100644 --- a/scripts/triage-context.test.mjs +++ b/scripts/triage-context.test.mjs @@ -127,6 +127,7 @@ test("keeps issue context behavior and filters PR-shaped issues from openIssues" url: "https://github.com/perfect-panel/frontend/issues/7", labels: ["bug"], user: "alice", + isPullRequest: false, }); assert.deepEqual(report.openIssues, [ { @@ -144,6 +145,45 @@ test("keeps issue context behavior and filters PR-shaped issues from openIssues" } }); +test("marks issue comments attached to pull requests for PR routing", async () => { + const event = { + action: "created", + issue: { + number: 42, + title: "Improve billing", + body: "PR body", + html_url: "https://github.com/perfect-panel/frontend/pull/42", + labels: [], + user: { login: "carol" }, + pull_request: {}, + }, + }; + const fixture = await withGithubFixture({ + "/repos/perfect-panel/frontend/issues?state=open&per_page=50": [], + }); + const { workspace, eventPath } = makeWorkspace(event); + + try { + const result = await runContext({ + cwd: workspace, + env: { + TRIAGE_TOKEN: "token", + GITHUB_API_BASE_URL: fixture.baseUrl, + GITHUB_EVENT_NAME: "issue_comment", + GITHUB_EVENT_PATH: eventPath, + GITHUB_REPOSITORY: "perfect-panel/frontend", + }, + }); + assert.equal(result.code, 0, result.stderr); + const report = JSON.parse( + readFileSync(join(workspace, ".automation", "context.json"), "utf8") + ); + assert.equal(report.trigger.issue.isPullRequest, true); + } finally { + await fixture.close(); + } +}); + test("builds pull_request_target context with trigger PR and open PR list from injectable GitHub API base", async () => { const event = { action: "synchronize", diff --git a/scripts/triage-webhook.mjs b/scripts/triage-webhook.mjs index 970dbb5..ab1dc2c 100644 --- a/scripts/triage-webhook.mjs +++ b/scripts/triage-webhook.mjs @@ -11,14 +11,18 @@ if (!(webhookUrl && webhookSecret)) { const context = JSON.parse(readFileSync(".automation/context.json", "utf8")); const githubEventName = process.env.GITHUB_EVENT_NAME || "unknown"; -const isPullRequest = githubEventName === "pull_request_target"; +const isPullRequest = + githubEventName === "pull_request_target" || + context.trigger?.issue?.isPullRequest === true; const explicitEventType = process.env.AUTOMATION_EVENT_TYPE; const eventType = explicitEventType || (isPullRequest ? "triage.pull_request" : "triage.issue"); +const dryRun = process.env.AUTOMATION_DRY_RUN === "true"; +const payloadContext = dryRun ? { ...context, test: true } : context; const payload = { eventType, - dryRun: process.env.AUTOMATION_DRY_RUN === "true", + dryRun, repo: "perfect-panel/frontend", source: "github-actions", trigger: { @@ -26,7 +30,7 @@ const payload = { eventName: githubEventName, eventAction: process.env.GITHUB_EVENT_ACTION || "", }, - context, + context: payloadContext, }; const rawBody = JSON.stringify(payload); diff --git a/scripts/triage-webhook.test.mjs b/scripts/triage-webhook.test.mjs index d904358..8db4045 100644 --- a/scripts/triage-webhook.test.mjs +++ b/scripts/triage-webhook.test.mjs @@ -133,6 +133,31 @@ test("sends pull_request_target events as triage.pull_request", async () => { } }); +test("routes issue comments attached to pull requests as triage.pull_request", async () => { + const server = await withServer((_record, response) => { + response.writeHead(202); + response.end("accepted"); + }); + + try { + const result = await runSender({ + cwd: makeWorkspace({ trigger: { issue: { isPullRequest: true } } }), + env: { + AUTOMATION_WEBHOOK_URL: server.url, + AUTOMATION_WEBHOOK_SECRET: "test-secret", + GITHUB_EVENT_NAME: "issue_comment", + GITHUB_EVENT_ACTION: "created", + }, + }); + assert.equal(result.code, 0, result.stderr); + const payload = JSON.parse(server.requests[0].body); + assert.equal(payload.eventType, "triage.pull_request"); + assert.equal(payload.trigger.kind, "pull_request"); + } finally { + await server.close(); + } +}); + test("supports explicit automation event type override for openapi adaptation without changing GitHub headers", async () => { const secret = "test-secret"; const server = await withServer((_record, response) => { @@ -159,6 +184,7 @@ test("supports explicit automation event type override for openapi adaptation wi const payload = JSON.parse(body); assert.equal(payload.eventType, "openapi.adapt"); assert.equal(payload.dryRun, true); + assert.equal(payload.context.test, true); assert.equal(payload.repo, "perfect-panel/frontend"); assert.equal(payload.trigger.kind, "push"); assert.equal(payload.trigger.eventName, "push");