b3609d6401
cloud-run.tf + cloud-run-stage.tf: small alignment edits from the dev-env agent's work to match the actual deployed Cloud Run shape. runners/startup.sh: 10-line additions from the gitea-runner agent during initial provisioning - environment setup adjustments discovered when the runner came up the first time. stripe-billing.tf: prior-session work that hadn't been committed, folding it in now to clean the working tree before further changes.
107 lines
4.0 KiB
Bash
107 lines
4.0 KiB
Bash
#!/usr/bin/env bash
|
|
# servers/gcp/runners/startup.sh
|
|
#
|
|
# Boot script for the Gitea Actions runner GCE VM.
|
|
# - Installs docker + git + jq + the Forgejo/Gitea act_runner binary.
|
|
# - Pulls the runner registration token from GCP Secret Manager
|
|
# (the VM's attached service account has secretmanager.secretAccessor on it).
|
|
# - Registers against https://git.neuralplatform.ai with labels matching
|
|
# the workflows that target ubuntu-latest hosts.
|
|
# - Starts act_runner under systemd so it auto-recovers on reboot.
|
|
#
|
|
# Logs land at /var/log/runner-bootstrap.log for debugging from IAP SSH.
|
|
|
|
set -euxo pipefail
|
|
exec > >(tee /var/log/runner-bootstrap.log) 2>&1
|
|
|
|
apt-get update
|
|
# nodejs/npm needed for JavaScript actions like actions/checkout and
|
|
# google-github-actions/auth. python3 is for our inline label-rewrite below.
|
|
apt-get install -y curl ca-certificates docker.io git jq nodejs npm python3
|
|
|
|
# Make docker usable by the unprivileged runner user
|
|
systemctl enable --now docker
|
|
|
|
useradd -m -s /bin/bash runner || true
|
|
usermod -aG docker runner
|
|
|
|
# act_runner — pinned to a known-good release. Bump RUNNER_VERSION when
|
|
# upgrading. The project moved from gitea/act_runner to gitea/runner around
|
|
# the 0.6.x series; the binary inside the asset is still called act_runner.
|
|
# Latest releases at: https://gitea.com/gitea/runner/releases
|
|
RUNNER_VERSION="0.6.1"
|
|
curl -fsSL \
|
|
"https://gitea.com/gitea/runner/releases/download/v${RUNNER_VERSION}/act_runner-${RUNNER_VERSION}-linux-amd64" \
|
|
-o /usr/local/bin/act_runner
|
|
chmod +x /usr/local/bin/act_runner
|
|
|
|
mkdir -p /opt/runner
|
|
chown -R runner:runner /opt/runner
|
|
|
|
# Pull registration token. Fail fast if the secret is missing — the runner
|
|
# is useless without it, and a silent fallback would leave us debugging an
|
|
# unregistered VM later.
|
|
GITEA_RUNNER_TOKEN="$(gcloud secrets versions access latest \
|
|
--secret=gitea-runner-token \
|
|
--project=neuron-785695)"
|
|
|
|
# Generate a baseline config so the daemon has a sane starting point. The
|
|
# register step writes the .runner state file into /opt/runner.
|
|
sudo -u runner /usr/local/bin/act_runner generate-config > /opt/runner/config.yaml
|
|
chown runner:runner /opt/runner/config.yaml
|
|
|
|
cd /opt/runner
|
|
sudo -u runner /usr/local/bin/act_runner register \
|
|
--no-interactive \
|
|
--instance https://git.neuralplatform.ai \
|
|
--token "${GITEA_RUNNER_TOKEN}" \
|
|
--name "gcp-us-central1-runner-1" \
|
|
--labels "ubuntu-latest,ubuntu-22.04,ubuntu-24.04"
|
|
|
|
# Belt-and-braces: act_runner v0.6 has a habit of wrapping bare labels with
|
|
# the default `:docker://docker.gitea.com/runner-images:<label>` shape on
|
|
# first daemon start. We want host execution (build-stage.sh uses the
|
|
# host's Docker socket), so re-write the labels in the persisted state
|
|
# file before we start the daemon.
|
|
python3 - <<'PY'
|
|
import json
|
|
p = "/opt/runner/.runner"
|
|
with open(p) as f: d = json.load(f)
|
|
d["labels"] = ["ubuntu-latest", "ubuntu-22.04", "ubuntu-24.04"]
|
|
with open(p, "w") as f: json.dump(d, f, indent=2)
|
|
PY
|
|
chown runner:runner /opt/runner/.runner
|
|
|
|
cat > /etc/systemd/system/act_runner.service <<'EOF'
|
|
[Unit]
|
|
Description=Gitea Actions runner (act_runner)
|
|
After=network-online.target docker.service
|
|
Wants=network-online.target
|
|
Requires=docker.service
|
|
|
|
[Service]
|
|
Type=simple
|
|
User=runner
|
|
WorkingDirectory=/opt/runner
|
|
# Wipe the act cache on each daemon start. Without this, host-mode
|
|
# execution leaves stale action source trees with .git/objects/pack/*.idx
|
|
# files whose permissions trip the next run's `cp -a` step
|
|
# ("open ...idx: permission denied"). The cache is not load-bearing
|
|
# (act re-downloads actions on demand), so a clean start each restart
|
|
# is the simplest fix.
|
|
ExecStartPre=/bin/sh -c "rm -rf /home/runner/.cache/act/* /home/runner/.cache/act/.* 2>/dev/null || true"
|
|
ExecStart=/usr/local/bin/act_runner daemon --config /opt/runner/config.yaml
|
|
Restart=always
|
|
RestartSec=5
|
|
# Pass through GCP metadata-server access so workflows can call gcloud
|
|
Environment=HOME=/home/runner
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOF
|
|
|
|
systemctl daemon-reload
|
|
systemctl enable --now act_runner
|
|
|
|
echo "act_runner registered and running"
|