diff --git a/codex-rs/cli/src/daemon_update_tests.rs b/codex-rs/cli/src/daemon_update_tests.rs index be62c96496..5991829b9f 100644 --- a/codex-rs/cli/src/daemon_update_tests.rs +++ b/codex-rs/cli/src/daemon_update_tests.rs @@ -1,8 +1,40 @@ +#![cfg(test)] + use super::*; use codex_tui::DaemonUpdateSource; use pretty_assertions::assert_eq; use std::os::unix::fs::PermissionsExt; +#[test] +fn package_update_runs_outside_the_project() -> anyhow::Result<()> { + const CHILD: &str = "CODEX_TEST_PACKAGE_UPDATE_CHILD"; + if std::env::var_os(CHILD).is_some() { + return run_update_action(UpdateAction::PnpmGlobalLatest, /*cli_executable*/ None); + } + + let project = tempfile::tempdir()?; + let bin = tempfile::tempdir()?; + codex_utils_cargo_bin::write_executable( + &bin.path().join("pnpm"), + "#!/bin/sh\npwd -P > \"$0.cwd\"\n", + )?; + assert_cmd::Command::new(std::env::current_exe()?) + .args([ + "--exact", + "daemon_update_tests::package_update_runs_outside_the_project", + ]) + .current_dir(project.path()) + .env("TMPDIR", project.path()) + .env("PATH", bin.path()) + .env(CHILD, "1") + .assert() + .success(); + + let cwd = std::fs::read_to_string(bin.path().join("pnpm.cwd"))?; + assert!(!std::path::Path::new(cwd.trim_end()).starts_with(project.path().canonicalize()?)); + Ok(()) +} + #[test] fn daemon_handoff_uses_selected_executable_and_propagates_failure() -> anyhow::Result<()> { let dir = tempfile::tempdir()?; diff --git a/codex-rs/cli/src/main.rs b/codex-rs/cli/src/main.rs index f3eb880312..1c3fe17c1c 100644 --- a/codex-rs/cli/src/main.rs +++ b/codex-rs/cli/src/main.rs @@ -848,6 +848,8 @@ fn run_update_action( .collect(); std::process::Command::new(&command_path) .args(&normalized_args) + // Package managers search parent directories for project config and hooks. + .current_dir("/") .status()? } };