Adjust the cancel PR workflows for better preemption. (#16749)

This commit is contained in:
Liangsheng Yin
2026-01-09 03:25:41 +08:00
committed by GitHub
parent 49305fa1c1
commit 064ae3419e
3 changed files with 141 additions and 96 deletions

View File

@@ -1,48 +0,0 @@
name: Cancel All PR Test Runs (Pendings Only)
on:
workflow_dispatch:
inputs:
workflows:
description: 'Space-separated list of workflow filenames to cancel'
required: true
type: string
default: 'pr-test.yml'
permissions:
actions: write # Needed to cancel runs
contents: read # Needed to read repo info
jobs:
cancel-pending-pr-test:
runs-on: ubuntu-latest
steps:
- name: Install GitHub CLI
run: sudo apt-get install -y gh jq
- name: Cancel all pending/waiting PR-associated runs for specified workflows
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPO: ${{ github.repository }}
run: |
# Read the space-separated string from the input into a bash array
WORKFLOW_FILES=(${{ github.event.inputs.workflows }})
echo "Targeting ${#WORKFLOW_FILES[@]} workflow(s): ${{ github.event.inputs.workflows }}"
for workflow_file in "${WORKFLOW_FILES[@]}"; do
echo "--- Checking workflow: $workflow_file ---"
gh run list \
--repo "$REPO" \
--workflow "$workflow_file" \
--json databaseId,status,event \
--limit 1000 \
| jq -r '.[] | select((.status=="queued" or .status=="waiting") and .event=="pull_request") | .databaseId' \
| while read run_id; do
echo "Attempting to cancel run ID: $run_id for workflow: $workflow_file"
# The "|| echo ..." part prevents the script from crashing if cancellation fails
gh run cancel "$run_id" --repo "$REPO" || echo "⚠️ Could not cancel run $run_id (it may have already completed). Continuing..."
done
done

View File

@@ -1,48 +0,0 @@
name: Cancel All PR Test Runs
on:
workflow_dispatch:
inputs:
workflows:
description: 'Space-separated list of workflow filenames to cancel'
required: true
type: string
default: 'pr-test.yml'
permissions:
actions: write # Needed to cancel runs
contents: read # Needed to read repo info
jobs:
cancel-pr-test:
runs-on: ubuntu-latest
steps:
- name: Install GitHub CLI
run: sudo apt-get install -y gh jq
- name: Cancel all PR-associated runs for specified workflows
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPO: ${{ github.repository }}
run: |
# Read the space-separated string from the input into a bash array
WORKFLOW_FILES=(${{ github.event.inputs.workflows }})
echo "Targeting ${#WORKFLOW_FILES[@]} workflow(s): ${{ github.event.inputs.workflows }}"
for workflow_file in "${WORKFLOW_FILES[@]}"; do
echo "--- Checking workflow: $workflow_file ---"
gh run list \
--repo "$REPO" \
--workflow "$workflow_file" \
--json databaseId,status,event \
--limit 1000 \
| jq -r '.[] | select((.status=="in_progress" or .status=="queued" or .status=="waiting") and .event=="pull_request") | .databaseId' \
| while read run_id; do
echo "Attempting to cancel run ID: $run_id for workflow: $workflow_file"
# The "|| echo ..." part prevents the script from crashing if cancellation fails
gh run cancel "$run_id" --repo "$REPO" || echo "⚠️ Could not cancel run $run_id (it may have already completed). Continuing..."
done
done

View File

@@ -0,0 +1,141 @@
name: Cancel Unfinished PR Tests
on:
workflow_dispatch:
inputs:
workflows:
description: 'Space-separated list of workflow filenames to cancel'
required: true
type: string
default: 'pr-test.yml'
permissions:
actions: write # Needed to cancel runs
contents: read # Needed to read repo info
pull-requests: read # needed for gh pr view (labels)
jobs:
cancel-pending-pr-test:
runs-on: ubuntu-latest
steps:
- name: Install GitHub CLI
run: sudo apt-get install -y gh jq
- name: Cancel unfinished PR-associated runs (skip high-priority PRs)
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPO: ${{ github.repository }}
WORKFLOWS: ${{ github.event.inputs.workflows || 'pr-test.yml' }}
shell: bash
run: |
set -euo pipefail
# Read the space-separated string from the input into a bash array
read -r -a WORKFLOW_FILES <<< "${WORKFLOWS}"
echo "Targeting ${#WORKFLOW_FILES[@]} workflow(s): ${WORKFLOWS}"
echo ""
for workflow_file in "${WORKFLOW_FILES[@]}"; do
echo "========================================="
echo "Workflow: $workflow_file"
echo "========================================="
# Get all unfinished runs
all_runs=$(gh run list \
--repo "$REPO" \
--workflow "$workflow_file" \
--json databaseId,status,event,url,createdAt \
--limit 1000 \
| jq -c '.[] | select(.status=="queued" or .status=="waiting" or .status=="in_progress")')
if [ -z "$all_runs" ]; then
echo "✅ No unfinished runs found"
echo ""
continue
fi
# Count runs by event type
total_runs=$(echo "$all_runs" | wc -l)
pr_runs=$(echo "$all_runs" | jq -s '[.[] | select(.event=="pull_request")] | length')
other_runs=$(echo "$all_runs" | jq -s '[.[] | select(.event!="pull_request")] | length')
echo "📊 Summary: $total_runs unfinished runs ($pr_runs PR-related, $other_runs other)"
echo ""
# Process non-PR runs first
if [ "$other_runs" -gt 0 ]; then
echo "--- Non-PR Runs ---"
echo "$all_runs" | jq -c 'select(.event!="pull_request")' | while read -r run; do
run_url=$(echo "$run" | jq -r '.url')
run_event=$(echo "$run" | jq -r '.event')
run_status=$(echo "$run" | jq -r '.status')
echo " • $run_event ($run_status): $run_url"
done
echo ""
fi
# Process PR runs
if [ "$pr_runs" -gt 0 ]; then
echo "--- PR Runs (checking for cancellation) ---"
echo "$all_runs" | jq -c 'select(.event=="pull_request")' | while read -r run; do
run_id=$(echo "$run" | jq -r '.databaseId')
run_url=$(echo "$run" | jq -r '.url')
run_status=$(echo "$run" | jq -r '.status')
echo ""
echo "Run ($run_status): $run_url"
# Fetch full run details to get head repository and branch info
run_details=$(gh api -H "Accept: application/vnd.github+json" \
"repos/$REPO/actions/runs/$run_id" 2>/dev/null || true)
if [ -z "$run_details" ]; then
echo " ⚠️ Could not fetch run details, skipping"
continue
fi
# Get head owner and branch (works for both fork and non-fork PRs)
head_owner=$(echo "$run_details" | jq -r '.head_repository.owner.login // empty')
head_branch=$(echo "$run_details" | jq -r '.head_branch // empty')
if [ -z "$head_owner" ] || [ -z "$head_branch" ]; then
echo " ⚠️ Missing head info, skipping"
continue
fi
echo " Branch: ${head_owner}:${head_branch}"
# Find PR by searching with head=owner:branch
pr_number=$(gh api -H "Accept: application/vnd.github+json" \
"repos/$REPO/pulls?state=open&head=${head_owner}:${head_branch}" \
--jq '.[0].number // empty' 2>/dev/null || true)
if [ -z "$pr_number" ]; then
echo " ⚠️ No open PR found, skipping"
continue
fi
pr_url="https://github.com/$REPO/pull/$pr_number"
echo " PR: $pr_url"
# Check for high priority label
labels=$(gh pr view "$pr_number" --repo "$REPO" --json labels \
| jq -r '.labels[].name' 2>/dev/null || true)
if echo "$labels" | grep -Fxq "high priority"; then
echo " 🛑 Skipping (high priority label)"
continue
fi
echo " 🚫 Cancelling..."
gh run cancel "$run_id" --repo "$REPO" || echo " ⚠️ Cancellation failed"
done
fi
echo ""
done
echo "========================================="
echo "✅ Processing complete"
echo "========================================="