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