Files
gitea-migration/runners-conversion/augur/entrypoint.sh

162 lines
5.2 KiB
Bash
Executable File

#!/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 "$@"