From b0c2151ad82ffc5b6ccfcdaf31565e99ad60a16d Mon Sep 17 00:00:00 2001 From: tang <12411175+thanning@user.noreply.gitee.com> Date: Wed, 26 Aug 2026 19:02:12 +0800 Subject: [PATCH] feat: trigger workflows when pull request head updates --- src/projects/activity-summary.test.ts | 27 +++++++++++++++++++++++++++ src/projects/activity-summary.ts | 11 +++++++++++ src/triggers/github/classification.ts | 2 ++ src/triggers/github/match.test.ts | 12 ++++++++++++ src/triggers/github/provider.test.ts | 3 ++- 5 files changed, 54 insertions(+), 1 deletion(-) diff --git a/src/projects/activity-summary.test.ts b/src/projects/activity-summary.test.ts index 70c63abc..574917cd 100644 --- a/src/projects/activity-summary.test.ts +++ b/src/projects/activity-summary.test.ts @@ -77,6 +77,33 @@ describe("summarizeTrigger", () => { }); }); + it("summarizes a pull request head update", () => { + const summary = summarizeTrigger("github.pull_request_updated", { + id: "1", + type: "pull_request", + repo: "acme/widgets", + repositoryId: 1, + installationId: 1, + createdAt: new Date().toISOString(), + payload: { + action: "synchronize", + pull_request: { + number: 42, + title: "Address review feedback", + html_url: "https://github.com/acme/widgets/pull/42", + }, + sender: { login: "alice" }, + }, + }); + + assert.deepEqual(summary, { + provider: "github", + headline: "Pull request #42 updated: Address review feedback", + actor: "alice", + externalUrl: "https://github.com/acme/widgets/pull/42", + }); + }); + it("falls back to a generic headline when a valid envelope carries a malformed event payload", () => { const summary = summarizeTrigger("github.push", { id: "1", diff --git a/src/projects/activity-summary.ts b/src/projects/activity-summary.ts index 1d021cef..2a46dd6f 100644 --- a/src/projects/activity-summary.ts +++ b/src/projects/activity-summary.ts @@ -68,6 +68,17 @@ function summarizeGitHub(payload: unknown): TriggerSummary { externalUrl, }; } + if (classified.semanticEvent === "github.pull_request_updated") { + return { + provider: "github", + headline: + classified.item?.number === null || classified.item === null + ? "Pull request updated" + : `Pull request #${String(classified.item.number)} updated${classified.item.title === null ? "" : `: ${classified.item.title}`}`, + actor: classified.actor.length === 0 ? null : classified.actor, + externalUrl, + }; + } const { headline, actor } = summarizeGitHubEvent(event.data.type, event.data.payload); return { provider: "github", headline, actor, externalUrl }; } diff --git a/src/triggers/github/classification.ts b/src/triggers/github/classification.ts index e315676a..d751aa4c 100644 --- a/src/triggers/github/classification.ts +++ b/src/triggers/github/classification.ts @@ -10,6 +10,7 @@ import type { NormalizedGitHubEvent } from "../../auth/github-events.js"; export const GITHUB_SEMANTIC_TRIGGER_EVENT_NAMES = [ "github.issue_created", "github.pull_request_created", + "github.pull_request_updated", "github.issue_comment_created", "github.pull_request_comment_created", "github.issue_label_added", @@ -139,6 +140,7 @@ function issueSemanticEvent(action: string | undefined): GitHubSemanticEvent | u function pullRequestSemanticEvent(action: string | undefined): GitHubSemanticEvent | undefined { if (action === "opened") return "github.pull_request_created"; + if (action === "synchronize") return "github.pull_request_updated"; if (action === "labeled") return "github.pull_request_label_added"; return undefined; } diff --git a/src/triggers/github/match.test.ts b/src/triggers/github/match.test.ts index 9786114e..37722a2e 100644 --- a/src/triggers/github/match.test.ts +++ b/src/triggers/github/match.test.ts @@ -38,6 +38,18 @@ describe("GitHub trigger matching", () => { event: eventFor("pull_request", { action: "closed", pull_request: pullRequest() }), expected: 0, }, + { + acceptance: "2: pull_request_updated accepts synchronized pull requests", + on: "github.pull_request_updated", + event: eventFor("pull_request", { action: "synchronize", pull_request: pullRequest() }), + expected: 1, + }, + { + acceptance: "2: pull_request_updated does not match edited pull-request metadata", + on: "github.pull_request_updated", + event: eventFor("pull_request", { action: "edited", pull_request: pullRequest() }), + expected: 0, + }, { acceptance: "3: created issue comments are separate from pull-request comments", on: "github.issue_comment_created", diff --git a/src/triggers/github/provider.test.ts b/src/triggers/github/provider.test.ts index 5414eb58..085a0479 100644 --- a/src/triggers/github/provider.test.ts +++ b/src/triggers/github/provider.test.ts @@ -120,6 +120,7 @@ describe("GitHub Phase 1 trigger provider", () => { ["issues", "opened", "github.issue_created", 211], ["issues", "labeled", "github.issue_label_added", 211], ["pull_request", "opened", "github.pull_request_created", 312], + ["pull_request", "synchronize", "github.pull_request_updated", 312], ["pull_request", "labeled", "github.pull_request_label_added", 312], ] as const)("derives an item reaction target for %s %s", async (type, action, source, number) => { const configuration = githubConfiguration(); @@ -547,7 +548,7 @@ function createEvent( function createItemEvent( type: "issues" | "pull_request", - action: "opened" | "labeled", + action: "opened" | "synchronize" | "labeled", number: number, ): NormalizedGitHubEvent { return {