learning_ai_common_plat/scripts/gitea/register-runner.sh
saravanakumardb1 3224199894 feat(gitea): reproducible Actions runner registration + harden runner config
- add scripts/gitea/register-runner.sh (idempotent register, host/docker modes,
  capacity arg, admin-API registration token, --force re-register)
- GITEA_VM_SETUP.md Step 11: runner install/register, host-vs-docker tradeoffs,
  token externalization (env_file), concurrency (capacity), token rotation,
  end-to-end CI verification
- document runner registration + secrets in persist/ephemeral table

Live runner hardened separately: capacity 1->2, GITEA_NPM_TOKEN moved from
inline config.yaml to chmod-600 runner.env via env_file.
2026-05-28 18:05:55 -07:00

107 lines
4.7 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# register-runner.sh — Reproducibly register (or re-register) a Gitea Actions
# runner against the local/VM Gitea instance.
#
# Why this exists: the runner was originally registered by hand, which is not
# reproducible for the next operator. This script captures the canonical flow:
# fetch a registration token from Gitea, register act_runner with the agreed
# labels + capacity, and externalise the npm token into a gitignored env_file
# (never inline in config.yaml).
#
# Usage:
# GITEA_ADMIN_USER=gitea-admin GITEA_ADMIN_PASS=... bash register-runner.sh
# bash register-runner.sh --instance http://localhost:3300 --name bytelyst-mac
# bash register-runner.sh --mode docker # containerized labels
# bash register-runner.sh --capacity 2 # parallel jobs
#
# Idempotent: if a runner is already registered (.runner exists), it prints the
# current registration and exits unless --force is passed.
set -euo pipefail
# ── defaults ───────────────────────────────────────────────────────────────
INSTANCE="${GITEA_INSTANCE:-http://localhost:3300}"
RUNNER_NAME="${RUNNER_NAME:-$(hostname -s)}"
CAPACITY="${RUNNER_CAPACITY:-2}"
MODE="host" # host | docker
FORCE=0
CONFIG_DIR="${ACT_RUNNER_CONFIG_DIR:-/opt/homebrew/etc/act_runner}"
RUNNER_FILE="${ACT_RUNNER_FILE:-/opt/homebrew/var/lib/act_runner/.runner}"
ENV_FILE="${ACT_RUNNER_ENV_FILE:-$CONFIG_DIR/runner.env}"
# Docker image used when MODE=docker (mirrors GitHub's ubuntu-latest closely).
DOCKER_IMAGE="${RUNNER_DOCKER_IMAGE:-catthehacker/ubuntu:act-latest}"
while [ $# -gt 0 ]; do
case "$1" in
--instance) INSTANCE="$2"; shift 2 ;;
--name) RUNNER_NAME="$2"; shift 2 ;;
--capacity) CAPACITY="$2"; shift 2 ;;
--mode) MODE="$2"; shift 2 ;;
--force) FORCE=1; shift ;;
-h|--help) grep '^#' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;;
*) echo "unknown arg: $1" >&2; exit 2 ;;
esac
done
command -v act_runner >/dev/null 2>&1 || {
echo "✗ act_runner not on PATH. Install: brew install act_runner" >&2
exit 1
}
# ── labels per mode ──────────────────────────────────────────────────────────
if [ "$MODE" = "docker" ]; then
LABELS="ubuntu-latest:docker://$DOCKER_IMAGE,ubuntu-22.04:docker://$DOCKER_IMAGE,self-hosted:host"
else
LABELS="ubuntu-latest:host,macos-latest:host,macos-15:host,self-hosted:host"
fi
echo "── Gitea runner registration ──"
echo " instance : $INSTANCE"
echo " name : $RUNNER_NAME"
echo " mode : $MODE"
echo " capacity : $CAPACITY"
echo " labels : $LABELS"
# ── already registered? ──────────────────────────────────────────────────────
if [ -f "$RUNNER_FILE" ] && [ "$FORCE" -ne 1 ]; then
echo ""
echo "✓ runner already registered ($RUNNER_FILE). Current identity:"
python3 - "$RUNNER_FILE" <<'PY' 2>/dev/null || cat "$RUNNER_FILE"
import json, sys
d = json.load(open(sys.argv[1]))
for k in ("id", "uuid", "name", "address", "labels", "ephemeral"):
print(f" {k}: {d.get(k)}")
PY
echo ""
echo " Pass --force to re-register (this invalidates the old runner)."
exit 0
fi
# ── fetch a registration token ───────────────────────────────────────────────
# Admin-scoped: GET /admin/runners/registration-token (Gitea >= 1.20).
: "${GITEA_ADMIN_USER:?set GITEA_ADMIN_USER}"
: "${GITEA_ADMIN_PASS:?set GITEA_ADMIN_PASS}"
REG_TOKEN=$(curl -fsS -u "$GITEA_ADMIN_USER:$GITEA_ADMIN_PASS" \
"$INSTANCE/api/v1/admin/runners/registration-token" \
| python3 -c "import json,sys; print(json.load(sys.stdin)['token'])")
[ -n "$REG_TOKEN" ] || { echo "✗ could not fetch registration token" >&2; exit 1; }
echo "✓ registration token obtained"
# ── register ────────────────────────────────────────────────────────────────
[ "$FORCE" -eq 1 ] && rm -f "$RUNNER_FILE"
act_runner register \
--no-interactive \
--instance "$INSTANCE" \
--token "$REG_TOKEN" \
--name "$RUNNER_NAME" \
--labels "$LABELS" \
--config "$CONFIG_DIR/config.yaml"
echo "✓ runner registered"
echo ""
echo "Next: externalise secrets into $ENV_FILE (see GITEA_VM_SETUP.md §11),"
echo "set runner.capacity: $CAPACITY in config.yaml, then:"
echo " brew services restart act_runner"