Files
gitea-migration/runners-conversion/periodVault/actions-local.sh

211 lines
5.9 KiB
Bash
Executable File

#!/usr/bin/env bash
# actions-local.sh
# Local GitHub Actions self-hosted runner lifecycle helper.
set -euo pipefail
RUNNER_DIR="${RUNNER_DIR:-$HOME/.periodvault-actions-runner}"
RUNNER_LABELS="${RUNNER_LABELS:-periodvault}"
RUNNER_NAME="${RUNNER_NAME:-$(hostname)-periodvault}"
RUNNER_WORKDIR="${RUNNER_WORKDIR:-_work}"
RUNNER_PID_FILE="${RUNNER_PID_FILE:-$RUNNER_DIR/.runner.pid}"
RUNNER_LOG_FILE="${RUNNER_LOG_FILE:-$RUNNER_DIR/runner.log}"
if git config --get remote.origin.url >/dev/null 2>&1; then
ORIGIN_URL="$(git config --get remote.origin.url)"
else
ORIGIN_URL=""
fi
if [[ -n "$ORIGIN_URL" && "$ORIGIN_URL" =~ ^git@github\.com:(.*)\.git$ ]]; then
RUNNER_URL_DEFAULT="https://github.com/${BASH_REMATCH[1]}"
elif [[ -n "$ORIGIN_URL" && "$ORIGIN_URL" =~ ^https://github\.com/.*$ ]]; then
RUNNER_URL_DEFAULT="${ORIGIN_URL%.git}"
else
RUNNER_URL_DEFAULT=""
fi
RUNNER_URL="${RUNNER_URL:-$RUNNER_URL_DEFAULT}"
ACT_WORKFLOW="${ACT_WORKFLOW:-.github/workflows/ci.yml}"
ACT_IMAGE="${ACT_IMAGE:-ghcr.io/catthehacker/ubuntu:act-latest}"
ACT_DOCKER_SOCKET="${ACT_DOCKER_SOCKET:-/Users/s/.colima/augur-actions/docker.sock}"
ACT_DAEMON_SOCKET="${ACT_DAEMON_SOCKET:-/var/run/docker.sock}"
ACT_DOCKER_CONFIG="${ACT_DOCKER_CONFIG:-/tmp/act-docker-config}"
usage() {
cat <<EOF
Usage: ./scripts/actions-local.sh <setup|start|stop|status|remove|run> [job-id]
Environment variables:
RUNNER_DIR Runner installation directory (default: $RUNNER_DIR)
RUNNER_URL GitHub repo/org URL for runner registration
RUNNER_TOKEN Registration/removal token (required for setup/remove)
RUNNER_LABELS Runner labels (default: $RUNNER_LABELS)
RUNNER_NAME Runner name (default: $RUNNER_NAME)
RUNNER_WORKDIR Runner work dir (default: $RUNNER_WORKDIR)
Local Actions execution (`run`) variables:
ACT_WORKFLOW Workflow file path (default: $ACT_WORKFLOW)
ACT_IMAGE Container image for self-hosted label mapping (default: $ACT_IMAGE)
ACT_DOCKER_SOCKET Docker host socket (default: $ACT_DOCKER_SOCKET)
ACT_DAEMON_SOCKET In-container daemon socket path (default: $ACT_DAEMON_SOCKET)
ACT_DOCKER_CONFIG Docker config dir used by act (default: $ACT_DOCKER_CONFIG)
EOF
}
ensure_runner_binaries() {
if [[ ! -x "$RUNNER_DIR/config.sh" || ! -x "$RUNNER_DIR/run.sh" ]]; then
echo "[actions-local] Missing runner binaries in $RUNNER_DIR."
echo "[actions-local] Download and extract GitHub runner there first."
exit 1
fi
}
ensure_runner_url() {
if [[ -z "$RUNNER_URL" ]]; then
echo "[actions-local] RUNNER_URL is empty."
echo "[actions-local] Set RUNNER_URL=https://github.com/<owner>/<repo> and retry."
exit 1
fi
}
require_token() {
if [[ -z "${RUNNER_TOKEN:-}" ]]; then
echo "[actions-local] RUNNER_TOKEN is required for this command."
exit 1
fi
}
cmd_setup() {
ensure_runner_binaries
ensure_runner_url
require_token
if [[ -f "$RUNNER_DIR/.runner" ]]; then
echo "[actions-local] Runner already configured in $RUNNER_DIR (idempotent no-op)."
exit 0
fi
(
cd "$RUNNER_DIR"
./config.sh \
--unattended \
--replace \
--url "$RUNNER_URL" \
--token "$RUNNER_TOKEN" \
--name "$RUNNER_NAME" \
--labels "$RUNNER_LABELS" \
--work "$RUNNER_WORKDIR"
)
echo "[actions-local] Runner configured."
}
cmd_start() {
ensure_runner_binaries
if [[ ! -f "$RUNNER_DIR/.runner" ]]; then
echo "[actions-local] Runner not configured. Run setup first."
exit 1
fi
if [[ -f "$RUNNER_PID_FILE" ]] && kill -0 "$(cat "$RUNNER_PID_FILE")" >/dev/null 2>&1; then
echo "[actions-local] Runner already running (pid $(cat "$RUNNER_PID_FILE"))."
exit 0
fi
(
cd "$RUNNER_DIR"
nohup ./run.sh >"$RUNNER_LOG_FILE" 2>&1 &
echo $! >"$RUNNER_PID_FILE"
)
echo "[actions-local] Runner started (pid $(cat "$RUNNER_PID_FILE"))."
echo "[actions-local] Log: $RUNNER_LOG_FILE"
}
cmd_stop() {
if [[ ! -f "$RUNNER_PID_FILE" ]]; then
echo "[actions-local] Runner is not running."
exit 0
fi
pid="$(cat "$RUNNER_PID_FILE")"
if kill -0 "$pid" >/dev/null 2>&1; then
kill "$pid"
rm -f "$RUNNER_PID_FILE"
echo "[actions-local] Runner stopped (pid $pid)."
else
rm -f "$RUNNER_PID_FILE"
echo "[actions-local] Runner pid file was stale; cleaned up."
fi
}
cmd_status() {
if [[ -f "$RUNNER_DIR/.runner" ]]; then
echo "[actions-local] configured: yes"
else
echo "[actions-local] configured: no"
fi
if [[ -f "$RUNNER_PID_FILE" ]] && kill -0 "$(cat "$RUNNER_PID_FILE")" >/dev/null 2>&1; then
echo "[actions-local] running: yes (pid $(cat "$RUNNER_PID_FILE"))"
else
echo "[actions-local] running: no"
fi
echo "[actions-local] runner-dir: $RUNNER_DIR"
echo "[actions-local] runner-labels: $RUNNER_LABELS"
}
cmd_remove() {
ensure_runner_binaries
require_token
if [[ ! -f "$RUNNER_DIR/.runner" ]]; then
echo "[actions-local] Runner is not configured."
exit 0
fi
(
cd "$RUNNER_DIR"
./config.sh remove --token "$RUNNER_TOKEN"
)
echo "[actions-local] Runner registration removed."
}
cmd_run() {
local job="${1:-sdd-gate}"
if ! command -v act >/dev/null 2>&1; then
echo "[actions-local] 'act' is required for local workflow execution."
exit 1
fi
mkdir -p "$ACT_DOCKER_CONFIG"
if [[ ! -f "$ACT_DOCKER_CONFIG/config.json" ]]; then
printf '{"auths":{}}\n' >"$ACT_DOCKER_CONFIG/config.json"
fi
DOCKER_CONFIG="$ACT_DOCKER_CONFIG" \
DOCKER_HOST="unix://$ACT_DOCKER_SOCKET" \
act -W "$ACT_WORKFLOW" \
-j "$job" \
-P "self-hosted=$ACT_IMAGE" \
-P "macos-latest=$ACT_IMAGE" \
--container-architecture linux/amd64 \
--container-daemon-socket "$ACT_DAEMON_SOCKET"
}
COMMAND="${1:-}"
case "$COMMAND" in
setup) cmd_setup ;;
start) cmd_start ;;
stop) cmd_stop ;;
status) cmd_status ;;
remove) cmd_remove ;;
run) cmd_run "${2:-}" ;;
""|--help|-h) usage ;;
*)
echo "[actions-local] Unknown command: $COMMAND"
usage
exit 1
;;
esac