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"