feat: add runner conversion scripts and strengthen cutover automation
This commit is contained in:
161
runners-conversion/augur/entrypoint.sh
Executable file
161
runners-conversion/augur/entrypoint.sh
Executable file
@@ -0,0 +1,161 @@
|
||||
#!/usr/bin/env bash
|
||||
# entrypoint.sh — Container startup script for the GitHub Actions runner.
|
||||
#
|
||||
# Lifecycle:
|
||||
# 1. Validate required environment variables
|
||||
# 2. Generate a short-lived registration token from GITHUB_PAT
|
||||
# 3. Configure the runner in ephemeral mode (one job, then exit)
|
||||
# 4. Trap SIGTERM/SIGINT for graceful deregistration
|
||||
# 5. Start the runner (run.sh)
|
||||
#
|
||||
# Docker's restart policy (restart: unless-stopped) brings the container
|
||||
# back after each job completes, repeating this cycle.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Configuration
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
RUNNER_DIR="/home/runner/actions-runner"
|
||||
RUNNER_LABELS="${RUNNER_LABELS:-self-hosted,Linux,X64}"
|
||||
RUNNER_GROUP="${RUNNER_GROUP:-default}"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Helpers
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
log() {
|
||||
printf '[entrypoint] %s\n' "$*"
|
||||
}
|
||||
|
||||
die() {
|
||||
printf '[entrypoint] ERROR: %s\n' "$*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Environment validation — fail fast with clear errors
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
validate_env() {
|
||||
local missing=()
|
||||
|
||||
[[ -z "${GITHUB_PAT:-}" ]] && missing+=("GITHUB_PAT")
|
||||
[[ -z "${REPO_URL:-}" ]] && missing+=("REPO_URL")
|
||||
[[ -z "${RUNNER_NAME:-}" ]] && missing+=("RUNNER_NAME")
|
||||
|
||||
if [[ ${#missing[@]} -gt 0 ]]; then
|
||||
die "Missing required environment variables: ${missing[*]}. Check your .env and envs/*.env files."
|
||||
fi
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Token generation — PAT → short-lived registration token
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
generate_token() {
|
||||
# Extract OWNER/REPO from the full URL.
|
||||
# Supports: https://github.com/OWNER/REPO or https://github.com/OWNER/REPO.git
|
||||
local repo_slug
|
||||
repo_slug="$(printf '%s' "$REPO_URL" \
|
||||
| sed -E 's#^https?://github\.com/##' \
|
||||
| sed -E 's/\.git$//')"
|
||||
|
||||
if [[ -z "$repo_slug" ]] || ! printf '%s' "$repo_slug" | grep -qE '^[^/]+/[^/]+$'; then
|
||||
die "Could not parse OWNER/REPO from REPO_URL: $REPO_URL"
|
||||
fi
|
||||
|
||||
log "Generating registration token for ${repo_slug}..."
|
||||
|
||||
local response
|
||||
response="$(curl -fsSL \
|
||||
-X POST \
|
||||
-H "Authorization: token ${GITHUB_PAT}" \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
"https://api.github.com/repos/${repo_slug}/actions/runners/registration-token")"
|
||||
|
||||
REG_TOKEN="$(printf '%s' "$response" | jq -r '.token // empty')"
|
||||
|
||||
if [[ -z "$REG_TOKEN" ]]; then
|
||||
die "Failed to generate registration token. Check that GITHUB_PAT has 'repo' scope and is valid."
|
||||
fi
|
||||
|
||||
log "Registration token obtained (expires in 1 hour)."
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Cleanup — deregister runner on container stop
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
cleanup() {
|
||||
log "Caught signal, removing runner registration..."
|
||||
|
||||
# Generate a removal token (different from registration token)
|
||||
local repo_slug
|
||||
repo_slug="$(printf '%s' "$REPO_URL" \
|
||||
| sed -E 's#^https?://github\.com/##' \
|
||||
| sed -E 's/\.git$//')"
|
||||
|
||||
local remove_token
|
||||
remove_token="$(curl -fsSL \
|
||||
-X POST \
|
||||
-H "Authorization: token ${GITHUB_PAT}" \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
"https://api.github.com/repos/${repo_slug}/actions/runners/remove-token" \
|
||||
| jq -r '.token // empty' || true)"
|
||||
|
||||
if [[ -n "$remove_token" ]]; then
|
||||
"${RUNNER_DIR}/config.sh" remove --token "$remove_token" 2>/dev/null || true
|
||||
log "Runner deregistered."
|
||||
else
|
||||
log "WARNING: Could not obtain removal token. Runner may appear stale in GitHub until it expires."
|
||||
fi
|
||||
|
||||
exit 0
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Main
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
main() {
|
||||
validate_env
|
||||
generate_token
|
||||
|
||||
# Trap signals for graceful shutdown
|
||||
trap cleanup SIGTERM SIGINT
|
||||
|
||||
# Remove stale configuration from previous run.
|
||||
# On container restart (vs recreate), the runner's writable layer persists
|
||||
# and config.sh refuses to re-configure if .runner already exists.
|
||||
# The --replace flag only handles server-side name conflicts, not this local check.
|
||||
if [[ -f "${RUNNER_DIR}/.runner" ]]; then
|
||||
log "Removing stale runner configuration from previous run..."
|
||||
rm -f "${RUNNER_DIR}/.runner" "${RUNNER_DIR}/.credentials" "${RUNNER_DIR}/.credentials_rsaparams"
|
||||
fi
|
||||
|
||||
log "Configuring runner '${RUNNER_NAME}' for ${REPO_URL}..."
|
||||
log "Labels: ${RUNNER_LABELS}"
|
||||
log "Group: ${RUNNER_GROUP}"
|
||||
|
||||
"${RUNNER_DIR}/config.sh" \
|
||||
--url "${REPO_URL}" \
|
||||
--token "${REG_TOKEN}" \
|
||||
--name "${RUNNER_NAME}" \
|
||||
--labels "${RUNNER_LABELS}" \
|
||||
--runnergroup "${RUNNER_GROUP}" \
|
||||
--work "/home/runner/_work" \
|
||||
--ephemeral \
|
||||
--unattended \
|
||||
--replace
|
||||
|
||||
log "Runner configured. Starting..."
|
||||
|
||||
# exec replaces the shell with the runner process.
|
||||
# The runner picks up one job, executes it, and exits.
|
||||
# Docker's restart policy restarts the container for the next job.
|
||||
exec "${RUNNER_DIR}/run.sh"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user