Files
Ferrous-Solitaire/scripts/watch_deploy.sh
T
funman300 123aa6d099 chore(scripts): add Gitea deploy watcher
Polls the docker-build / web-wasm-rebuild workflow runs and prints a
compact status block until the newest deploy is live. Reads the API
token from ~/.config/tea/config.yml and never prints it.

Closes #119

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 13:10:24 -07:00

67 lines
2.7 KiB
Bash
Executable File

#!/usr/bin/env bash
# Live-watch the Gitea Actions deploy pipeline for Ferrous Solitaire.
#
# Polls recent workflow runs and prints a compact status block each cycle.
# Stops when the newest docker-build (the deploy) has completed and no
# web-wasm-rebuild is still pending — i.e. the full fix is live.
#
# Usage: ./scripts/watch_deploy.sh [interval_seconds]
# token is read from ~/.config/tea/config.yml (never printed).
set -uo pipefail
REPO="funman300/Ferrous-Solitaire"
BASE="https://git.aleshym.co/api/v1/repos/${REPO}"
INTERVAL="${1:-20}"
CFG="${HOME}/.config/tea/config.yml"
TOKEN="$(grep -E '^[[:space:]]*token:' "$CFG" | head -1 | sed -E 's/.*token:[[:space:]]*//' | tr -d '"'\'' ')"
[ -z "$TOKEN" ] && { echo "error: no token in $CFG" >&2; exit 1; }
echo "── watching ${REPO} deploy (poll ${INTERVAL}s, Ctrl-C to stop) ──"
while :; do
json="$(curl -s --max-time 20 -H "Authorization: token ${TOKEN}" "${BASE}/actions/runs?limit=6")"
# Print rows + emit the deploy state on the last line (parsed below).
# JSON is passed via env var because `python3 -` reads its program from the
# heredoc on stdin, so stdin can't also carry the data.
out="$(JSON_DATA="$json" python3 - <<'PY'
import os, sys, json, datetime
now = datetime.datetime.now().strftime("%H:%M:%S")
raw = os.environ.get("JSON_DATA", "").strip()
try:
d = json.loads(raw)
except Exception:
print("[%s] (api unavailable, retrying)" % now)
print("STATE=DEPLOYING")
sys.exit(0)
runs = d.get("workflow_runs", [])[:6]
icons = {("completed","success"):"OK ", ("completed","failure"):"FAIL",
("completed","cancelled"):"CXL "}
def ic(s, c):
if s == "queued": return "queue"
if s == "in_progress": return "run.."
return icons.get((s, c), s or "?")
print("[%s]" % datetime.datetime.now().strftime("%H:%M:%S"))
for r in runs:
wf = str(r.get("path","")).split("@")[0].split("/")[-1].replace(".yml","")
print(" %-5s %-5s %-7s %-18s %s/%s" % (
ic(r.get("status"), r.get("conclusion")),
r.get("id"), str(r.get("head_sha"))[:7], wf[:18],
r.get("status"), r.get("conclusion")))
db = [r for r in runs if "docker-build" in str(r.get("path"))]
wr_pending = any(r.get("status") != "completed" for r in runs if "web-wasm-rebuild" in str(r.get("path")))
top = db[0] if db else None
live = bool(top and top.get("status")=="completed" and top.get("conclusion")=="success" and not wr_pending)
print("STATE=%s" % ("LIVE" if live else ("WAIT_WASM" if wr_pending else "DEPLOYING")))
PY
)"
echo "$out" | grep -v '^STATE='
if echo "$out" | grep -q '^STATE=LIVE'; then
echo ""
echo "DEPLOY LIVE — newest docker-build succeeded, no wasm rebuild pending."
echo " Test: https://klondike.aleshym.co/play?v=${RANDOM}"
break
fi
sleep "$INTERVAL"
done