fix(install): resilient latest-version fetch (both installers)

Merged
MD
5mo ago
+136-34

What

Follow-up to #930 (reported by @ralphstodomingo): a transient 504 from api.github.com/.../releases/latest — or the 60/hr/IP unauthenticated rate limit — aborted the whole install with Failed to fetch version information, even though the download uses releases/latest/download/<file> (GitHub resolves "latest" server-side, no API call needed). The API response only feeds the version-string display and the already-installed short-circuit.

This issue exists in both installers (install bash:206-213 and install.ps1), so both are fixed here for parity.

Stacked on feat/windows-powershell-installer (sibling to #942) because install.ps1 isn't on main yet.

Changes (latest path, both installers)

  • Retry the releases/latest API call up to 3× with linear backoff (bash uses curl --fail so a 504 retries instead of parsing an error body).
  • On continued failure, degrade gracefully: print a muted notice and install latest anyway (banner shows latest).
  • Only short-circuit as "already installed" on a real version match — never treat empty==empty (unresolved version + unreadable binary) as installed.
  • Pinned -Version/--version unchanged: a genuine 404 still hard-fails.

Note (from the same review comment): the exit 0-closes-an-interactive-window quirk under irm | iex is PowerShell-only and only affects pasting directly into an interactive shell (not the documented powershell -c "…" form); curl | bash exits in a subshell. Left as-is — low severity, no parity gap to fix.

Verification

  • bash -n install clean; install.ps1 parses clean and the Pester suite (6/6) still passes on PowerShell 7.6.2.
  • version-fetch-resilience.test.ts pins retry + graceful-degrade in both installers (57 pass across the install/branding set).
  • The degrade path isn't exercised end-to-end (forcing an API failure then proceeds to a 268 MB download); covered by content assertions + parse + no-regression.

🤖 Generated with Claude Code


Summary by cubic

Makes the “latest” install path resilient in both installers and fixes Windows parsing on PowerShell 5.1. Installs no longer fail when the GitHub releases API blips; they retry and proceed with “latest”.

  • Bug Fixes
    • Latest path (both): retry releases/latest up to 3 times with backoff and a 10s timeout; on failure, continue and show “latest”. Pinned --version/-Version installs unchanged.
    • Correct “already installed” check: only short-circuit on a real version match; in PowerShell reset $specificVersion to $null on degrade to avoid empty==empty.
    • Windows: make install.ps1 ASCII-only so it parses on Windows PowerShell 5.1.
    • Tests: add packages/opencode/test/install/version-fetch-resilience.test.ts to pin retry, timeout, and graceful-degrade; update packages/opencode/test/release-validation/windows-installer-930-codex.test.ts to expect degrade (not hard-fail) on latest-version fetch.

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Improved “latest release” resolution in both installers: transient GitHub API failures are retried and no longer stop the installation process.
    • Prevented incorrect “already installed” skipping when version resolution fails, and updated install status to show latest when the resolved tag isn’t available.
  • Tests

    • Updated and added automated coverage to confirm both bash and PowerShell installers degrade gracefully during GitHub API failures and behave correctly afterward.