Skip to content

Add retry logic for tool downloads#14363

Open
cderv wants to merge 5 commits intomainfrom
fix/ci-download-retry
Open

Add retry logic for tool downloads#14363
cderv wants to merge 5 commits intomainfrom
fix/ci-download-retry

Conversation

@cderv
Copy link
Copy Markdown
Collaborator

@cderv cderv commented Apr 15, 2026

Transient network failures during quarto install (CDN timeouts,
connection resets mid-download) cause hard failures. Seen in CI on
arm64 runners: error reading a body from connection during Chrome
Headless Shell download.

Fix

Two layers of resilience:

Internal retry (src/core/download.ts): Wraps downloadWithProgress
in withRetry — 3 attempts with 2-10s jittered backoff. Only retries
network errors (connection reset, body read failures), not HTTP status
errors. Protects all quarto install commands for all users.

CI retry (.github/workflows/test-install.yml): Bash retry loop on
install steps as defense-in-depth. Uses ::warning:: annotations for
visibility.

Fixes https://github.com/quarto-dev/quarto-cli/actions/runs/24458183539/job/71464601541

cderv added 5 commits April 15, 2026 17:29
Wraps the fetch+stream download in withRetry (3 attempts, 2-10s jittered
backoff). Only retries on network errors (connection reset, body read
failures), not on HTTP status errors which are deterministic.

This protects all `quarto install` commands (TinyTeX, Chrome Headless
Shell, VeraPDF) from transient CDN failures — both in CI and for end
users on flaky connections.
Wraps TinyTeX and Chrome Headless Shell install steps in a 3-attempt
retry loop with 15s delay. Uses GitHub Actions annotations (::warning::
and ::error::) for visibility. Defense-in-depth alongside the internal
download retry added to downloadWithProgress.
Changes to the download logic should trigger the install integration
tests since all tool installs go through downloadWithProgress.
`return fn()` inside an async try block returns the promise directly
without awaiting — rejected promises bypass the catch block entirely.
Changed to `return await fn()` so async failures are caught and retried.

Without this fix, withRetry never retried async callbacks (including
downloadWithProgress and Netlify file uploads).
Skip sleep/warning on final attempt — no retry follows. Also add
src/core/retry.ts to workflow path triggers since retry behavior
directly affects tool installs.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant