fix: retry transient GitHub API failures when minting the runner token - #53
Merged
Conversation
A single transient GitHub API 503 took the runner down for ~23h (2026-07-19 20:07 EDT). The registrar's `curl -fsS ... | jq -re` piped an empty body into jq on the 503, jq exited 4, the registrar container died, the runner never started (gated on service_healthy), and systemd's StartLimitBurst=5 parked the whole unit until manual recovery. A momentary upstream blip became a multi-hour outage with no self-recovery. Wrap both GitHub API calls (installation access token, registration token) in a bounded retry with backoff: - retry on curl-level failures and HTTP 429/5xx (3s, 6s, 9s backoff), - fail fast on a genuine 4xx (bad creds/permissions won't fix on retry), - capture and log the real HTTP status, so a failure reads as "transient HTTP 503" instead of an opaque jq exit 4. Retry budget (~21s of sleeps + fast 5xx responses) stays well under the registrar healthcheck's ~90s window, so a slow mint is never marked unhealthy. No compose or systemd changes; RestartSec stays at 5s to keep the normal ephemeral job-cycle fast. Verified with a shell test double under dash and busybox ash covering: 503->503->200 (recovers), 401 (fails fast, 1 call), persistent 500 (exhausts 4 attempts), and curl network error (treated as transient).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What / why
A single transient GitHub API 503 took the runner down for ~23h (outage started
2026-07-19 20:07:43 EDT; Healthchecks correctly alerted).Failure chain: registrar's
curl -fsS ... | jq -repipes an empty body intojqon the 503 →jqexits 4 → registrar container dies → runner never starts (depends_on: service_healthy) →--abort-on-container-exit→ systemd restart storm →StartLimitBurst=5parks the unit → no self-recovery. A momentary upstream blip became a multi-hour outage.The fix
Wrap both GitHub API calls (installation access token, registration token) in a bounded retry helper:
429/5xxwith backoff (3s, 6s, 9s).4xx— bad creds/permissions won't recover on retry.transient HTTP 503instead of an opaquejqexit 4.Scope / non-goals
RestartSecstays5s(it also governs the normal ephemeral job-cycle — raising it would add latency to every job pickup).StartLimitBurst=5is intentionally left to still park on genuinely permanent faults (deprecated binary, revoked creds) and alert.Testing
Shell test double run under
dashand busyboxash(Alpine prod shell), all passing:503, 503, 200(this outage)401bad creds500000, retriedSyntax validated under
sh -nanddash -n.Deploy note
Not yet deployed. Live service was already recovered via
reset-failed+startand is draining the queued-job backlog. Deploy (ansiblegithub_runner_refbump) should wait until the runner is idle, since a restart cancels an in-flight ephemeral job.