Use Linux release assets for updater#253
Conversation
|
@avifenesh You read my mind. I was actually thinking about publishing distro packages so it can be installed from there, and letting That way, we could avoid distributing OpenAI's proprietary DMG. |
|
@Leay15 its also looks nice |
ilysenko
left a comment
There was a problem hiding this comment.
Thanks for the work here, but I do not think we should merge this direction.
This changes the updater source of truth from "each user downloads the official OpenAI Codex DMG and rebuilds locally" to "install Linux packages from this repository's GitHub Releases". If those release packages bundle the Codex Desktop app/resources, we would effectively be redistributing OpenAI's proprietary desktop product ourselves.
I think this repo should continue distributing only the Linux adaptation/build tooling, while the upstream Codex app is obtained from OpenAI by each user during install/update. The updater UX and feature-selection pieces may still be useful, but the public Linux release-asset install path should not land unless the release assets contain only our own code/metadata or we have explicit permission to redistribute Codex Desktop.
@ilysenko I must say that at this point we are not really distributing even if you pull the DMG, you just align the wrapper with the version an give us an easier life. Give me a green light and I'm moving the heavy electron into Rust + GPUI, and you get almost all the advanced capabilities self-implemented anyway, while the backend interacts with Codex CLI like the real Codex app.
|
|
@ilysenko With a lot of respect of course, your repo, your rule, im adjusting myself. LMK if you want it to follow the upstream anyway. I can have two update button if it matter. |
|
Thanks, that makes sense. I opened a discussion so we can think through the updater direction with the wider community before changing the model: #257 |
avifenesh
left a comment
There was a problem hiding this comment.
Two technical findings on the updater state-machine changes, independent of the design-direction concern already raised.
1. auto_install_on_app_exit is silently broken (HIGH)
The new run_check_cycle transitions to ReadyToInstall with artifact_paths.package_path set to None (line 657). The existing reconcile_pending_install (unchanged by this PR) handles ReadyToInstall by cloning package_path and returning early if it is None (app.rs:700–702). That early return skips the auto_install_on_app_exit check entirely, so the daemon never auto-installs updates detected through the new flow.
auto_install_on_app_exit defaults to true (config.rs:89), so this regression affects most users.
The old flow worked because run_check_cycle downloaded the DMG and built the package during the check itself, so package_path was always set before the daemon's reconcile loop ran. The new flow defers package acquisition to prepare_update_package_if_needed, which is only called from run_install_ready (user-triggered), never from reconcile_pending_install.
If the intent is to keep auto-install working for the no-features case, the reconcile path needs to call prepare_update_package_if_needed (which already handles headless/no-features gracefully) instead of returning early.
2. GitHub releases API pagination not handled (MEDIUM)
fetch_remote_metadata calls GET /repos/{owner}/{repo}/releases without ?per_page=N. GitHub returns at most 30 releases per page. If the repository ever accumulates more than 30 releases, select_latest_release only sees the first page and could miss the actual latest non-prerelease.
The GitHub API returns releases newest-first by default, so the practical risk is low in the near term, but it's a latent correctness gap. A simple fix is to append ?per_page=100 to the URL (the maximum allowed), or use a higher-level strategy if the repo expects many releases.
This is an auto review done by revuto.
| .clone() | ||
| .expect("candidate version should be set before local build"); | ||
| builder::build_update(config, state, paths, &candidate_version, &downloaded.path).await?; | ||
| state.status = UpdateStatus::ReadyToInstall; |
There was a problem hiding this comment.
The check cycle now transitions to ReadyToInstall with package_path = None (set on line 657). The existing reconcile_pending_install handles ReadyToInstall at app.rs:699–702 by cloning package_path and returning early when it is None:
UpdateStatus::ReadyToInstall => {
let Some(package_path) = state.artifact_paths.package_path.clone() else {
return Ok(()); // ← always taken now
};
// auto_install_on_app_exit check never reached
}This silently disables auto_install_on_app_exit for the new update flow. Since auto_install_on_app_exit defaults to true, most existing users will stop receiving auto-installed updates. The daemon's reconcile loop will spin every RECONCILE_INTERVAL_SECONDS doing nothing.
If the intent is to keep auto-install working (at least for the no-features case where prepare_update_package_if_needed can download the release package without a GUI prompt), the reconcile path should call prepare_update_package_if_needed instead of returning early.
This is an auto review done by revuto.
| ) -> Result<RemoteMetadata> { | ||
| let response = client | ||
| .head(dmg_url) | ||
| .get(releases_api_url) |
There was a problem hiding this comment.
This GET request fetches the default page (30 items) from the GitHub releases API. If the repository accumulates more than 30 releases, select_latest_release may not see the actual latest non-prerelease.
Consider appending ?per_page=100 to DEFAULT_RELEASES_API_URL (or passing per_page as a query parameter here) to reduce the risk. The GitHub API maximum is 100 per page, which should be sufficient for the foreseeable lifetime of this repo.
This is an auto review done by revuto.







Summary
codex-update-managercheck this repository's GitHub Releases instead of the upstream DMG URL..deb,.rpm, or.pkg.tar.*) and install that release asset directly.Why
The updater should follow the Linux project releases as the source of truth. This keeps user updates aligned with the packages published by
codex-desktop-linux, rather than rebuilding from OpenAI's macOS artifact on every client machine.Scope
This is intentionally narrow: no feature-selection UI changes, no appcast support, and no release automation changes.
Validation
cargo fmt --all -- --checkcargo test -p codex-update-managercargo clippy --workspace --all-targets -- -D warningsgit diff --checkcodex-update-manager check-nowagainst the live repo releases API returnsidlewhen no releases are published yet.