mirror of
https://github.com/openai/codex.git
synced 2026-05-27 14:34:24 +00:00
## 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.
71 lines
2.1 KiB
Rust
71 lines
2.1 KiB
Rust
pub(crate) fn is_newer(latest: &str, current: &str) -> Option<bool> {
|
|
match (parse_version(latest), parse_version(current)) {
|
|
(Some(l), Some(c)) => Some(l > c),
|
|
_ => None,
|
|
}
|
|
}
|
|
|
|
pub(crate) fn extract_version_from_latest_tag(latest_tag_name: &str) -> anyhow::Result<String> {
|
|
latest_tag_name
|
|
.strip_prefix("rust-v")
|
|
.map(str::to_owned)
|
|
.ok_or_else(|| anyhow::anyhow!("Failed to parse latest tag name '{latest_tag_name}'"))
|
|
}
|
|
|
|
pub(crate) fn is_source_build_version(version: &str) -> bool {
|
|
parse_version(version) == Some((0, 0, 0))
|
|
}
|
|
|
|
fn parse_version(v: &str) -> Option<(u64, u64, u64)> {
|
|
let mut iter = v.trim().split('.');
|
|
let maj = iter.next()?.parse::<u64>().ok()?;
|
|
let min = iter.next()?.parse::<u64>().ok()?;
|
|
let pat = iter.next()?.parse::<u64>().ok()?;
|
|
Some((maj, min, pat))
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use pretty_assertions::assert_eq;
|
|
|
|
#[test]
|
|
fn extracts_version_from_latest_tag() {
|
|
assert_eq!(
|
|
extract_version_from_latest_tag("rust-v1.5.0").expect("failed to parse version"),
|
|
"1.5.0"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn latest_tag_without_prefix_is_invalid() {
|
|
assert!(extract_version_from_latest_tag("v1.5.0").is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn prerelease_version_is_not_considered_newer() {
|
|
assert_eq!(is_newer("0.11.0-beta.1", "0.11.0"), None);
|
|
assert_eq!(is_newer("1.0.0-rc.1", "1.0.0"), None);
|
|
}
|
|
|
|
#[test]
|
|
fn plain_semver_comparisons_work() {
|
|
assert_eq!(is_newer("0.11.1", "0.11.0"), Some(true));
|
|
assert_eq!(is_newer("0.11.0", "0.11.1"), Some(false));
|
|
assert_eq!(is_newer("1.0.0", "0.9.9"), Some(true));
|
|
assert_eq!(is_newer("0.9.9", "1.0.0"), Some(false));
|
|
}
|
|
|
|
#[test]
|
|
fn source_build_version_is_not_checked() {
|
|
assert!(is_source_build_version("0.0.0"));
|
|
assert!(!is_source_build_version("0.1.0"));
|
|
}
|
|
|
|
#[test]
|
|
fn whitespace_is_ignored() {
|
|
assert_eq!(parse_version(" 1.2.3 \n"), Some((1, 2, 3)));
|
|
assert_eq!(is_newer(" 1.2.3 ", "1.2.2"), Some(true));
|
|
}
|
|
}
|