mirror of
https://github.com/openai/codex.git
synced 2026-11-07 20:30:33 +00:00
Move daemon packages out of the standalone CLI installation (#45546)
## Why The daemon shares the standalone CLI package, coupling daemon updates to the visible CLI installation. A dedicated package lets daemon updates preserve the CLI selection and shell profile. ## What changed - Add dedicated daemon package selection and separate daemon and updater PID files, with diagnostics for the new files. - Make `codex app-server daemon update` migrate eligible legacy stable latest-channel installations to a dedicated package. Prepare and validate the release and its package-ownership support before switching; preserve settings and whether the daemon was running. Scheduled updates keep legacy installations in place. - Add daemon-only and deferred-selection modes to the shell and PowerShell installers, leaving the visible CLI installation unchanged. - Coordinate migration with installer locks, refresh package selection after acquiring lifecycle locks, and reject package changes during update downloads. ## Testing Add coverage for running and stopped migrations, incompatible installers and releases, package-selection races, daemon-only updates, and a capability probe that does not start an updater. Add a shell installer regression test verifying that daemon installation preserves the visible CLI and shell profile. GitOrigin-RevId: 1ec0f358f8f6ebde7daddb74e880cc8d2235d647
This commit is contained in:
@@ -55,6 +55,16 @@ pub(super) async fn background_server_check(config: &Config) -> DoctorCheck {
|
||||
"update-loop pid file",
|
||||
&state_dir.join(UPDATE_PID_FILE_NAME),
|
||||
);
|
||||
push_file_detail(
|
||||
&mut details,
|
||||
"dedicated pid file",
|
||||
&state_dir.join("daemon.pid"),
|
||||
);
|
||||
push_file_detail(
|
||||
&mut details,
|
||||
"dedicated update-loop pid file",
|
||||
&state_dir.join("daemon-updater.pid"),
|
||||
);
|
||||
push_configured_updater(&mut details, &state_dir.join(SETTINGS_FILE_NAME));
|
||||
|
||||
let socket_path = match codex_app_server::app_server_control_socket_path(&config.codex_home) {
|
||||
@@ -322,6 +332,7 @@ mod tests {
|
||||
detail.starts_with("automatic updates:")
|
||||
|| detail.starts_with("update interval:")
|
||||
|| detail.starts_with("update-loop pid file:")
|
||||
|| detail.starts_with("dedicated")
|
||||
})
|
||||
.map(|detail| {
|
||||
detail
|
||||
|
||||
+2
-1
@@ -1,8 +1,9 @@
|
||||
---
|
||||
source: cli/src/doctor/background.rs
|
||||
assertion_line: 332
|
||||
expression: details
|
||||
---
|
||||
update-loop pid file: CODEX_HOME/app-server-daemon/app-server-updater.pid (missing)
|
||||
dedicated pid file: CODEX_HOME/app-server-daemon/daemon.pid (missing)
|
||||
dedicated update-loop pid file: CODEX_HOME/app-server-daemon/daemon-updater.pid (missing)
|
||||
automatic updates: disabled (configured)
|
||||
update interval: 90 minutes (configured)
|
||||
|
||||
@@ -809,7 +809,11 @@ enum AppServerDaemonSubcommand {
|
||||
|
||||
/// [internal] Run the detached pid-backed standalone updater loop.
|
||||
#[clap(hide = true)]
|
||||
PidUpdateLoop,
|
||||
PidUpdateLoop {
|
||||
/// Check support for daemon-owned packages without starting the updater.
|
||||
#[arg(long, hide = true)]
|
||||
check_package_ownership: bool,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Args)]
|
||||
@@ -1392,10 +1396,6 @@ async fn cli_main(
|
||||
AppServerDaemonSubcommand::Restart => {
|
||||
print_app_server_daemon_output(AppServerLifecycleCommand::Restart).await?;
|
||||
}
|
||||
AppServerDaemonSubcommand::Update => {
|
||||
let output = codex_app_server_daemon::update().await?;
|
||||
println!("{}", serde_json::to_string(&output)?);
|
||||
}
|
||||
AppServerDaemonSubcommand::EnableRemoteControl => {
|
||||
print_app_server_remote_control_output(AppServerRemoteControlMode::Enabled)
|
||||
.await?;
|
||||
@@ -1412,7 +1412,13 @@ async fn cli_main(
|
||||
AppServerDaemonSubcommand::Version => {
|
||||
print_app_server_daemon_output(AppServerLifecycleCommand::Version).await?;
|
||||
}
|
||||
AppServerDaemonSubcommand::PidUpdateLoop => {
|
||||
AppServerDaemonSubcommand::PidUpdateLoop {
|
||||
check_package_ownership: true,
|
||||
} => return Ok(()),
|
||||
AppServerDaemonSubcommand::Update
|
||||
| AppServerDaemonSubcommand::PidUpdateLoop {
|
||||
check_package_ownership: false,
|
||||
} => {
|
||||
let cli_overrides = root_config_overrides
|
||||
.parse_overrides()
|
||||
.map_err(anyhow::Error::msg)?;
|
||||
@@ -1422,7 +1428,14 @@ async fn cli_main(
|
||||
.await
|
||||
.map_err(anyhow::Error::from);
|
||||
let http_client_factory = updater_http_client_factory(config);
|
||||
codex_app_server_daemon::run_pid_update_loop(http_client_factory).await?;
|
||||
if matches!(daemon_cli.subcommand, AppServerDaemonSubcommand::Update) {
|
||||
let output =
|
||||
codex_app_server_daemon::update(http_client_factory).await?;
|
||||
println!("{}", serde_json::to_string(&output)?);
|
||||
} else {
|
||||
codex_app_server_daemon::run_pid_update_loop(http_client_factory)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
},
|
||||
Some(AppServerSubcommand::Proxy(proxy_cli)) => {
|
||||
@@ -2643,7 +2656,7 @@ fn app_server_subcommand_name(subcommand: Option<&AppServerSubcommand>) -> &'sta
|
||||
}
|
||||
AppServerDaemonSubcommand::Stop => "app-server daemon stop",
|
||||
AppServerDaemonSubcommand::Version => "app-server daemon version",
|
||||
AppServerDaemonSubcommand::PidUpdateLoop => "app-server daemon pid-update-loop",
|
||||
AppServerDaemonSubcommand::PidUpdateLoop { .. } => "app-server daemon pid-update-loop",
|
||||
},
|
||||
Some(AppServerSubcommand::Proxy(_)) => "app-server proxy",
|
||||
Some(AppServerSubcommand::GenerateTs(_)) => "app-server generate-ts",
|
||||
|
||||
Reference in New Issue
Block a user