Skip to content

Commit 5a14e8e

Browse files
antonisclaude
andauthored
ci: Cancel in-progress CI jobs when a PR is closed or merged (#5725)
* ci: Cancel in-progress CI jobs when a PR is closed or merged The existing concurrency groups use `github.ref` which for PRs resolves to `refs/pull/<number>/merge`. When a PR is merged, the push to main creates a different concurrency group (`refs/heads/main`), so the still-running PR workflows are never cancelled, wasting CI resources. This adds a new workflow that triggers on `pull_request: closed` (fired on both merge and manual close) and cancels all in-progress and queued workflow runs for the PR's head branch via the GitHub API. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(ci): Handle cancel errors gracefully in PR cleanup workflow Wrap the cancelWorkflowRun call in try/catch so that if a run completes between the list and cancel calls, the error doesn't abort cancellation of the remaining runs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent d4b0134 commit 5a14e8e

File tree

1 file changed

+51
-0
lines changed

1 file changed

+51
-0
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
name: Cancel PR Workflows
2+
3+
on:
4+
pull_request:
5+
types: [closed]
6+
7+
jobs:
8+
cancel:
9+
name: Cancel In-Progress Workflows
10+
runs-on: ubuntu-latest
11+
steps:
12+
- name: Cancel in-progress workflow runs
13+
uses: actions/github-script@v7
14+
with:
15+
script: |
16+
const { owner, repo } = context.repo;
17+
const branch = context.payload.pull_request.head.ref;
18+
19+
const workflows = await github.rest.actions.listWorkflowRunsForRepo({
20+
owner,
21+
repo,
22+
branch,
23+
status: 'in_progress',
24+
});
25+
26+
const waitingWorkflows = await github.rest.actions.listWorkflowRunsForRepo({
27+
owner,
28+
repo,
29+
branch,
30+
status: 'queued',
31+
});
32+
33+
const runs = [...workflows.data.workflow_runs, ...waitingWorkflows.data.workflow_runs];
34+
35+
for (const run of runs) {
36+
if (run.id === context.runId) {
37+
continue;
38+
}
39+
try {
40+
console.log(`Cancelling run ${run.id} (${run.name})`);
41+
await github.rest.actions.cancelWorkflowRun({
42+
owner,
43+
repo,
44+
run_id: run.id,
45+
});
46+
} catch (error) {
47+
console.log(`Failed to cancel run ${run.id}: ${error.message}`);
48+
}
49+
}
50+
51+
console.log(`Cancelled ${runs.length > 1 ? runs.length - 1 : 0} workflow run(s) for branch ${branch}`);

0 commit comments

Comments
 (0)