#!/usr/bin/env bash set -euo pipefail # ── setup_runner_mac.sh ─────────────────────────────────────────────────────── # Sets up act_runner as a host-mode runner on macOS for iOS CI/CD. # Installs the binary, generates a config, registers against Gitea, # and installs a LaunchDaemon so the runner starts at boot. # # Usage: sudo ./setup_runner_mac.sh # Example: sudo ./setup_runner_mac.sh mac-runner-1 # ───────────────────────────────────────────────────────────────────────────── usage() { echo "Usage: sudo $0 " exit 1 } [[ $# -ne 1 ]] && usage [[ "$EUID" -ne 0 ]] && { echo "ERROR: run with sudo"; exit 1; } RUNNER_NAME="$1" GITEA_URL="https://gitea.kalekber.cc/" REGISTRATION_TOKEN="AboxpDKWx7gizwJ9xeheHVqKjj9J9N9BgyX96wvu" CACHE_PORT=8088 INSTALL_DIR="/usr/local/bin" WORK_DIR="/var/lib/act_runner" CONFIG_PATH="/etc/act_runner/config.yaml" LAUNCHDAEMON_PLIST="/Library/LaunchDaemons/com.gitea.act_runner.plist" # ── detect Mac LAN IP ───────────────────────────────────────────────────────── HOST_IP=$(ipconfig getifaddr en0 2>/dev/null || ipconfig getifaddr en1 2>/dev/null || echo "") if [[ -z "$HOST_IP" ]]; then echo "ERROR: could not detect LAN IP via en0/en1. Set cache.host manually in $CONFIG_PATH" HOST_IP="127.0.0.1" fi echo "Host LAN IP: $HOST_IP" # ── download act_runner binary ──────────────────────────────────────────────── ARCH=$(uname -m) if [[ "$ARCH" == "arm64" ]]; then BINARY_URL="https://gitea.com/gitea/act_runner/releases/download/v0.3.0/act_runner-0.3.0-darwin-arm64" else BINARY_URL="https://gitea.com/gitea/act_runner/releases/download/v0.3.0/act_runner-0.3.0-darwin-amd64" fi echo "Downloading act_runner for $ARCH..." curl -fsSL "$BINARY_URL" -o "$INSTALL_DIR/act_runner" chmod +x "$INSTALL_DIR/act_runner" echo "Installed: $("$INSTALL_DIR/act_runner" --version)" # ── create working directory ────────────────────────────────────────────────── mkdir -p "$WORK_DIR" mkdir -p "$(dirname "$CONFIG_PATH")" # ── generate and patch config ───────────────────────────────────────────────── "$INSTALL_DIR/act_runner" generate-config > "$CONFIG_PATH" # Patch labels, cache host/port, and capacity awk -v host="$HOST_IP" -v port="$CACHE_PORT" ' /^runner:/ { in_runner=1; in_cache=0 } /^cache:/ { in_cache=1; in_runner=0 } /^[a-z]/ && !/^runner:/ && !/^cache:/ { in_runner=0; in_cache=0 } in_runner && /capacity:/ { $0 = " capacity: 1" } in_runner && /labels:/ { print; skip_labels=1; next } skip_labels && /^ - / { next } skip_labels && !/^ - / { skip_labels=0 print " - \"macos-latest:host\"" print " - \"macos-14:host\"" } in_cache && /enabled:/ { $0 = " enabled: true" } in_cache && /host:/ { $0 = " host: \"" host "\"" } in_cache && /port:/ { $0 = " port: " port; in_cache=0 } { print } ' "$CONFIG_PATH" > "${CONFIG_PATH}.tmp" && mv "${CONFIG_PATH}.tmp" "$CONFIG_PATH" echo "Config patched: labels=macos-latest:host, cache=$HOST_IP:$CACHE_PORT" # ── register runner ─────────────────────────────────────────────────────────── echo "Registering runner '$RUNNER_NAME'..." "$INSTALL_DIR/act_runner" register \ --no-interactive \ --config "$CONFIG_PATH" \ --instance "$GITEA_URL" \ --token "$REGISTRATION_TOKEN" \ --name "$RUNNER_NAME" \ --labels "macos-latest:host,macos-14:host" # Copy .runner file to work dir if it was created in cwd [[ -f ".runner" ]] && cp .runner "$WORK_DIR/.runner" # ── install LaunchDaemon ────────────────────────────────────────────────────── # PATH must include Homebrew + Xcode tools so xcodebuild, xcrun, npm, etc. are found. HOMEBREW_PREFIX=$([ "$ARCH" = "arm64" ] && echo "/opt/homebrew" || echo "/usr/local") cat > "$LAUNCHDAEMON_PLIST" < Label com.gitea.act_runner ProgramArguments ${INSTALL_DIR}/act_runner daemon --config ${CONFIG_PATH} RunAtLoad KeepAlive WorkingDirectory ${WORK_DIR} StandardOutPath ${WORK_DIR}/act_runner.log StandardErrorPath ${WORK_DIR}/act_runner.err EnvironmentVariables PATH ${HOMEBREW_PREFIX}/bin:${HOMEBREW_PREFIX}/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Applications/Xcode.app/Contents/Developer/usr/bin HOME ${WORK_DIR} PLIST echo "LaunchDaemon written to $LAUNCHDAEMON_PLIST" # ── load the daemon ─────────────────────────────────────────────────────────── launchctl unload "$LAUNCHDAEMON_PLIST" 2>/dev/null || true launchctl load "$LAUNCHDAEMON_PLIST" echo "Runner '$RUNNER_NAME' started via LaunchDaemon" echo "" echo "Useful commands:" echo " View logs: tail -f $WORK_DIR/act_runner.log" echo " Stop runner: sudo launchctl unload $LAUNCHDAEMON_PLIST" echo " Start runner: sudo launchctl load $LAUNCHDAEMON_PLIST"