Skip to content

Guard npm update readiness#19389

Merged
shijie-oai merged 1 commit intomainfrom
codex/npm-update-readiness
Apr 26, 2026
Merged

Guard npm update readiness#19389
shijie-oai merged 1 commit intomainfrom
codex/npm-update-readiness

Conversation

@shijie-oai
Copy link
Copy Markdown
Collaborator

@shijie-oai shijie-oai commented Apr 24, 2026

Why

For npm/Bun-managed installs, the update prompt was treating the latest GitHub release as ready to install. During the 0.124.0 release, GitHub and npm visibility were not atomic: the root npm wrapper could become visible before the npm registry marked that version as the package latest. That left a window where users could be prompted to upgrade before npm was ready for the release.

What changed

  • Keep GitHub Releases as the candidate latest-version source for npm/Bun installs, but only write the existing version.json cache after npm registry metadata proves that same root version is ready.
  • Add codex-rs/tui/src/npm_registry.rs to validate npm readiness by checking dist-tags.latest and root package dist metadata for the GitHub candidate version.
  • Move version parsing helpers into codex-rs/tui/src/update_versions.rs so that logic can be tested without compiling the release-only updates.rs module under tests.
  • Update .github/workflows/rust-release.yml so the six known platform tarballs publish before the root @openai/codex wrapper. Other npm tarballs publish before the root wrapper, and the SDK publishes after the root package it depends on.

Bojun-Vvibe added a commit to Bojun-Vvibe/oss-contributions that referenced this pull request Apr 24, 2026
…ness + thread-store harness

- anomalyco/opencode#24179: session-scoped permission bridge for external providers (merge-after-nits)
- anomalyco/opencode#24162: desktop health-check exponential backoff (request-changes; loopback gate dropped, no_proxy widened)
- openai/codex#19389: npm update prompt readiness gate (merge-after-nits)
- openai/codex#19266: non-local thread-store regression harness (merge-after-nits)
@shijie-oai shijie-oai force-pushed the codex/npm-update-readiness branch from 92a9708 to 4ec099d Compare April 25, 2026 01:08
@shijie-oai shijie-oai force-pushed the codex/npm-update-readiness branch from 4ec099d to 90e50c3 Compare April 25, 2026 01:56
@shijie-oai shijie-oai changed the title Guard npm update prompt on registry readiness Guard npm update readiness Apr 25, 2026
@shijie-oai shijie-oai force-pushed the codex/npm-update-readiness branch 2 times, most recently from 12092c7 to c4a3343 Compare April 25, 2026 17:14
@shijie-oai shijie-oai force-pushed the codex/npm-update-readiness branch from c4a3343 to 6a66b76 Compare April 25, 2026 19:17
Comment on lines +100 to +110
let latest_version = fetch_latest_github_release_version().await?;
let package_info = create_client()
.get(npm_registry::PACKAGE_URL)
.send()
.await?
.error_for_status()?
.json::<ReleaseInfo>()
.json::<NpmPackageInfo>()
.await?;
extract_version_from_latest_tag(&latest_tag_name)?
npm_registry::ensure_version_ready(&package_info, &latest_version)?;
latest_version
}
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previouly we only rely on github latest tag but given recent issue there is a clear lag between github package readiness and npm status. Here we are adding a cross validation to make sure both are ready.

tarballs=(
"${platform_tarballs[@]}"
"${other_tarballs[@]}"
"${root_tarball}"
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Root tarball is what determines when npm says a version is ready. So even with the cross validation logic below against github latest, we can still run into user wants to upgrade yet it is actually no 100% ready.

}
}

fn extract_version_from_latest_tag(latest_tag_name: &str) -> anyhow::Result<String> {
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refactored into its own file.

Ok(())
}

fn parse_version(v: &str) -> Option<(u64, u64, u64)> {
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactored out into update_version

Comment on lines +670 to +673
if [[ ! -f "${required_tarball}" ]]; then
echo "Missing npm tarball: ${required_tarball}"
exit 1
fi
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So hardcoding the platform is a bit ugly but we can make sure that all tarballs are covered. Alternatively we can use a sort given that we didn't really care about existence prviously.

@shijie-oai shijie-oai force-pushed the codex/npm-update-readiness branch from 6a66b76 to 5f9e8c9 Compare April 25, 2026 23:09
@shijie-oai shijie-oai marked this pull request as ready for review April 25, 2026 23:11
Copy link
Copy Markdown
Collaborator

@etraut-openai etraut-openai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for doing this!

This PR includes two pieces: a build script change and a client-side change. Of the two, I think the build script change is much more important.

I have a small concern about the client change. It hardcodes the address of the public npm registry. Most of our users will go through the public registry, but some enterprises may use internal npm registries for supply chain controls. I guess that these enterprises will typically disable our auto-update check using check_for_update_on_startup = false.

@shijie-oai
Copy link
Copy Markdown
Collaborator Author

Thanks for doing this!

This PR includes two pieces: a build script change and a client-side change. Of the two, I think the build script change is much more important.

I have a small concern about the client change. It hardcodes the address of the public npm registry. Most of our users will go through the public registry, but some enterprises may use internal npm registries for supply chain controls. I guess that these enterprises will typically disable our auto-update check using check_for_update_on_startup = false.

Hm that is a good point with the internal npm registries but there should not be any behavioral difference. Really the only case is check_for_update_on_startup == true (or unset) and distributed through internal registry. With previous approach of only checking against github latest release we would still show upgrade disregarding internal registry status. With the adding cross valiation against public registry that behavior does not change - not ideal but no regression.

@shijie-oai shijie-oai merged commit 4e30281 into main Apr 26, 2026
25 checks passed
@shijie-oai shijie-oai deleted the codex/npm-update-readiness branch April 26, 2026 00:09
@github-actions github-actions Bot locked and limited conversation to collaborators Apr 26, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants