Improve CI workflow polling: skip when no workflow files, lock onto run by ID, prefer push events
This commit is contained in:
152
gp
152
gp
@@ -543,6 +543,11 @@ wait_for_workflow() {
|
|||||||
return 0 # silently skip if not a Gitea remote or no token
|
return 0 # silently skip if not a Gitea remote or no token
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Skip if no workflow files exist in the repo
|
||||||
|
if ! ls .gitea/workflows/*.yml .gitea/workflows/*.yaml .github/workflows/*.yml .github/workflows/*.yaml 2>/dev/null | grep -q .; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
local spinner_chars='⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏'
|
local spinner_chars='⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏'
|
||||||
local spin_idx=0
|
local spin_idx=0
|
||||||
local poll_interval=3
|
local poll_interval=3
|
||||||
@@ -581,44 +586,58 @@ wait_for_workflow() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Poll API for the run
|
# Poll API for the run
|
||||||
local response
|
local run_info=""
|
||||||
response=$(curl -sf "${GITEA_API_BASE}/actions/runs?limit=5" -H "Authorization: ${GITEA_AUTH_HEADER}" 2>/dev/null) || true
|
if [ "$found" = true ] && [ -n "$run_id" ]; then
|
||||||
|
# Already locked onto a run - query it directly by ID
|
||||||
if [ -n "$response" ]; then
|
run_info=$(curl -sf "${GITEA_API_BASE}/actions/runs/${run_id}" -H "Authorization: ${GITEA_AUTH_HEADER}" 2>/dev/null \
|
||||||
# Find the run matching our commit SHA
|
| python3 -c "
|
||||||
local run_info
|
import json, sys
|
||||||
run_info=$(echo "$response" | python3 -c "
|
r = json.load(sys.stdin)
|
||||||
|
print(r['id'], r['status'], r.get('conclusion',''), r.get('html_url',''))
|
||||||
|
" 2>/dev/null) || true
|
||||||
|
else
|
||||||
|
# Search for a run matching our commit SHA (prefer push events)
|
||||||
|
local response
|
||||||
|
response=$(curl -sf "${GITEA_API_BASE}/actions/runs?limit=20" -H "Authorization: ${GITEA_AUTH_HEADER}" 2>/dev/null) || true
|
||||||
|
if [ -n "$response" ]; then
|
||||||
|
run_info=$(echo "$response" | python3 -c "
|
||||||
import json, sys
|
import json, sys
|
||||||
d = json.load(sys.stdin)
|
d = json.load(sys.stdin)
|
||||||
for r in d.get('workflow_runs', []):
|
runs = [r for r in d.get('workflow_runs', []) if r.get('head_sha','').startswith('${head_sha}')]
|
||||||
if r.get('head_sha','').startswith('${head_sha}'):
|
# Prefer push-triggered runs over workflow_run-triggered ones
|
||||||
print(r['id'], r['status'], r.get('conclusion',''), r.get('html_url',''))
|
push_runs = [r for r in runs if r.get('event') == 'push']
|
||||||
break
|
pick = push_runs[0] if push_runs else (runs[0] if runs else None)
|
||||||
|
if pick:
|
||||||
|
print(pick['id'], pick['status'], pick.get('conclusion',''), pick.get('html_url',''))
|
||||||
" 2>/dev/null) || true
|
" 2>/dev/null) || true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
if [ -n "$run_info" ]; then
|
if [ -n "$run_info" ]; then
|
||||||
|
if [ "$found" = false ]; then
|
||||||
found=true
|
found=true
|
||||||
run_id=$(echo "$run_info" | awk '{print $1}')
|
run_id=$(echo "$run_info" | awk '{print $1}')
|
||||||
local run_status
|
fi
|
||||||
run_status=$(echo "$run_info" | awk '{print $2}')
|
local run_status
|
||||||
local run_conclusion
|
run_status=$(echo "$run_info" | awk '{print $2}')
|
||||||
run_conclusion=$(echo "$run_info" | awk '{print $3}')
|
local run_conclusion
|
||||||
run_url=$(echo "$run_info" | awk '{print $4}')
|
run_conclusion=$(echo "$run_info" | awk '{print $3}')
|
||||||
|
run_url=$(echo "$run_info" | awk '{print $4}')
|
||||||
|
|
||||||
# Fetch per-job status
|
# Fetch per-job status
|
||||||
local jobs_response
|
local jobs_response
|
||||||
jobs_response=$(curl -sf "${GITEA_API_BASE}/actions/runs/${run_id}/jobs" -H "Authorization: ${GITEA_AUTH_HEADER}" 2>/dev/null) || true
|
jobs_response=$(curl -sf "${GITEA_API_BASE}/actions/runs/${run_id}/jobs" -H "Authorization: ${GITEA_AUTH_HEADER}" 2>/dev/null) || true
|
||||||
|
|
||||||
# Clear previous output
|
# Clear previous output
|
||||||
local i
|
local i
|
||||||
for ((i=0; i<prev_lines; i++)); do
|
for ((i=0; i<prev_lines; i++)); do
|
||||||
printf "\033[A\033[K"
|
printf "\033[A\033[K"
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ "$run_status" = "completed" ]; then
|
if [ "$run_status" = "completed" ]; then
|
||||||
# Show final job results
|
# Show final job results
|
||||||
if [ -n "$jobs_response" ]; then
|
if [ -n "$jobs_response" ]; then
|
||||||
echo "$jobs_response" | python3 -c "
|
echo "$jobs_response" | python3 -c "
|
||||||
import json, sys
|
import json, sys
|
||||||
d = json.load(sys.stdin)
|
d = json.load(sys.stdin)
|
||||||
for j in d.get('jobs', []):
|
for j in d.get('jobs', []):
|
||||||
@@ -634,27 +653,27 @@ for j in d.get('jobs', []):
|
|||||||
icon = '\033[1;33m?\033[0m'
|
icon = '\033[1;33m?\033[0m'
|
||||||
print(f' {icon} {name}')
|
print(f' {icon} {name}')
|
||||||
" 2>/dev/null
|
" 2>/dev/null
|
||||||
fi
|
|
||||||
if [ "$run_conclusion" = "success" ]; then
|
|
||||||
print_success "CI workflow passed"
|
|
||||||
else
|
|
||||||
print_error "CI workflow failed (conclusion: $run_conclusion)"
|
|
||||||
[ -n "$run_url" ] && print_info "View: $run_url"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
fi
|
fi
|
||||||
|
if [ "$run_conclusion" = "success" ]; then
|
||||||
|
print_success "CI workflow passed"
|
||||||
|
else
|
||||||
|
print_error "CI workflow failed (conclusion: $run_conclusion)"
|
||||||
|
[ -n "$run_url" ] && print_info "View: $run_url"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
# Show per-job progress with spinner
|
# Show per-job progress with spinner
|
||||||
local spin_char="${spinner_chars:$spin_idx:1}"
|
local spin_char="${spinner_chars:$spin_idx:1}"
|
||||||
spin_idx=$(( (spin_idx + 1) % ${#spinner_chars} ))
|
spin_idx=$(( (spin_idx + 1) % ${#spinner_chars} ))
|
||||||
local mins=$((elapsed / 60))
|
local mins=$((elapsed / 60))
|
||||||
local secs=$((elapsed % 60))
|
local secs=$((elapsed % 60))
|
||||||
|
|
||||||
prev_lines=0
|
prev_lines=0
|
||||||
if [ -n "$jobs_response" ]; then
|
if [ -n "$jobs_response" ]; then
|
||||||
local job_lines
|
local job_lines
|
||||||
job_lines=$(echo "$jobs_response" | python3 -c "
|
job_lines=$(echo "$jobs_response" | python3 -c "
|
||||||
import json, sys
|
import json, sys
|
||||||
d = json.load(sys.stdin)
|
d = json.load(sys.stdin)
|
||||||
for j in d.get('jobs', []):
|
for j in d.get('jobs', []):
|
||||||
@@ -667,7 +686,7 @@ for j in d.get('jobs', []):
|
|||||||
elif status == 'completed' and conclusion == 'failure':
|
elif status == 'completed' and conclusion == 'failure':
|
||||||
icon = '\033[0;31m✗\033[0m'
|
icon = '\033[0;31m✗\033[0m'
|
||||||
label = ''
|
label = ''
|
||||||
elif status == 'running':
|
elif status in ('running', 'in_progress'):
|
||||||
icon = '${spin_char}'
|
icon = '${spin_char}'
|
||||||
label = ' running'
|
label = ' running'
|
||||||
elif status == 'waiting':
|
elif status == 'waiting':
|
||||||
@@ -678,33 +697,40 @@ for j in d.get('jobs', []):
|
|||||||
label = ' ' + status
|
label = ' ' + status
|
||||||
print(f' {icon} {name}{label}')
|
print(f' {icon} {name}{label}')
|
||||||
" 2>/dev/null) || true
|
" 2>/dev/null) || true
|
||||||
if [ -n "$job_lines" ]; then
|
if [ -n "$job_lines" ]; then
|
||||||
echo "$job_lines"
|
echo "$job_lines"
|
||||||
prev_lines=$(echo "$job_lines" | wc -l)
|
prev_lines=$(echo "$job_lines" | wc -l)
|
||||||
fi
|
|
||||||
else
|
|
||||||
printf " %s CI %s (%d:%02d)\n" "$spin_char" "$run_status" "$mins" "$secs"
|
|
||||||
prev_lines=1
|
|
||||||
fi
|
fi
|
||||||
|
else
|
||||||
sleep "$poll_interval"
|
printf " %s CI %s (%d:%02d)\n" "$spin_char" "$run_status" "$mins" "$secs"
|
||||||
elapsed=$((elapsed + poll_interval))
|
prev_lines=1
|
||||||
continue
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
sleep "$poll_interval"
|
||||||
|
elapsed=$((elapsed + poll_interval))
|
||||||
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# No run found yet - show waiting spinner
|
# No run found yet - give up after 15 seconds (no workflow configured)
|
||||||
|
if [ "$elapsed" -ge 15 ]; then
|
||||||
|
local i
|
||||||
|
for ((i=0; i<prev_lines; i++)); do
|
||||||
|
printf "\033[A\033[K"
|
||||||
|
done
|
||||||
|
print_info "No CI workflow found"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Show waiting spinner
|
||||||
local spin_char="${spinner_chars:$spin_idx:1}"
|
local spin_char="${spinner_chars:$spin_idx:1}"
|
||||||
spin_idx=$(( (spin_idx + 1) % ${#spinner_chars} ))
|
spin_idx=$(( (spin_idx + 1) % ${#spinner_chars} ))
|
||||||
local mins=$((elapsed / 60))
|
|
||||||
local secs=$((elapsed % 60))
|
|
||||||
|
|
||||||
# Clear previous output
|
# Clear previous output
|
||||||
local i
|
local i
|
||||||
for ((i=0; i<prev_lines; i++)); do
|
for ((i=0; i<prev_lines; i++)); do
|
||||||
printf "\033[A\033[K"
|
printf "\033[A\033[K"
|
||||||
done
|
done
|
||||||
printf " %s waiting for workflow to start (%d:%02d)\n" "$spin_char" "$mins" "$secs"
|
printf " %s waiting for workflow to start\n" "$spin_char"
|
||||||
prev_lines=1
|
prev_lines=1
|
||||||
|
|
||||||
sleep "$poll_interval"
|
sleep "$poll_interval"
|
||||||
|
|||||||
Reference in New Issue
Block a user