|
1 | 1 | #!/bin/bash |
2 | 2 | # wait-pr-checks.sh - Poll GitHub Actions status for a PR and exit on first failure or when all pass |
3 | 3 | # |
4 | | -# Usage: ./scripts/wait-pr-checks.sh <pr-number> [repo] |
5 | | -# pr-number: The PR number to check |
| 4 | +# Usage: ./scripts/wait-pr-checks.sh [pr-number] [repo] |
| 5 | +# pr-number: Optional PR number (auto-detects from current branch if not provided) |
6 | 6 | # repo: Optional repository in format owner/repo (defaults to coder/httpjail) |
7 | 7 | # |
8 | 8 | # Exit codes: |
9 | 9 | # 0 - All checks passed |
10 | 10 | # 1 - A check failed |
11 | | -# 2 - Invalid arguments |
| 11 | +# 2 - Invalid arguments or no PR found |
12 | 12 | # |
13 | 13 | # Requires: gh, jq |
14 | 14 |
|
15 | 15 | set -euo pipefail |
16 | 16 |
|
17 | | -# Parse arguments |
18 | | -if [ $# -lt 1 ]; then |
19 | | - echo "Usage: $0 <pr-number> [repo]" >&2 |
20 | | - echo "Example: $0 47" >&2 |
21 | | - echo "Example: $0 47 coder/httpjail" >&2 |
22 | | - exit 2 |
| 17 | +# Parse arguments and auto-detect PR if needed |
| 18 | +if [ $# -eq 0 ]; then |
| 19 | + # Auto-detect PR from current branch |
| 20 | + echo "Auto-detecting PR from current branch..." >&2 |
| 21 | + CURRENT_BRANCH=$(git branch --show-current) |
| 22 | + |
| 23 | + # Try to find PR for current branch |
| 24 | + PR_INFO=$(gh pr list --head "${CURRENT_BRANCH}" --json number,headRefName --limit 1 2>/dev/null || echo "[]") |
| 25 | + PR_NUMBER=$(echo "$PR_INFO" | jq -r '.[0].number // empty') |
| 26 | + |
| 27 | + if [ -z "$PR_NUMBER" ]; then |
| 28 | + echo "Error: No PR found for branch '${CURRENT_BRANCH}'" >&2 |
| 29 | + echo "" >&2 |
| 30 | + echo "Usage: $0 [pr-number] [repo]" >&2 |
| 31 | + echo " When called without arguments, auto-detects PR from current branch" >&2 |
| 32 | + echo " Examples:" >&2 |
| 33 | + echo " $0 # Auto-detect PR from current branch" >&2 |
| 34 | + echo " $0 47 # Monitor PR #47" >&2 |
| 35 | + echo " $0 47 coder/httpjail # Monitor PR #47 in specific repo" >&2 |
| 36 | + exit 2 |
| 37 | + fi |
| 38 | + |
| 39 | + # Auto-detect repo from git remote |
| 40 | + REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner 2>/dev/null || echo "coder/httpjail") |
| 41 | + echo "Found PR #${PR_NUMBER} for branch '${CURRENT_BRANCH}' in ${REPO}" >&2 |
| 42 | +elif [ $# -eq 1 ]; then |
| 43 | + PR_NUMBER="$1" |
| 44 | + REPO="coder/httpjail" |
| 45 | +else |
| 46 | + PR_NUMBER="$1" |
| 47 | + REPO="$2" |
23 | 48 | fi |
24 | 49 |
|
25 | | -PR_NUMBER="$1" |
26 | | -REPO="${2:-coder/httpjail}" |
27 | | - |
28 | 50 | # Check for required tools |
29 | 51 | if ! command -v jq &> /dev/null; then |
30 | 52 | echo "Error: jq is required but not installed" >&2 |
@@ -71,7 +93,43 @@ while true; do |
71 | 93 | if [ $failed_count -gt 0 ]; then |
72 | 94 | echo -e "\n\n${RED}❌ The following check(s) failed:${NC}" |
73 | 95 | echo "$json_output" | jq -r '.[] | select(.state == "FAILURE" or .state == "ERROR") | " - \(.name)"' |
74 | | - echo -e "\nView details at: https://github.com/${REPO}/pull/${PR_NUMBER}/checks" |
| 96 | + |
| 97 | + # Try to fetch logs for the first failed check |
| 98 | + echo -e "\n${YELLOW}Fetching logs for first failed check...${NC}\n" |
| 99 | + |
| 100 | + # Get the first failed check details |
| 101 | + first_failed=$(echo "$json_output" | jq -r '.[] | select(.state == "FAILURE" or .state == "ERROR") | "\(.name)|\(.link)"' | head -1) |
| 102 | + |
| 103 | + if [ -n "$first_failed" ]; then |
| 104 | + IFS='|' read -r check_name check_link <<< "$first_failed" |
| 105 | + echo -e "${YELLOW}=== Logs for: ${check_name} ===${NC}" |
| 106 | + |
| 107 | + # Extract run ID and job ID from the link |
| 108 | + if [[ "$check_link" =~ /runs/([0-9]+)/job/([0-9]+) ]]; then |
| 109 | + run_id="${BASH_REMATCH[1]}" |
| 110 | + job_id="${BASH_REMATCH[2]}" |
| 111 | + |
| 112 | + # Use direct API call to get job logs (more reliable than gh run view) |
| 113 | + if job_logs=$(gh api "repos/${REPO}/actions/jobs/${job_id}/logs" --paginate 2>&1); then |
| 114 | + # Look for error patterns in the logs |
| 115 | + error_logs=$(echo "$job_logs" | grep -E "(error:|Error:|ERROR:|warning:|clippy::|failed|Failed|##\[error\])" | head -30) |
| 116 | + if [ -n "$error_logs" ]; then |
| 117 | + echo "$error_logs" |
| 118 | + else |
| 119 | + # If no error patterns found, show last 100 lines which often contain the failure |
| 120 | + echo "$job_logs" | tail -100 |
| 121 | + fi |
| 122 | + else |
| 123 | + # If logs aren't ready, try to at least show the conclusion |
| 124 | + echo "Full logs not available yet. Check: ${check_link}" |
| 125 | + fi |
| 126 | + else |
| 127 | + echo "Could not parse check link: ${check_link}" |
| 128 | + fi |
| 129 | + echo "" |
| 130 | + fi |
| 131 | + |
| 132 | + echo -e "\nView full details at: https://github.com/${REPO}/pull/${PR_NUMBER}/checks" |
75 | 133 | exit 1 |
76 | 134 | fi |
77 | 135 |
|
|
0 commit comments