From 8fe558f6c1edd6322b9465c1358c7e15b78a106f Mon Sep 17 00:00:00 2001 From: Qiufeng Date: Tue, 4 Aug 2026 15:59:52 +0800 Subject: [PATCH] ops: add one-command Gitea runner setup --- setup-gitea-runner.sh | 139 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100755 setup-gitea-runner.sh diff --git a/setup-gitea-runner.sh b/setup-gitea-runner.sh new file mode 100755 index 0000000..43318c8 --- /dev/null +++ b/setup-gitea-runner.sh @@ -0,0 +1,139 @@ +#!/usr/bin/env bash + +set -Eeuo pipefail + +GITEA_URL="${GITEA_URL:-http://38.76.196.225:10099/}" +GITEA_REPOSITORY="${GITEA_REPOSITORY:-awaioi/ERP}" +RUNNER_IMAGE="${RUNNER_IMAGE:-gitea/runner:3.0.2}" +RUNNER_CONTAINER="${RUNNER_CONTAINER:-gitea-runner}" +RUNNER_VOLUME="${RUNNER_VOLUME:-gitea-runner-data}" +RUNNER_LABELS="${RUNNER_LABELS:-ubuntu-latest:docker://docker.gitea.com/runner-images:ubuntu-latest}" + +log() { + printf '[Gitea Runner] %s\n' "$*" +} + +fail() { + printf '[Gitea Runner] ERROR: %s\n' "$*" >&2 + exit 1 +} + +command -v docker >/dev/null 2>&1 || fail "docker is not installed" +docker info >/dev/null 2>&1 || fail "docker is not running or the current user cannot access it" + +find_gitea_container() { + local container_id image name + + while read -r container_id image name; do + case "$image" in + gitea/gitea:* | gitea/gitea@* | */gitea/gitea:* | */gitea/gitea@* | docker.gitea.com/gitea:* | docker.gitea.com/gitea@*) + printf '%s\n' "$container_id" + return 0 + ;; + esac + done < <(docker ps --format '{{.ID}} {{.Image}} {{.Names}}') + + while read -r container_id name; do + case "$name" in + *runner*) ;; + *gitea*) + printf '%s\n' "$container_id" + return 0 + ;; + esac + done < <(docker ps --format '{{.ID}} {{.Names}}') + + return 1 +} + +GITEA_CONTAINER="$(find_gitea_container || true)" +[[ -n "$GITEA_CONTAINER" ]] || fail "no running Gitea container was found" + +TMP_DIR="$(mktemp -d)" +TOKEN_FILE="$TMP_DIR/runner-token" +BOOTSTRAP_RUNNING=0 + +cleanup() { + if [[ "$BOOTSTRAP_RUNNING" == "1" ]]; then + docker rm -f "$RUNNER_CONTAINER" >/dev/null 2>&1 || true + fi + if [[ -f "$TOKEN_FILE" ]]; then + : >"$TOKEN_FILE" + fi + rm -rf -- "$TMP_DIR" +} +trap cleanup EXIT + +log "Generating a repository-scoped registration token" +if ! docker exec -u git "$GITEA_CONTAINER" gitea actions generate-runner-token \ + --scope "$GITEA_REPOSITORY" | tr -d '\r' | tail -n 1 >"$TOKEN_FILE"; then + fail "Gitea could not generate a runner token" +fi +[[ -s "$TOKEN_FILE" ]] || fail "Gitea returned an empty runner token" +chmod 600 "$TOKEN_FILE" + +log "Pulling $RUNNER_IMAGE" +docker pull "$RUNNER_IMAGE" +docker rm -f "$RUNNER_CONTAINER" >/dev/null 2>&1 || true +docker volume create "$RUNNER_VOLUME" >/dev/null +docker run --rm --entrypoint /bin/rm \ + -v "$RUNNER_VOLUME:/data" \ + "$RUNNER_IMAGE" -f /data/.runner + +log "Registering the runner" +docker run -d \ + --name "$RUNNER_CONTAINER" \ + -v "$RUNNER_VOLUME:/data" \ + -v "$TOKEN_FILE:/run/secrets/gitea_runner_token:ro,Z" \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -e "GITEA_INSTANCE_URL=$GITEA_URL" \ + -e GITEA_RUNNER_REGISTRATION_TOKEN_FILE=/run/secrets/gitea_runner_token \ + -e "GITEA_RUNNER_NAME=erp-release-$(hostname -s)" \ + -e "GITEA_RUNNER_LABELS=$RUNNER_LABELS" \ + -e GITEA_MAX_REG_ATTEMPTS=24 \ + "$RUNNER_IMAGE" >/dev/null +BOOTSTRAP_RUNNING=1 + +READY=0 +for ((attempt = 1; attempt <= 60; attempt++)); do + if docker exec "$RUNNER_CONTAINER" test -s /data/.runner 2>/dev/null; then + READY=1 + break + fi + if [[ "$(docker inspect -f '{{.State.Running}}' "$RUNNER_CONTAINER" 2>/dev/null || true)" != "true" ]]; then + break + fi + sleep 2 +done + +if [[ "$READY" != "1" ]]; then + docker logs --tail 100 "$RUNNER_CONTAINER" >&2 || true + fail "runner registration failed" +fi + +docker logs --tail 30 "$RUNNER_CONTAINER" || true +docker rm -f "$RUNNER_CONTAINER" >/dev/null +BOOTSTRAP_RUNNING=0 +: >"$TOKEN_FILE" + +log "Starting the persistent runner without the registration token" +docker run -d \ + --name "$RUNNER_CONTAINER" \ + --restart unless-stopped \ + -v "$RUNNER_VOLUME:/data" \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -e "GITEA_INSTANCE_URL=$GITEA_URL" \ + -e "GITEA_RUNNER_NAME=erp-release-$(hostname -s)" \ + -e "GITEA_RUNNER_LABELS=$RUNNER_LABELS" \ + "$RUNNER_IMAGE" >/dev/null + +sleep 5 +[[ "$(docker inspect -f '{{.State.Running}}' "$RUNNER_CONTAINER")" == "true" ]] || { + docker logs --tail 100 "$RUNNER_CONTAINER" >&2 || true + fail "runner container stopped after registration" +} + +log "Runner is online; queued release jobs can now continue" +docker ps --filter "name=^/${RUNNER_CONTAINER}$" \ + --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}' +docker logs --tail 80 "$RUNNER_CONTAINER" || true