#!/bin/bash # gitea-runs — Gitea Actions CLI helper # Usage: # gitea-runs List recent runs # gitea-runs list [limit] List recent runs (default 10) # gitea-runs view View run details & jobs # gitea-runs open [run_number] Open run in browser # gitea-runs workflows List workflows # gitea-runs dispatch [ref] Trigger a workflow dispatch # gitea-runs help Show this help set -e # Config from tea CLI TEA_CONFIG="${XDG_CONFIG_HOME:-$HOME/Library/Application Support}/tea/config.yml" if [ ! -f "$TEA_CONFIG" ]; then TEA_CONFIG="$HOME/.config/tea/config.yml" fi # Parse tea config (nested under logins) GITEA_URL=$(grep 'url:' "$TEA_CONFIG" | head -1 | awk '{print $NF}') GITEA_TOKEN=$(grep 'token:' "$TEA_CONFIG" | head -1 | awk '{print $NF}') # Detect repo from git remote REPO=$(git remote get-url origin 2>/dev/null | sed 's|.*gitea.pipexerp.com[:/]*||;s|\.git$||;s|^10022/||') if [ -z "$REPO" ]; then echo "Error: not in a git repo or remote not configured" exit 1 fi API="$GITEA_URL/api/v1" AUTH="Authorization: token $GITEA_TOKEN" GREEN='\033[0;32m' RED='\033[0;31m' CYAN='\033[0;36m' NC='\033[0m' cmd_dispatch() { local workflow="${1:-}" local ref="${2:-main}" if [ -z "$workflow" ]; then echo "Usage: gitea-runs dispatch [ref]" echo "" echo "Available workflows:" curl -s -H "$AUTH" "$API/repos/$REPO/actions/workflows" 2>/dev/null \ | python3 -c " import json, sys data = json.load(sys.stdin) for w in data.get('workflows', []): print(f\" {w['id']:30s} {w['name']}\") " 2>/dev/null return fi local http_code http_code=$(curl -s -o /dev/null -w "%{http_code}" \ -H "$AUTH" \ -H "Content-Type: application/json" \ -X POST "$API/repos/$REPO/actions/workflows/$workflow/dispatches" \ -d "{\"ref\":\"$ref\"}" 2>/dev/null) if [ "$http_code" = "204" ]; then echo -e "${GREEN}✓${NC} Dispatched workflow: $workflow (ref: $ref)" echo " View: $GITEA_URL/$REPO/actions" else echo -e "${RED}✗${NC} Failed to dispatch (HTTP $http_code)" fi } cmd_workflows() { echo -e "${CYAN}Workflows for $REPO${NC}" echo "" curl -s -H "$AUTH" "$API/repos/$REPO/actions/workflows" 2>/dev/null \ | python3 -c " import json, sys data = json.load(sys.stdin) for w in data.get('workflows', []): state = '✓' if w['state'] == 'active' else '✗' print(f\" {state} {w['id']:30s} {w['name']}\") " 2>/dev/null } cmd_list() { local limit="${1:-10}" echo -e "${CYAN}Recent runs for $REPO${NC}" echo "" curl -s -H "$AUTH" "$API/repos/$REPO/actions/runs?limit=$limit" 2>/dev/null \ | python3 -c " import json, sys limit = $limit data = json.load(sys.stdin) for r in data.get('workflow_runs', [])[:limit]: status = r.get('status', '?') num = r.get('run_number', 0) title = r.get('display_title', '')[:60] wf = r.get('path', '') wf = wf.split('@')[0] if '@' in wf else wf icon = {'success':'\u2713','completed':'\u2713','failure':'\u2717','cancelled':'\u2717','in_progress':'\u27f3','running':'\u27f3','queued':'\u25cc','waiting':'\u25cc'}.get(status, '?') color = {'success':'\033[0;32m','completed':'\033[0;32m','failure':'\033[0;31m','cancelled':'\033[0;31m','in_progress':'\033[0;33m','running':'\033[0;33m'}.get(status, '\033[0;37m') print(f\"{color}{icon}\033[0m #{num:<4} {status:<12} {wf:<20} {title}\") " 2>/dev/null } cmd_view() { local run_number="${1:-}" if [ -z "$run_number" ]; then echo "Usage: gitea-runs view " return 1 fi # Find run by run_number (API uses internal id, html uses run_number) local run_data run_data=$(curl -s -H "$AUTH" "$API/repos/$REPO/actions/runs?limit=50" 2>/dev/null \ | python3 -c " import json, sys data = json.load(sys.stdin) for r in data.get('workflow_runs', []): if r['run_number'] == $run_number: print(json.dumps(r)) break " 2>/dev/null) if [ -z "$run_data" ]; then echo -e "${RED}✗${NC} Run #$run_number not found" return 1 fi local run_id run_id=$(echo "$run_data" | python3 -c "import json,sys; print(json.load(sys.stdin)['id'])") # Print run info echo "$run_data" | python3 -c " import json, sys r = json.load(sys.stdin) status = r.get('status', '?') icon = {'success':'\u2713','failure':'\u2717','in_progress':'\u27f3','queued':'\u25cc'}.get(status, '?') color = {'success':'\033[0;32m','failure':'\033[0;31m','in_progress':'\033[0;33m'}.get(status, '\033[0;37m') print(f\"{color}{icon} Run #{r.get('run_number',0)} \u2014 {status}\033[0m\") print(f\" Title: {r.get('display_title','')}\") print(f\" Event: {r.get('event','')}\") print(f\" Branch: {r.get('head_branch','')}\") print(f\" Commit: {r.get('head_sha','')[:8]}\") print(f\" Actor: {r.get('actor',{}).get('login','')}\") wf = r.get('path', '') wf = wf.split('@')[0] if '@' in wf else wf print(f\" Workflow: {wf}\") " 2>/dev/null # Print jobs echo "" echo -e "${CYAN}Jobs:${NC}" curl -s -H "$AUTH" "$API/repos/$REPO/actions/runs/$run_id/jobs" 2>/dev/null \ | python3 -c " import json, sys from datetime import datetime data = json.load(sys.stdin) for j in data.get('jobs', []): status = j.get('status', '?') icon = {'success':'\u2713','failure':'\u2717','in_progress':'\u27f3','queued':'\u25cc','waiting':'\u25cc'}.get(status, '?') color = {'success':'\033[0;32m','failure':'\033[0;31m','in_progress':'\033[0;33m'}.get(status, '\033[0;37m') runner = j.get('runner_name', '-') started = j.get('started_at', '')[:19].replace('T', ' ') completed = j.get('completed_at', '')[:19].replace('T', ' ') duration = '' if completed and not completed.startswith('1970'): try: d = datetime.fromisoformat(completed) - datetime.fromisoformat(started) duration = f' ({int(d.total_seconds())}s)' except: pass print(f\" {color}{icon}\033[0m {j.get('name',''):<30} {status:<12} runner: {runner}{duration}\") " 2>/dev/null } cmd_open() { local run_id="${1:-}" local url="$GITEA_URL/$REPO/actions" if [ -n "$run_id" ]; then url="$url/runs/$run_id" fi echo "Opening: $url" open "$url" 2>/dev/null || xdg-open "$url" 2>/dev/null || echo "$url" } cmd_help() { echo "gitea-runs — Gitea Actions CLI helper" echo "" echo "Usage:" echo " gitea-runs List recent runs" echo " gitea-runs list [limit] List recent runs (default 10)" echo " gitea-runs view View run details & jobs" echo " gitea-runs open [run_number] Open run in browser" echo " gitea-runs workflows List workflows" echo " gitea-runs dispatch [ref] Trigger a workflow dispatch" echo " gitea-runs help Show this help" echo "" echo "Repo: $REPO" echo "Gitea: $GITEA_URL" } # Main case "${1:-}" in list|ls) shift; cmd_list "$@" ;; view|v) shift; cmd_view "$@" ;; dispatch) shift; cmd_dispatch "$@" ;; workflows|wf) cmd_workflows ;; open|o) shift; cmd_open "$@" ;; help|--help|-h) cmd_help ;; "") cmd_list ;; *) cmd_view "$1" ;; esac