From efa946e15354eb21ba9a4427a435f50367a7ba8c Mon Sep 17 00:00:00 2001 From: j Date: Mon, 9 Mar 2026 07:10:36 +1300 Subject: [PATCH] Show per-job CI progress instead of simple spinner in workflow wait --- gp | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 109 insertions(+), 18 deletions(-) diff --git a/gp b/gp index 99b7e1b..9dd2bde 100755 --- a/gp +++ b/gp @@ -514,7 +514,7 @@ parse_gitea_remote() { } # Function to wait for CI workflow to complete after push -# Polls Gitea Actions API, shows spinner, ESC cancels +# Polls Gitea Actions API, shows per-job progress, ESC cancels wait_for_workflow() { local head_sha="$1" local branch="$2" @@ -540,7 +540,8 @@ wait_for_workflow() { # Restore terminal on exit trap 'stty "$old_tty" 2>/dev/null; trap - RETURN' RETURN - local run_url="" status="" conclusion="" found=false + local run_url="" run_id="" found=false + local prev_lines=0 # track how many lines we printed last time while [ "$elapsed" -lt "$max_wait" ]; do # Check for ESC key @@ -549,15 +550,19 @@ wait_for_workflow() { if [ "$key" = $'\x1b' ]; then # Drain any remaining escape sequence bytes dd bs=1 count=5 2>/dev/null >/dev/null || true - echo -e "\r\033[K" + # Clear the job status lines + local i + for ((i=0; i/dev/null) || true + response=$(curl -sf "${GITEA_API_BASE}/actions/runs?limit=5" -H "Authorization: token ${GITEA_API_TOKEN}" 2>/dev/null) || true if [ -n "$response" ]; then # Find the run matching our commit SHA @@ -567,44 +572,130 @@ import json, sys d = json.load(sys.stdin) for r in d.get('workflow_runs', []): if r.get('head_sha','').startswith('${head_sha}'): - print(r['status'], r.get('conclusion',''), r.get('html_url','')) + print(r['id'], r['status'], r.get('conclusion',''), r.get('html_url','')) break " 2>/dev/null) || true if [ -n "$run_info" ]; then found=true - status=$(echo "$run_info" | awk '{print $1}') - conclusion=$(echo "$run_info" | awk '{print $2}') - run_url=$(echo "$run_info" | awk '{print $3}') + run_id=$(echo "$run_info" | awk '{print $1}') + local run_status + run_status=$(echo "$run_info" | awk '{print $2}') + local run_conclusion + run_conclusion=$(echo "$run_info" | awk '{print $3}') + run_url=$(echo "$run_info" | awk '{print $4}') - if [ "$status" = "completed" ]; then - echo -e "\r\033[K" - if [ "$conclusion" = "success" ]; then + # Fetch per-job status + local jobs_response + jobs_response=$(curl -sf "${GITEA_API_BASE}/actions/runs/${run_id}/jobs" -H "Authorization: token ${GITEA_API_TOKEN}" 2>/dev/null) || true + + # Clear previous output + local i + for ((i=0; i/dev/null + fi + if [ "$run_conclusion" = "success" ]; then print_success "CI workflow passed" else - print_error "CI workflow failed (conclusion: $conclusion)" + 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 + local spin_char="${spinner_chars:$spin_idx:1}" + spin_idx=$(( (spin_idx + 1) % ${#spinner_chars} )) + local mins=$((elapsed / 60)) + local secs=$((elapsed % 60)) + + prev_lines=0 + if [ -n "$jobs_response" ]; then + local job_lines + job_lines=$(echo "$jobs_response" | python3 -c " +import json, sys +d = json.load(sys.stdin) +for j in d.get('jobs', []): + name = j['name'] + status = j['status'] + conclusion = j.get('conclusion', '') + if status == 'completed' and conclusion == 'success': + icon = '\033[0;32m✓\033[0m' + label = '' + elif status == 'completed' and conclusion == 'failure': + icon = '\033[0;31m✗\033[0m' + label = '' + elif status == 'running': + icon = '${spin_char}' + label = ' running' + elif status == 'waiting': + icon = '·' + label = ' queued' + else: + icon = '·' + label = ' ' + status + print(f' {icon} {name}{label}') +" 2>/dev/null) || true + if [ -n "$job_lines" ]; then + echo "$job_lines" + 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 + + sleep "$poll_interval" + elapsed=$((elapsed + poll_interval)) + continue fi fi - # Show spinner + # No run found yet - show waiting spinner local spin_char="${spinner_chars:$spin_idx:1}" spin_idx=$(( (spin_idx + 1) % ${#spinner_chars} )) - local status_msg="waiting" - $found && status_msg="$status" local mins=$((elapsed / 60)) local secs=$((elapsed % 60)) - printf "\r %s CI %s (%d:%02d)" "$spin_char" "$status_msg" "$mins" "$secs" + + # Clear previous output + local i + for ((i=0; i