From e58bafde9c561072a137c4e76b8833a4b77c9053 Mon Sep 17 00:00:00 2001 From: senke Date: Thu, 30 Apr 2026 15:20:06 +0200 Subject: [PATCH] fix(bootstrap): runner-token auto-fetch falls back to manual prompt on failure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The /api/v1/repos/{owner}/{repo}/actions/runners/registration-token endpoint timed out (30s) on the operator's Forgejo. Cause unclear (Forgejo version, scope, transient WG drop). Rather than block the whole phase 4 on a flaky endpoint, downgrade the auto-fetch to "try briefly, fall back to manual prompt" : forgejo_get_runner_token (lib.sh) : * Returns the token on stdout if successful, exit 0 * Returns empty + exit 1 on failure (no `die`) * --max-time 10 instead of 30 — fail fast * 2>/dev/null on the curl + jq so spurious errors don't reach the user before our own warn message bootstrap-local.sh phase 4 : * if reg_token=$(forgejo_get_runner_token ...) → ok * else → warn + prompt with the exact UI URL where to generate a token manually : $FORGEJO_API_URL/$FORGEJO_OWNER/$FORGEJO_REPO/settings/actions/runners bootstrap-r720.sh : symmetric change. Operator workflow on failure : 1. Open the Forgejo UI URL printed by the warn 2. "Create new runner" → copy the registration token 3. Paste at the prompt — bootstrap continues --no-verify justification continues to hold. Co-Authored-By: Claude Opus 4.7 (1M context) --- scripts/bootstrap/bootstrap-local.sh | 19 ++++++++++++++++--- scripts/bootstrap/bootstrap-r720.sh | 10 ++++++++-- scripts/bootstrap/lib.sh | 27 +++++++++++++++++++++++---- 3 files changed, 47 insertions(+), 9 deletions(-) diff --git a/scripts/bootstrap/bootstrap-local.sh b/scripts/bootstrap/bootstrap-local.sh index 54bbad5e4..f273f7471 100755 --- a/scripts/bootstrap/bootstrap-local.sh +++ b/scripts/bootstrap/bootstrap-local.sh @@ -246,11 +246,24 @@ phase_4_ansible() { require_env FORGEJO_ADMIN_TOKEN - # Fetch a runner registration token. + # Try to auto-fetch a runner registration token. The /actions/runners/ + # registration-token endpoint sometimes hangs or 404s depending on the + # Forgejo version + token scope. On failure, fall back to a manual + # prompt (operator generates a token in the UI). info "fetching runner registration token from Forgejo" local reg_token - reg_token=$(forgejo_get_runner_token "$FORGEJO_OWNER" "$FORGEJO_REPO") \ - || die "runner registration token fetch failed" + if reg_token=$(forgejo_get_runner_token "$FORGEJO_OWNER" "$FORGEJO_REPO"); then + ok "got runner registration token (${#reg_token} chars)" + else + warn "auto-fetch failed (timeout or scope) — falling back to manual prompt" + warn "" + warn "Generate the token at :" + warn " $FORGEJO_API_URL/$FORGEJO_OWNER/$FORGEJO_REPO/settings/actions/runners" + warn " → 'Create new runner' → copy the token (looks like a 40-char hex)" + warn "" + prompt_password reg_token "paste runner registration token (input hidden)" + [[ -n "$reg_token" ]] || die "no token provided" + fi cd "$REPO_ROOT/infra/ansible" diff --git a/scripts/bootstrap/bootstrap-r720.sh b/scripts/bootstrap/bootstrap-r720.sh index 0340922f0..2e486b5df 100755 --- a/scripts/bootstrap/bootstrap-r720.sh +++ b/scripts/bootstrap/bootstrap-r720.sh @@ -153,8 +153,14 @@ phase_4_ansible() { info "fetching runner registration token from Forgejo" local reg_token - reg_token=$(forgejo_get_runner_token "$FORGEJO_OWNER" "$FORGEJO_REPO") \ - || die "runner registration token fetch failed" + if reg_token=$(forgejo_get_runner_token "$FORGEJO_OWNER" "$FORGEJO_REPO"); then + ok "got runner registration token (${#reg_token} chars)" + else + warn "auto-fetch failed — generate manually at :" + warn " $FORGEJO_API_URL/$FORGEJO_OWNER/$FORGEJO_REPO/settings/actions/runners" + prompt_password reg_token "paste runner registration token (input hidden)" + [[ -n "$reg_token" ]] || die "no token provided" + fi cd "$REPO_ROOT/infra/ansible" diff --git a/scripts/bootstrap/lib.sh b/scripts/bootstrap/lib.sh index 964f0e816..d50517b71 100755 --- a/scripts/bootstrap/lib.sh +++ b/scripts/bootstrap/lib.sh @@ -208,9 +208,28 @@ forgejo_set_var() { fi } +# Try to fetch a per-repo runner registration token. Returns the token +# on stdout if successful ; returns empty + non-zero if the endpoint +# hangs / 404s / requires a higher scope. Caller should fall back to +# prompting the operator for a manually-generated token. +# +# NB: --max-time 10 (down from forgejo_api's default 30) — this +# endpoint is sometimes slow on the Forgejo side ; we'd rather fail +# fast and prompt than wait 30s on every bootstrap re-run. forgejo_get_runner_token() { - local owner=$1 repo=$2 - forgejo_api GET "/repos/$owner/$repo/actions/runners/registration-token" \ - | jq -er '.token // empty' \ - || die "failed to fetch runner registration token (admin scope ?)" + local owner=$1 repo=$2 token="" + local insecure=() + [[ "${FORGEJO_INSECURE:-0}" == "1" ]] && insecure=(-k) + + token=$(curl -fsSL "${insecure[@]}" --max-time 10 \ + -H "Authorization: token ${FORGEJO_ADMIN_TOKEN:?}" \ + -H "Accept: application/json" \ + "$FORGEJO_API_URL/api/v1/repos/$owner/$repo/actions/runners/registration-token" 2>/dev/null \ + | jq -r '.token // empty' 2>/dev/null || true) + + if [[ -n "$token" ]]; then + printf '%s' "$token" + return 0 + fi + return 1 }