Skip to content

fix: retry and verify the Nix archive download - #7

Merged
otavio merged 1 commit into
mainfrom
fix/retry-nix-archive-download
Aug 13, 2026
Merged

fix: retry and verify the Nix archive download#7
otavio merged 1 commit into
mainfrom
fix/retry-nix-archive-download

Conversation

@otavio

@otavio otavio commented Aug 13, 2026

Copy link
Copy Markdown
Member

What fails today

nix-quick-install-action pipes its download straight into tar:

curl -sL --retry 3 --retry-connrefused "$url" | tar -x -I unzstd -C /nix

When GitHub serves a truncated release asset, the short body has already
reached tar, so curl --retry cannot help. The job dies with:

zstd: /*stdin*\: unexpected end of file
tar: Error is not recoverable: exiting now

Every later step reports outcome=skipped, so the reported failure names the
caller's job — gofmt, lint — and points at the pull request, although the
pull request is not the cause. Reported downstream as InoBram/inobramxd#488.

What this does

Fetch the same archive to a file first, then hand the verified copy to
nix-quick-install-action through its nix_archives_url input.

  • Three bounded attempts with a growing wait, and an integrity check on each.
    A body that is short but well-formed at the transfer level is the case only
    the integrity check can catch; it now drives a retry, not a job failure.
  • A download that never arrives intact fails with a message naming the URL,
    not the extraction.
  • Only a 404 skips the retry — it means nix-version is not a version the
    pinned release ships. A 5xx or an expired asset redirect is the transient
    class the retry exists for.
  • --speed-limit/--speed-time bound a stalled body, so the retry is bounded
    in wall time and not only in attempts.

The pre-fetch has to build the same URL as the pinned action, so the Nix
version becomes an explicit nix-version input (default 2.29.2, the pinned
release's own default) passed to both sides. Both actions install Nix, so both
carry the pre-fetch.

Tests

tests/prefetch-nix-archive.test.sh — 26 assertions, driven by a local server
that reproduces each failure mode. It installs no Nix, so it still reports when
the Nix install itself is broken.

Covered: a healthy download; a silently truncated body (retried, not accepted);
an always-truncated body (fails, message names the URL and the attempt count,
leaves no archive behind); a 404 (one request, no retry); a 5xx (retried to
exhaustion); the reported output path; and two static guards — each manifest's
pin matches the release tag it pre-fetches, and the path each manifest uses
resolves to the script.

The nix-version job installs a non-default Nix (2.28.5) and asserts
nix --version reports it, which proves the pre-fetched archive is the
installed one.

After merge

This needs a release for @v1 callers to get it: docs/releasing.md.

nix-quick-install-action pipes its download straight into tar, so a
truncated release asset cannot be retried: curl's own --retry cannot
help once a short body has already reached tar. The job then dies with
"zstd: unexpected end of file" before any project tool runs, and the
reported failure names the caller's job -- gofmt, lint -- rather than
the download that actually failed.

Fetch the archive to a file first, three bounded attempts with a growing
wait and an integrity check on each, then hand the verified copy to
nix-quick-install-action through its nix_archives_url input. A body that
is short but well-formed at the transfer level is the case only the
integrity check can catch, and it now drives a retry instead of a job
failure. A download that never arrives intact fails with a message
naming the URL. Only a 404 skips the retry: it means nix-version is not
a version the pinned release ships, while a 5xx or an expired asset
redirect is exactly the transient class the retry exists for.
--speed-limit/--speed-time bound a stalled body, so the retry is bounded
in wall time and not just in attempts.

The pre-fetch has to build the same URL as the pinned action, so the Nix
version becomes an explicit input (nix-version, defaulting to the pinned
release's own default) passed to both sides, and the release tag is
carried next to each pin. Both actions install Nix, so both carry the
pre-fetch, and the tests fail if a pin drifts from its release tag or if
a manifest reaches the script by a path that does not resolve.

The tests run on a bare runner with no Nix, so they still report when
the Nix install itself is broken.

Refs: InoBram/inobramxd#488
@otavio
otavio merged commit ff26e0e into main Aug 13, 2026
13 checks passed
@otavio
otavio deleted the fix/retry-nix-archive-download branch August 13, 2026 17:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant