fix(bootstrap): runner-token auto-fetch falls back to manual prompt on failure

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) <noreply@anthropic.com>
This commit is contained in:
senke 2026-04-30 15:20:06 +02:00
parent a881be9dad
commit e58bafde9c
3 changed files with 47 additions and 9 deletions

View file

@ -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"

View file

@ -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"

View file

@ -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
}