Files
sciagent/scripts/setup-gitea-runner.sh
Thinh Lam 688fac73e9
CI/CD / backend (push) Failing after 2m8s
CI/CD / frontend (push) Failing after 1m40s
CI/CD / deploy (push) Has been skipped
sciagent code + Gitea Actions CI/CD
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 09:38:30 +07:00

131 lines
5.0 KiB
Bash
Executable File

#!/usr/bin/env bash
# ============================================================================
# Install a Gitea Actions runner (act_runner) on THIS host for tlam89/sciagent.
# Target: the Gitea + app box 103.149.170.102 (run this ON that box, as root).
#
# Registers ONE runner with two labels so the CI/CD pipeline can use both:
# ci -> docker mode (clean ephemeral containers; backend + frontend jobs)
# deploy -> host mode (runs on the host so it can drive `docker compose`)
#
# Prereqs installed/verified here: Docker + compose plugin, Node.js (needed by
# host-mode actions/checkout). Re-runnable: skips steps already done.
#
# Usage (token already minted for this repo; rotate via Gitea if it expires):
# sudo bash setup-gitea-runner.sh
# Override:
# GITEA_URL=http://localhost:3000 RUNNER_TOKEN=xxx bash setup-gitea-runner.sh
# ============================================================================
set -euo pipefail
GITEA_URL="${GITEA_URL:-http://localhost:3000}"
RUNNER_TOKEN="${RUNNER_TOKEN:-aCd3rpPnJTAPVHqsTIme9SaJm3pUbnbyOQqMrt9O}"
RUNNER_NAME="${RUNNER_NAME:-sciagent-box-runner}"
RUNNER_LABELS="${RUNNER_LABELS:-ci:docker://catthehacker/ubuntu:act-22.04,deploy:host}"
ACT_VERSION="${ACT_VERSION:-0.2.11}"
RUNNER_DIR="${RUNNER_DIR:-/opt/act_runner}"
log(){ printf '\n\033[36m==> %s\033[0m\n' "$*"; }
[[ "$(id -u)" -eq 0 ]] || { echo "Run as root (sudo)."; exit 1; }
# --- 1. Docker + compose plugin --------------------------------------------
if ! command -v docker >/dev/null 2>&1; then
log "Installing Docker (get.docker.com convenience script)"
curl -fsSL https://get.docker.com | sh
fi
if ! docker compose version >/dev/null 2>&1; then
log "docker compose plugin missing — installing docker-compose-plugin"
(apt-get update && apt-get install -y docker-compose-plugin) || \
echo "WARN: install the compose plugin manually for your distro."
fi
systemctl enable --now docker >/dev/null 2>&1 || true
docker version --format '{{.Server.Version}}' >/dev/null 2>&1 || { echo "Docker daemon not running"; exit 1; }
# --- 2. Node.js (host-mode jobs run actions/checkout, which needs node) -----
if ! command -v node >/dev/null 2>&1; then
log "Installing Node.js 20"
curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && apt-get install -y nodejs || \
echo "WARN: install Node.js 20 manually if your distro is non-Debian."
fi
# --- 3. Download act_runner -------------------------------------------------
mkdir -p "$RUNNER_DIR"
cd "$RUNNER_DIR"
if [[ ! -x "$RUNNER_DIR/act_runner" ]]; then
log "Downloading act_runner ${ACT_VERSION}"
arch="$(uname -m)"; case "$arch" in x86_64) arch=amd64;; aarch64) arch=arm64;; esac
curl -fsSL -o act_runner \
"https://dl.gitea.com/act_runner/${ACT_VERSION}/act_runner-${ACT_VERSION}-linux-${arch}"
chmod +x act_runner
fi
# --- 4. Register ------------------------------------------------------------
if [[ ! -f "$RUNNER_DIR/.runner" ]]; then
log "Registering with Gitea ($GITEA_URL) labels: $RUNNER_LABELS"
./act_runner register --no-interactive \
--instance "$GITEA_URL" \
--token "$RUNNER_TOKEN" \
--name "$RUNNER_NAME" \
--labels "$RUNNER_LABELS"
else
log ".runner already exists — skipping register"
fi
[[ -f "$RUNNER_DIR/config.yaml" ]] || ./act_runner generate-config > config.yaml
# generate-config injects DEFAULT labels (ubuntu-latest/22.04/20.04) into config.yaml
# which OVERRIDE the --labels passed at registration. Force our labels into config.yaml
# so the daemon advertises ci (docker) + deploy (host), not the defaults.
python3 - "$RUNNER_DIR/config.yaml" "$RUNNER_LABELS" <<'PY'
import sys,re
path,labels=sys.argv[1],sys.argv[2].split(",")
s=open(path).read().splitlines(keepends=True)
o=[];i=0;n=len(s);done=False
while i<n:
if not done and re.match(r'^\s{2}labels:\s*$',s[i]):
o.append(" labels:\n")
for x in labels: o.append(' - "%s"\n'%x)
i+=1
while i<n and re.match(r'^\s{4}(- |#)',s[i]): i+=1
done=True; continue
o.append(s[i]); i+=1
if not done:
o2=[];ins=False
for line in o:
o2.append(line)
if not ins and re.match(r'^runner:\s*$',line):
o2.append(" labels:\n")
for x in labels: o2.append(' - "%s"\n'%x)
ins=True
o=o2
open(path,"w").write("".join(o))
print("config.yaml labels ->", ", ".join(labels))
PY
# --- 5. systemd service -----------------------------------------------------
log "Installing systemd service act_runner"
cat > /etc/systemd/system/act_runner.service <<UNIT
[Unit]
Description=Gitea Actions runner (sciagent)
After=docker.service network-online.target
Wants=docker.service
[Service]
WorkingDirectory=${RUNNER_DIR}
ExecStart=${RUNNER_DIR}/act_runner daemon --config ${RUNNER_DIR}/config.yaml
Restart=always
RestartSec=5
User=root
[Install]
WantedBy=multi-user.target
UNIT
systemctl daemon-reload
systemctl enable --now act_runner
sleep 3
systemctl --no-pager --full status act_runner | head -12
echo
echo "Done. Verify in Gitea: Repo → Settings → Actions → Runners — '$RUNNER_NAME' should be Online."
echo "Logs: journalctl -u act_runner -f"