En Windows el stdout de Python defaultea a cp1252 y crashea con
UnicodeEncodeError al imprimir literales no-ASCII (e.g. el ✓ del print
de éxito de pr-create.sh). El sintoma era que el PR se creaba OK pero
el script terminaba con exit 1 por el crash del print posterior.
Agrego export PYTHONIOENCODING=utf-8 después de set -euo pipefail en
los 10 scripts que invocan python (todos menos query.sh). Cubre tanto
las invocaciones inline como futuras sin tener que acordarse caso por
caso. Mantiene los literales unicode existentes (✓, →, ─, ⚠️).
125 lines
4.1 KiB
Bash
125 lines
4.1 KiB
Bash
#!/usr/bin/env bash
|
|
# gitea skill — listar runs de Gitea Actions de un repo.
|
|
#
|
|
# Gitea 1.24 expone `/actions/tasks` (NO `/actions/runs`). El endpoint solo
|
|
# acepta `page` y `limit` — los demás filtros (workflow, branch, status,
|
|
# event, actor) se aplican client-side acá.
|
|
#
|
|
# Uso:
|
|
# actions-list-runs.sh <owner>/<repo> [--workflow <filename>]
|
|
# [--branch <ref>] [--status <s>]
|
|
# [--event <e>] [--actor <user>]
|
|
# [--limit N]
|
|
|
|
set -euo pipefail
|
|
|
|
# Forzar UTF-8 en stdout de Python (Windows defaultea a cp1252 y crashea con
|
|
# literales no-ASCII). Ver memoria feedback_api_utf8_encoding.md.
|
|
export PYTHONIOENCODING=utf-8
|
|
|
|
SKILL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
QUERY="$SKILL_DIR/scripts/query.sh"
|
|
|
|
repo_arg=""
|
|
workflow=""
|
|
branch=""
|
|
status=""
|
|
event=""
|
|
limit=10
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--workflow) workflow="$2"; shift 2 ;;
|
|
--branch) branch="$2"; shift 2 ;;
|
|
--status) status="$2"; shift 2 ;;
|
|
--event) event="$2"; shift 2 ;;
|
|
--limit) limit="$2"; shift 2 ;;
|
|
-h|--help)
|
|
cat <<EOF
|
|
Uso: actions-list-runs.sh <owner>/<repo> [opciones]
|
|
|
|
Opciones (todas client-side, el server solo respeta page+limit):
|
|
--workflow <filename> ej. deploy-infra.yml (matchea workflow_id)
|
|
--branch <ref> ej. main (matchea head_branch)
|
|
--status <s> success | failure | running | waiting | cancelled
|
|
--event <e> push | pull_request | workflow_dispatch
|
|
--limit N cuántos traer del server (default 10)
|
|
|
|
NOTA: Gitea no devuelve el actor del run en /actions/tasks, así que no hay
|
|
filtro --actor. Si necesitás esa info, mirá el merge commit con git log.
|
|
EOF
|
|
exit 0
|
|
;;
|
|
-*) echo "ERROR: flag desconocida: $1" >&2; exit 2 ;;
|
|
*) repo_arg="$1"; shift ;;
|
|
esac
|
|
done
|
|
|
|
if [[ -z "$repo_arg" ]]; then
|
|
echo "ERROR: pasá <owner>/<repo>." >&2
|
|
exit 2
|
|
fi
|
|
|
|
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=${limit}")"
|
|
|
|
# export ANTES del pipe — el VAR=val inline no llega al python downstream.
|
|
export PY_WORKFLOW="$workflow" PY_BRANCH="$branch" PY_STATUS="$status" \
|
|
PY_EVENT="$event" PY_OWNER="$owner" PY_REPO="$repo"
|
|
|
|
echo "$resp" | PYTHONIOENCODING=utf-8 python -c '
|
|
import json, os, sys
|
|
d = json.load(sys.stdin)
|
|
runs = d.get("workflow_runs", [])
|
|
total = d.get("total_count", len(runs))
|
|
|
|
owner = os.environ.get("PY_OWNER", "")
|
|
repo = os.environ.get("PY_REPO", "")
|
|
|
|
def keep(r):
|
|
wf = os.environ.get("PY_WORKFLOW")
|
|
if wf:
|
|
rwf = r.get("workflow_id","")
|
|
if rwf != wf and not rwf.endswith(wf):
|
|
return False
|
|
if os.environ.get("PY_BRANCH") and r.get("head_branch") != os.environ["PY_BRANCH"]:
|
|
return False
|
|
if os.environ.get("PY_STATUS") and r.get("status") != os.environ["PY_STATUS"]:
|
|
return False
|
|
if os.environ.get("PY_EVENT") and r.get("event") != os.environ["PY_EVENT"]:
|
|
return False
|
|
return True
|
|
|
|
filtered = [r for r in runs if keep(r)]
|
|
any_filter = any(os.environ.get(k) for k in ("PY_WORKFLOW","PY_BRANCH","PY_STATUS","PY_EVENT"))
|
|
filt_label = f" (filtered: {len(filtered)}/{len(runs)})" if any_filter else ""
|
|
print(f"{len(filtered)} run(s) en {owner}/{repo}{filt_label}, total disponible={total}")
|
|
print()
|
|
|
|
if not filtered:
|
|
sys.exit(0)
|
|
|
|
for r in filtered:
|
|
tid = r.get("id")
|
|
rnum = r.get("run_number")
|
|
title = r.get("display_title") or r.get("name","?")
|
|
if len(title) > 70: title = title[:67] + "..."
|
|
st = r.get("status","?")
|
|
branch = r.get("head_branch") or "?"
|
|
ev = r.get("event","?")
|
|
wf = r.get("workflow_id","?")
|
|
created = (r.get("created_at") or "")[:19].replace("T"," ")
|
|
sha = (r.get("head_sha") or "")[:7]
|
|
print(f" #{rnum:<4} task={tid:<5} {st:<10} {ev:<18} {branch:<14} {wf}")
|
|
print(f" {title}")
|
|
print(f" sha={sha} created={created}")
|
|
'
|