#!/usr/bin/env bash
# setup-gh-runner.sh — register this Mac as a self-hosted GitHub Actions runner
# for the current repo. Installed by `scaffold agent-ops install --component ci`.
#
# Self-hosted runner usage is FREE on every GitHub plan (Actions minutes bill
# only for GitHub-hosted runners). The runner is persistent, managed by launchd
# via the runner's own svc.sh (start at login, restart on crash). Requires: gh
# authenticated with admin on the repo (registration-token API).
#
#   setup-gh-runner.sh               register + start
#   setup-gh-runner.sh --print-only  preview without side effects
set -euo pipefail

PRINT_ONLY=0
[ "${1:-}" = "--print-only" ] && PRINT_ONLY=1

command -v gh >/dev/null 2>&1 || { echo "gh CLI required" >&2; exit 2; }
if [ "$PRINT_ONLY" = 1 ]; then
	# Preview must not require gh auth / network — show a placeholder if it can't resolve.
	REPO="$(gh repo view --json nameWithOwner -q .nameWithOwner 2>/dev/null || echo '<owner>/<repo>')"
else
	REPO="$(gh repo view --json nameWithOwner -q .nameWithOwner)"
fi
RUNNER_DIR="$HOME/.gh-runner/{{PROJECT_NAME}}"
NAME="{{PROJECT_NAME}}-mq-runner"

if [ "$PRINT_ONLY" = 1 ]; then
	echo "would register runner '$NAME' for $REPO"
	echo "  dir:    $RUNNER_DIR"
	echo "  labels: self-hosted,macOS,ARM64"
	echo "  mgmt:   ./svc.sh install && ./svc.sh start (launchd)"
	exit 0
fi

mkdir -p "$RUNNER_DIR"
cd "$RUNNER_DIR"

if [ ! -f config.sh ]; then
	echo "downloading latest actions runner (osx-arm64)…"
	# One API call; extract both URL and digest from the same response (jq when
	# available, else two gh calls as a fallback).
	SEL='.assets[] | select(.name | test("actions-runner-osx-arm64-[0-9.]+\\.tar\\.gz$"))'
	REL="$(gh api repos/actions/runner/releases/latest)"
	if command -v jq >/dev/null 2>&1; then
		URL="$(printf '%s' "$REL" | jq -r "$SEL | .browser_download_url")"
		DIGEST="$(printf '%s' "$REL" | jq -r "$SEL | .digest // \"\"")"
	else
		URL="$(gh api repos/actions/runner/releases/latest -q "$SEL | .browser_download_url")"
		DIGEST="$(gh api repos/actions/runner/releases/latest -q "$SEL | .digest // \"\"")"
	fi
	curl -fsSL "$URL" -o runner.tar.gz
	# Verify the download against the release's published digest when available —
	# a compromised asset or MITM would otherwise run arbitrary code as this user.
	if [ -n "$DIGEST" ]; then
		EXPECTED="${DIGEST#sha256:}"
		ACTUAL="$(shasum -a 256 runner.tar.gz | awk '{print $1}')"
		if [ "$EXPECTED" != "$ACTUAL" ]; then
			echo "runner tarball checksum mismatch (expected $EXPECTED, got $ACTUAL)" >&2
			rm -f runner.tar.gz
			exit 3
		fi
		echo "runner tarball checksum verified"
	else
		echo "warning: release provided no digest — skipping checksum verification" >&2
	fi
	tar xzf runner.tar.gz
	rm runner.tar.gz
fi

# Rerunnable: config.sh refuses when a .runner config already exists, so on a
# re-run just (re)install and start the service instead of reconfiguring.
if [ -f .runner ]; then
	echo "runner already configured — ensuring the launchd service is running"
	./svc.sh install 2>/dev/null || true # may already be installed; that's fine
	if ! ./svc.sh start; then
		echo "error: svc.sh start failed — the runner service is NOT running." >&2
		echo "  inspect: (cd $RUNNER_DIR && ./svc.sh status)" >&2
		exit 4
	fi
else
	TOKEN="$(gh api -X POST "repos/$REPO/actions/runners/registration-token" -q .token)"
	./config.sh --unattended --url "https://github.com/$REPO" --token "$TOKEN" \
		--name "$NAME" --labels self-hosted,macOS,ARM64 --replace
	./svc.sh install
	./svc.sh start
fi
echo "runner '$NAME' registered and started (launchd keeps it alive)."
echo "verify: gh api repos/$REPO/actions/runners -q '.runners[].name'"
