sciagent code + Gitea Actions CI/CD
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Executable
+130
@@ -0,0 +1,130 @@
|
||||
#!/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"
|
||||
Reference in New Issue
Block a user