fix(CI): cancel a PR's CI when the PR closes (#26719)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: CodeRabbit <coderabbitai[bot]@users.noreply.github.com>
This commit is contained in:
sudlud
2026-07-21 14:59:34 +02:00
committed by GitHub
parent 86e8abce1a
commit db8a92b8b7
7 changed files with 66 additions and 12 deletions

View File

@@ -0,0 +1,48 @@
name: cancel-pr-runs-on-close
on:
# pull_request_target, not pull_request: for a PR from a fork the GITHUB_TOKEN
# of a pull_request run is read-only, so the cancel would 403. This workflow
# never checks out or runs PR code, so the elevated token is not exposed to it.
pull_request_target:
types:
- closed
permissions:
actions: write
jobs:
cancel:
runs-on: ubuntu-latest
name: cancel CI still running for the closed PR
if: github.repository == 'azerothcore/azerothcore-wotlk'
steps:
- name: Cancel workflow runs for this PR
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_REPO: ${{ github.repository }}
PR_SHA: ${{ github.event.pull_request.head.sha }}
PR_REPO: ${{ github.event.pull_request.head.repo.full_name }}
run: |
set -euo pipefail
# head_sha alone would let anyone cancel another PR's CI: push that
# PR's head commit to your own fork, open a PR and close it, and every
# run for the commit matches. So the run must also come from this PR's
# head repository. `gh run list` exposes neither head_repository nor
# the (fork-empty) pull_requests field, hence the raw API call.
gh api "repos/${GH_REPO}/actions/runs?event=pull_request&head_sha=${PR_SHA}&per_page=100" \
--jq '.workflow_runs[]
| select(.head_repository.full_name == env.PR_REPO and .status != "completed")
| .id' \
| while read -r id; do
# gh has no bulk cancel. A run that finishes between the listing
# and the cancel returns 409, which is not worth failing over.
if ! err=$(gh run cancel "$id" 2>&1); then
if echo "$err" | grep -Fq "HTTP 409"; then
echo "::warning::run $id was already finished"
else
echo "::error::Failed to cancel run $id: $err"
exit 1
fi
fi
done

View File

@@ -20,8 +20,9 @@ concurrency:
# #
# - PRs use `refs/pull/<PR_NUMBER>/merge`, so new commits cancel older # - PRs use `refs/pull/<PR_NUMBER>/merge`, so new commits cancel older
# in-progress runs for the same PR. # in-progress runs for the same PR.
# - When a PR is merged, a push to the target branch starts a new group, # - A merge does NOT cancel the PR's own runs: this group is keyed on
# canceling any still-running PR CI. # refs/pull/<N>/merge and the master push on refs/heads/master, so they
# never share a group. See the cancel-pr-runs-on-close workflow.
# - Branch pushes are isolated by ref. # - Branch pushes are isolated by ref.
group: ${{ github.workflow }}-${{ github.ref }} group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true cancel-in-progress: true

View File

@@ -20,8 +20,9 @@ concurrency:
# #
# - PRs use `refs/pull/<PR_NUMBER>/merge`, so new commits cancel older # - PRs use `refs/pull/<PR_NUMBER>/merge`, so new commits cancel older
# in-progress runs for the same PR. # in-progress runs for the same PR.
# - When a PR is merged, a push to the target branch starts a new group, # - A merge does NOT cancel the PR's own runs: this group is keyed on
# canceling any still-running PR CI. # refs/pull/<N>/merge and the master push on refs/heads/master, so they
# never share a group. See the cancel-pr-runs-on-close workflow.
# - Branch pushes are isolated by ref. # - Branch pushes are isolated by ref.
group: ${{ github.workflow }}-${{ github.ref }} group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true cancel-in-progress: true

View File

@@ -28,8 +28,9 @@ concurrency:
# #
# - PRs use `refs/pull/<PR_NUMBER>/merge`, so new commits cancel older # - PRs use `refs/pull/<PR_NUMBER>/merge`, so new commits cancel older
# in-progress runs for the same PR. # in-progress runs for the same PR.
# - When a PR is merged, a push to the target branch starts a new group, # - A merge does NOT cancel the PR's own runs: this group is keyed on
# canceling any still-running PR CI. # refs/pull/<N>/merge and the master push on refs/heads/master, so they
# never share a group. See the cancel-pr-runs-on-close workflow.
# - Branch pushes are isolated by ref. # - Branch pushes are isolated by ref.
group: ${{ github.workflow }}-${{ github.ref }} group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true cancel-in-progress: true

View File

@@ -13,8 +13,9 @@ concurrency:
# #
# - PRs use `refs/pull/<PR_NUMBER>/merge`, so new commits cancel older # - PRs use `refs/pull/<PR_NUMBER>/merge`, so new commits cancel older
# in-progress runs for the same PR. # in-progress runs for the same PR.
# - When a PR is merged, a push to the target branch starts a new group, # - A merge does NOT cancel the PR's own runs: this group is keyed on
# canceling any still-running PR CI. # refs/pull/<N>/merge and the master push on refs/heads/master, so they
# never share a group. See the cancel-pr-runs-on-close workflow.
# - Branch pushes are isolated by ref. # - Branch pushes are isolated by ref.
group: ${{ github.workflow }}-${{ github.ref }} group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true cancel-in-progress: true

View File

@@ -13,8 +13,9 @@ concurrency:
# #
# - PRs use `refs/pull/<PR_NUMBER>/merge`, so new commits cancel older # - PRs use `refs/pull/<PR_NUMBER>/merge`, so new commits cancel older
# in-progress runs for the same PR. # in-progress runs for the same PR.
# - When a PR is merged, a push to the target branch starts a new group, # - A merge does NOT cancel the PR's own runs: this group is keyed on
# canceling any still-running PR CI. # refs/pull/<N>/merge and the master push on refs/heads/master, so they
# never share a group. See the cancel-pr-runs-on-close workflow.
# - Branch pushes are isolated by ref. # - Branch pushes are isolated by ref.
group: ${{ github.workflow }}-${{ github.ref }} group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true cancel-in-progress: true

View File

@@ -13,8 +13,9 @@ concurrency:
# #
# - PRs use `refs/pull/<PR_NUMBER>/merge`, so new commits cancel older # - PRs use `refs/pull/<PR_NUMBER>/merge`, so new commits cancel older
# in-progress runs for the same PR. # in-progress runs for the same PR.
# - When a PR is merged, a push to the target branch starts a new group, # - A merge does NOT cancel the PR's own runs: this group is keyed on
# canceling any still-running PR CI. # refs/pull/<N>/merge and the master push on refs/heads/master, so they
# never share a group. See the cancel-pr-runs-on-close workflow.
# - Branch pushes are isolated by ref. # - Branch pushes are isolated by ref.
group: ${{ github.workflow }}-${{ github.ref }} group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true cancel-in-progress: true