#!/usr/bin/env bash # gitea skill — ver detalle de un run de Actions. # # Gitea no tiene `GET /actions/runs/{id}` ni `/actions/runs/{id}/jobs`, así que # este script: # 1. Lista /actions/tasks y matchea por task_id o run_number # 2. Imprime la metadata # 3. Hace un probe del job_id (porque la API tampoco lo expone) leyendo la # primera línea de los logs candidatos hasta encontrar el que diga # "received task " # # Uso: # actions-view.sh / set -euo pipefail SKILL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" QUERY="$SKILL_DIR/scripts/query.sh" if [[ $# -lt 2 ]]; then cat >&2 </ Ejemplo: actions-view.sh NucleOS/nucleo-infra 11 EOF exit 2 fi repo_arg="$1" run_ref="$2" if [[ "$repo_arg" == */* ]]; then owner="${repo_arg%%/*}" repo="${repo_arg##*/}" else set -a; source "$SKILL_DIR/.env"; set +a owner="${GITEA_DEFAULT_OWNER:?owner no especificado y GITEA_DEFAULT_OWNER vacío}" repo="$repo_arg" fi resp="$("$QUERY" "/repos/${owner}/${repo}/actions/tasks?limit=50")" # Matchear por task.id o run_number task_data="$(echo "$resp" | PY_REF="$run_ref" python -c ' import json, os, sys ref = int(os.environ["PY_REF"]) d = json.load(sys.stdin) for r in d.get("workflow_runs", []): if r.get("id") == ref or r.get("run_number") == ref: print(json.dumps(r)) break ' | tr -d '\r')" if [[ -z "$task_data" ]]; then echo "ERROR: no encontré ningún run con id o run_number = $run_ref en los últimos 50." >&2 echo " Probá: actions-list-runs.sh $owner/$repo --limit 50" >&2 exit 3 fi task_id="$(echo "$task_data" | python -c 'import json,sys; print(json.load(sys.stdin)["id"])' | tr -d '\r')" export PY_OWNER="$owner" PY_REPO="$repo" PYTHONIOENCODING=utf-8 echo "$task_data" | python -c ' import json, sys r = json.load(sys.stdin) fmt = lambda s, n: (s or "")[:n].replace("T", " ") print("=== Run #{} (task_id={}) ===".format(r.get("run_number"), r.get("id"))) print(" workflow: " + str(r.get("workflow_id"))) print(" status: " + str(r.get("status"))) print(" event: " + str(r.get("event"))) print(" branch: " + str(r.get("head_branch"))) print(" sha: " + fmt(r.get("head_sha"), 12)) print(" title: " + str(r.get("display_title"))) print(" created: " + fmt(r.get("created_at"), 19)) print(" started: " + fmt(r.get("run_started_at"), 19)) print(" updated: " + fmt(r.get("updated_at"), 19)) print(" url: " + str(r.get("url"))) ' echo # ─── Probe job_id ─────────────────────────────────────────────────────── # Gitea no expone una API para listar jobs de un run. Pero la primera línea # de cada log contiene "received task ". Probamos un rango pequeño # y matcheamos. echo "→ Probing job_id (Gitea no tiene API para listar jobs de un run)..." >&2 found_jid="" # Disable pipefail dentro del probe: `head -1` cierra el pipe upstream y curl # muere con SIGPIPE (141) — con pipefail, eso mata el script. set +o pipefail for delta in 0 1 2 3 4 5 -1 -2 -3 6 7 8 9 10; do jid=$((task_id + delta)) if [[ $jid -lt 1 ]]; then continue; fi first_line="$("$QUERY" "/repos/${owner}/${repo}/actions/jobs/${jid}/logs" 2>/dev/null | head -1 || true)" if echo "$first_line" | grep -q "received task ${task_id} "; then found_jid="$jid" break fi done set -o pipefail if [[ -n "$found_jid" ]]; then echo " job_id (probed): $found_jid" echo " para logs: bash actions-logs.sh $owner/$repo $task_id [--tail N | --errors | ...]" else echo " ⚠️ No pude encontrar el job_id en task_id±10. El run podría tener" >&2 echo " múltiples jobs o estar muy desfasado. Probá rangos más anchos" >&2 echo " manualmente: query.sh /repos/$owner/$repo/actions/jobs//logs" >&2 fi