## What changed
- Make the shell and PowerShell installers download release metadata and assets from `releases.openai.com` by default, with bounded request timeouts.
- Fall back to GitHub Releases when metadata is unusable, required assets are missing, or downloaded assets fail checksum or manifest validation.
- Document `CODEX_INSTALLER_USE_RELEASES_OPENAI_COM=false` for opting out of the default release source.
## Testing
- Cover default-source installation, malformed and incomplete metadata, version mismatches, corrupt assets, invalid checksums, incomplete manifests, and GitHub fallback failures in the shell installer tests.
GitOrigin-RevId: 1c65d527ca79761358c3a4cd7a5fd675e1ef75b2
## What changed
- Let the shell and PowerShell installers resolve metadata and download assets from `releases.openai.com` when `CODEX_INSTALLER_USE_RELEASES_OPENAI_COM` is enabled.
- Fall back to GitHub Releases when metadata or asset downloads from the alternate source are unavailable.
- Verify that an installed or cached Codex binary reports the resolved version before activating it.
## Testing
- Cover latest-release installation, asset fallback, mismatched binary versions, and reuse of a cached legacy package in the shell installer tests.
GitOrigin-RevId: 48c57d3377fbc6b0903570c665041bb465ca6f4c
# Summary
GitHub's latest-release endpoint can return compact, single-line JSON.
The standalone installer treated release metadata as line-oriented text,
so those responses could make asset lookup fail even though the
requested assets were present.
The regression was introduced by
[#31056](https://github.com/openai/codex/pull/31056). That change reused
the `/releases/latest` metadata response for both version resolution and
asset lookup, exposing the existing formatting-sensitive asset parser to
compact responses from that endpoint.
This change parses the release metadata once with a one-pass POSIX awk
scanner. The scanner tracks JSON strings and nesting, extracts the root
release tag plus direct asset name/digest pairs, and produces the same
result regardless of whitespace or object field order. It uses POSIX
`fold` to bound awk record sizes so compact responses stay fast across
awk implementations.
Fixes#31520.
## Changes
- replace line-oriented release metadata matching with structure-aware
parsing
- reuse the parsed metadata for latest-version and asset-digest lookup
- add regression coverage for compact JSON, reordered fields, nested
decoys, and JSON-looking release text
## Design decisions
- Keep the installer dependency-free by using standard POSIX tools
already required by the shell installer.
- Parse only the GitHub release fields the installer consumes, in one
pass, instead of vendoring a general JSON library.
- Preserve asset-object boundaries so nested or string-encoded `name`
and `digest` fields cannot be mistaken for release assets.
## Testing
- Tests: focused installer suite locally and on Linux.
- Smoke tests: real pretty and compact GitHub release metadata,
latest-release resolution, and checksum-asset selection.
- Portability: macOS awk plus Linux gawk, mawk, and nawk.
- Stress coverage: randomized formatting and field order, adversarial
nested/string content, and a synthetic 2,000-asset compact response.
## Why
The standalone installers currently perform separate unauthenticated
GitHub REST API lookups while resolving the latest version, locating the
platform package, locating its checksum manifest, and retrieving asset
digests. A single install can therefore make up to four release-metadata
requests.
When GitHub's shared unauthenticated rate limit is exhausted, valid
releases fail to install. The shell installer also suppresses the
metadata request failure while probing assets, so a `403` is misreported
as though the release assets do not exist. This makes the failure both
more likely and harder to diagnose.
Fixes#28538.
## What changed
- Resolve the selected version and fetch its release metadata together.
- Reuse that one metadata response for package, checksum, and
legacy-package selection in both `install.sh` and `install.ps1`.
- Report metadata fetch failures as possible GitHub availability or
rate-limit failures instead of missing assets.
- Add a mocked-`curl` regression suite covering exact releases,
`latest`, and a simulated metadata `403`, and run it in `repo-checks`.
For `latest`, the metadata returned by `/releases/latest` now supplies
both the resolved version and the asset list. For an explicitly selected
version, the installer makes one request to that release's tag endpoint.
## Verification
- `python3 -m unittest discover -s scripts/install -p 'test_*.py' -v`
- `sh -n scripts/install/install.sh`
- Parsed `scripts/install/install.ps1` with the PowerShell language
parser.
## Scope
This change reduces GitHub API usage and preserves the underlying error,
but it does not move release artifacts away from GitHub's CDN.