List Active Runs #36
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: List Active Runs | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| workflows: | |
| description: 'Space-separated list of workflow filenames to check' | |
| required: false | |
| type: string | |
| default: 'pr-test.yml' | |
| permissions: | |
| actions: read | |
| contents: read | |
| pull-requests: read | |
| jobs: | |
| list-active-runs: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Install GitHub CLI | |
| run: sudo apt-get install -y gh jq | |
| - name: List active runs grouped by PR | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| REPO: ${{ github.repository }} | |
| WORKFLOWS: ${{ github.event.inputs.workflows || 'pr-test.yml' }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| echo "=========================================" | |
| echo "🔍 Active Workflow Runs Report" | |
| echo "=========================================" | |
| echo "" | |
| # Get all workflows or specific ones | |
| read -r -a workflow_files <<< "${WORKFLOWS}" | |
| echo "📋 Checking specified workflows: ${WORKFLOWS}" | |
| echo "" | |
| # Create a temporary file to store PR data | |
| pr_data_file=$(mktemp) | |
| # Process each workflow | |
| for workflow_file in ${workflow_files[@]}; do | |
| echo "Scanning workflow: $workflow_file" | |
| # Get all active runs (queued, waiting, in_progress) | |
| active_runs=$(gh run list \ | |
| --repo "$REPO" \ | |
| --workflow "$workflow_file" \ | |
| --json databaseId,status,event,headBranch,createdAt,updatedAt,headSha,number,attempt \ | |
| --limit 500 \ | |
| | jq -c '.[] | select(.status=="queued" or .status=="waiting" or .status=="in_progress")') | |
| if [ -z "$active_runs" ]; then | |
| continue | |
| fi | |
| # Process each run | |
| echo "$active_runs" | while read -r run; do | |
| run_id=$(echo "$run" | jq -r '.databaseId') | |
| run_status=$(echo "$run" | jq -r '.status') | |
| run_event=$(echo "$run" | jq -r '.event') | |
| created_at=$(echo "$run" | jq -r '.createdAt') | |
| head_sha=$(echo "$run" | jq -r '.headSha') | |
| run_number=$(echo "$run" | jq -r '.number') | |
| run_attempt=$(echo "$run" | jq -r '.attempt // 1') | |
| # Get detailed run information including jobs | |
| run_details=$(gh api "repos/$REPO/actions/runs/$run_id" 2>/dev/null || true) | |
| if [ -z "$run_details" ]; then | |
| continue | |
| fi | |
| 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 | |
| continue | |
| fi | |
| # Find PR number (may be empty for non-PR runs) | |
| pr_number=$(gh api "repos/$REPO/pulls?state=open&head=${head_owner}:${head_branch}" \ | |
| --jq '.[0].number // empty' 2>/dev/null || true) | |
| if [ -z "$pr_number" ]; then | |
| pr_number="NO_PR" | |
| fi | |
| # Get jobs for this run (with pagination to avoid missing jobs) | |
| jobs=$(gh api "repos/$REPO/actions/runs/$run_id/jobs" --paginate --jq '.jobs[]' | jq -s '.') | |
| running_jobs=$(echo "$jobs" | jq '[.[] | select(.status=="in_progress")] | length') | |
| queued_jobs=$(echo "$jobs" | jq '[.[] | select(.status=="queued" or .status=="waiting")] | length') | |
| # Get runner info for running jobs | |
| runners=$(echo "$jobs" | jq -r '.[] | select(.status=="in_progress") | .runner_name // "N/A"' | paste -sd "," -) | |
| # Calculate queue time | |
| current_time=$(date -u +%s) | |
| created_time=$(date -u -d "$created_at" +%s 2>/dev/null || echo "$current_time") | |
| queue_time=$((current_time - created_time)) | |
| queue_minutes=$((queue_time / 60)) | |
| # Store data in temporary file (unified format with event and branch) | |
| echo "$pr_number|$workflow_file|$run_id|$run_status|$running_jobs|$queued_jobs|$runners|$queue_minutes|$created_at|$head_sha|$run_attempt|$run_event|$head_branch" >> "$pr_data_file" | |
| done | |
| done | |
| echo "" | |
| echo "=========================================" | |
| echo "📊 Active Runs Summary" | |
| echo "=========================================" | |
| echo "" | |
| if [ ! -s "$pr_data_file" ]; then | |
| echo "✅ No active runs found" | |
| rm -f "$pr_data_file" | |
| exit 0 | |
| fi | |
| # Get unique PR numbers (exclude NO_PR entries) | |
| pr_numbers=$(cut -d'|' -f1 < "$pr_data_file" | grep -v '^NO_PR$' | sort -u || true) | |
| # Separate high priority and normal PRs | |
| high_priority_prs=() | |
| normal_prs=() | |
| for pr_num in $pr_numbers; do | |
| labels=$(gh pr view "$pr_num" --repo "$REPO" --json labels \ | |
| | jq -r '.labels[].name' 2>/dev/null || true) | |
| if echo "$labels" | grep -Fxq "high priority"; then | |
| high_priority_prs+=($pr_num) | |
| else | |
| normal_prs+=($pr_num) | |
| fi | |
| done | |
| # Combine: high priority first, then normal | |
| sorted_pr_numbers=("${high_priority_prs[@]}" "${normal_prs[@]}") | |
| pr_count=0 | |
| total_running=0 | |
| total_queued=0 | |
| for pr_num in "${sorted_pr_numbers[@]}"; do | |
| pr_count=$((pr_count + 1)) | |
| # Get PR details | |
| pr_info=$(gh pr view "$pr_num" --repo "$REPO" --json title,author,labels,url 2>/dev/null || true) | |
| if [ -z "$pr_info" ]; then | |
| continue | |
| fi | |
| pr_title=$(echo "$pr_info" | jq -r '.title') | |
| pr_author=$(echo "$pr_info" | jq -r '.author.login') | |
| pr_url=$(echo "$pr_info" | jq -r '.url') | |
| pr_labels=$(echo "$pr_info" | jq -r '.labels[].name' | paste -sd ", " -) | |
| if [ -z "$pr_labels" ]; then | |
| pr_labels="(no labels)" | |
| fi | |
| # Add priority indicator | |
| priority_indicator="" | |
| if echo "$pr_labels" | grep -q "high priority"; then | |
| priority_indicator="🔴 [HIGH PRIORITY] " | |
| fi | |
| echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" | |
| echo "🔗 ${priority_indicator}PR #$pr_num: $pr_title" | |
| echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" | |
| echo "👤 Author: $pr_author" | |
| echo "🏷️ Labels: $pr_labels" | |
| echo "🔗 URL: $pr_url" | |
| echo "" | |
| # Get all runs for this PR | |
| pr_runs=$(grep "^$pr_num|" "$pr_data_file") | |
| pr_running_total=0 | |
| pr_queued_total=0 | |
| echo "$pr_runs" | while read -r line; do | |
| workflow=$(echo "$line" | cut -d'|' -f2) | |
| run_id=$(echo "$line" | cut -d'|' -f3) | |
| status=$(echo "$line" | cut -d'|' -f4) | |
| running=$(echo "$line" | cut -d'|' -f5) | |
| queued=$(echo "$line" | cut -d'|' -f6) | |
| runners=$(echo "$line" | cut -d'|' -f7) | |
| queue_min=$(echo "$line" | cut -d'|' -f8) | |
| created=$(echo "$line" | cut -d'|' -f9) | |
| attempt=$(echo "$line" | cut -d'|' -f11) | |
| pr_running_total=$((pr_running_total + running)) | |
| pr_queued_total=$((pr_queued_total + queued)) | |
| run_url="https://github.com/$REPO/actions/runs/$run_id" | |
| # Calculate retry count for this specific run | |
| retry_count=$((attempt - 1)) | |
| # Show retry indicator | |
| retry_indicator="" | |
| if [ "$retry_count" -gt 0 ]; then | |
| retry_indicator=" 🔄 Retry #$retry_count" | |
| fi | |
| echo " 📦 Workflow: $workflow (Run #$run_id)$retry_indicator" | |
| echo " Status: $status" | |
| echo " 🟢 Running jobs: $running" | |
| echo " 🟡 Queued jobs: $queued" | |
| if [ "$running" -gt 0 ] && [ "$runners" != "" ]; then | |
| echo " 🖥️ Runners: $runners" | |
| fi | |
| if [ "$queue_min" -gt 0 ]; then | |
| echo " ⏱️ Queue time: ${queue_min} minutes" | |
| fi | |
| echo " 🔗 Run URL: $run_url" | |
| echo "" | |
| done | |
| # Summary for this PR | |
| pr_running_total=$(grep "^$pr_num|" "$pr_data_file" | cut -d'|' -f5 | awk '{sum+=$1} END {print sum+0}') | |
| pr_queued_total=$(grep "^$pr_num|" "$pr_data_file" | cut -d'|' -f6 | awk '{sum+=$1} END {print sum+0}') | |
| total_running=$((total_running + pr_running_total)) | |
| total_queued=$((total_queued + pr_queued_total)) | |
| echo " 📊 PR Total: $pr_running_total running, $pr_queued_total queued" | |
| echo "" | |
| done | |
| # --- Non-PR Runs Section --- | |
| non_pr_runs=$(grep '^NO_PR|' "$pr_data_file" 2>/dev/null || true) | |
| non_pr_running=0 | |
| non_pr_queued=0 | |
| if [ -n "$non_pr_runs" ]; then | |
| echo "=========================================" | |
| echo "📦 Non-PR Runs (manual / scheduled / other)" | |
| echo "=========================================" | |
| echo "" | |
| echo "$non_pr_runs" | while read -r line; do | |
| workflow=$(echo "$line" | cut -d'|' -f2) | |
| run_id=$(echo "$line" | cut -d'|' -f3) | |
| status=$(echo "$line" | cut -d'|' -f4) | |
| running=$(echo "$line" | cut -d'|' -f5) | |
| queued=$(echo "$line" | cut -d'|' -f6) | |
| runners=$(echo "$line" | cut -d'|' -f7) | |
| queue_min=$(echo "$line" | cut -d'|' -f8) | |
| created=$(echo "$line" | cut -d'|' -f9) | |
| attempt=$(echo "$line" | cut -d'|' -f11) | |
| event=$(echo "$line" | cut -d'|' -f12) | |
| branch=$(echo "$line" | cut -d'|' -f13) | |
| run_url="https://github.com/$REPO/actions/runs/$run_id" | |
| retry_count=$((attempt - 1)) | |
| retry_indicator="" | |
| if [ "$retry_count" -gt 0 ]; then | |
| retry_indicator=" 🔄 Retry #$retry_count" | |
| fi | |
| echo " 📦 Workflow: $workflow (Run #$run_id)$retry_indicator" | |
| echo " Event: $event" | |
| echo " Branch: $branch" | |
| echo " Status: $status" | |
| echo " 🟢 Running jobs: $running" | |
| echo " 🟡 Queued jobs: $queued" | |
| if [ "$running" -gt 0 ] && [ "$runners" != "" ]; then | |
| echo " 🖥️ Runners: $runners" | |
| fi | |
| if [ "$queue_min" -gt 0 ]; then | |
| echo " ⏱️ Queue time: ${queue_min} minutes" | |
| fi | |
| echo " 🔗 Run URL: $run_url" | |
| echo "" | |
| done | |
| non_pr_running=$(echo "$non_pr_runs" | cut -d'|' -f5 | awk '{sum+=$1} END {print sum+0}') | |
| non_pr_queued=$(echo "$non_pr_runs" | cut -d'|' -f6 | awk '{sum+=$1} END {print sum+0}') | |
| non_pr_count=$(echo "$non_pr_runs" | wc -l | tr -d ' ') | |
| total_running=$((total_running + non_pr_running)) | |
| total_queued=$((total_queued + non_pr_queued)) | |
| echo " 📊 Non-PR Total: $non_pr_running running, $non_pr_queued queued" | |
| echo "" | |
| fi | |
| # Overall summary | |
| echo "=========================================" | |
| echo "📈 Overall Summary" | |
| echo "=========================================" | |
| echo "Total PRs with active runs: $pr_count" | |
| echo "Total non-PR active runs: ${non_pr_count:-0}" | |
| echo "Total running jobs: $total_running" | |
| echo "Total queued jobs: $total_queued" | |
| echo "=========================================" | |
| # Cleanup | |
| rm -f "$pr_data_file" |