updates: use brew api for version check (#10809)

## Problem

`codex` currently prompts you to update via `brew upgrade --cask codex`
but the brew api does not return the new version

> <img width="1500" height="822" alt="Screenshot 2026-02-05 at 12 36
09 PM"
src="https://github.com/user-attachments/assets/9e12929d-95e8-43f4-8fba-ab93f5f76e73"
/>

## Solution

`codex-rs/tui/src/updates.rs` was using the [latest cask in
github](https://github.com/Homebrew/homebrew-cask/blob/HEAD/Casks/c/codex.rb)
but this does not agree with the brew api, which leads to the issue
above. Instead we use the [brew api json
endpoint](https://github.com/Homebrew/homebrew-cask/blob/HEAD/Casks/c/codex.rb)
to ensure our version check agrees with the upgrade command.
This commit is contained in:
Noah Jorgensen 2026-02-05 15:12:27 -08:00 committed by GitHub
parent dbe47ea01a
commit dcea972db8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -56,8 +56,7 @@ struct VersionInfo {
const VERSION_FILENAME: &str = "version.json";
// We use the latest version from the cask if installation is via homebrew - homebrew does not immediately pick up the latest release and can lag behind.
const HOMEBREW_CASK_URL: &str =
"https://raw.githubusercontent.com/Homebrew/homebrew-cask/HEAD/Casks/c/codex.rb";
const HOMEBREW_CASK_API_URL: &str = "https://formulae.brew.sh/api/cask/codex.json";
const LATEST_RELEASE_URL: &str = "https://api.github.com/repos/openai/codex/releases/latest";
#[derive(Deserialize, Debug, Clone)]
@ -65,6 +64,11 @@ struct ReleaseInfo {
tag_name: String,
}
#[derive(Deserialize, Debug, Clone)]
struct HomebrewCaskInfo {
version: String,
}
fn version_filepath(config: &Config) -> PathBuf {
config.codex_home.join(VERSION_FILENAME)
}
@ -77,14 +81,14 @@ fn read_version_info(version_file: &Path) -> anyhow::Result<VersionInfo> {
async fn check_for_update(version_file: &Path) -> anyhow::Result<()> {
let latest_version = match update_action::get_update_action() {
Some(UpdateAction::BrewUpgrade) => {
let cask_contents = create_client()
.get(HOMEBREW_CASK_URL)
let HomebrewCaskInfo { version } = create_client()
.get(HOMEBREW_CASK_API_URL)
.send()
.await?
.error_for_status()?
.text()
.json::<HomebrewCaskInfo>()
.await?;
extract_version_from_cask(&cask_contents)?
version
}
_ => {
let ReleaseInfo {
@ -123,18 +127,6 @@ fn is_newer(latest: &str, current: &str) -> Option<bool> {
}
}
fn extract_version_from_cask(cask_contents: &str) -> anyhow::Result<String> {
cask_contents
.lines()
.find_map(|line| {
let line = line.trim();
line.strip_prefix("version \"")
.and_then(|rest| rest.strip_suffix('"'))
.map(ToString::to_string)
})
.ok_or_else(|| anyhow::anyhow!("Failed to find version in Homebrew cask file"))
}
fn extract_version_from_latest_tag(latest_tag_name: &str) -> anyhow::Result<String> {
latest_tag_name
.strip_prefix("rust-v")
@ -190,16 +182,18 @@ mod tests {
use super::*;
#[test]
fn parses_version_from_cask_contents() {
let cask = r#"
cask "codex" do
version "0.55.0"
end
"#;
assert_eq!(
extract_version_from_cask(cask).expect("failed to parse version"),
"0.55.0"
);
fn extract_version_from_brew_api_json() {
//
// https://formulae.brew.sh/api/cask/codex.json
let cask_json = r#"{
"token": "codex",
"full_token": "codex",
"tap": "homebrew/cask",
"version": "0.96.0",
}"#;
let HomebrewCaskInfo { version } = serde_json::from_str::<HomebrewCaskInfo>(cask_json)
.expect("failed to parse version from cask json");
assert_eq!(version, "0.96.0");
}
#[test]