From 8960c363c61e33b7b3d3ec34a608160f2a81a907 Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Tue, 3 Nov 2026 20:11:45 +0000 Subject: [PATCH] Preserve installer stderr when releasing the install lock (#59227) ## Why Redirecting stderr on `exec` while closing the lock descriptor suppressed subsequent installer warnings, including the warning that an existing npm-managed Codex installation remains installed. ## What changed Remove the stderr redirection from `release_install_lock` when closing file descriptor 9. Add a regression test asserting that a noninteractive install succeeds and emits the existing npm installation warning. GitOrigin-RevId: 5a35ccd9bf62afb99cc949892ec724a01e2d9eee --- scripts/install/install.sh | 2 +- scripts/install/test_install_sh.py | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/scripts/install/install.sh b/scripts/install/install.sh index b79970f9c1..222155d9bc 100755 --- a/scripts/install/install.sh +++ b/scripts/install/install.sh @@ -743,7 +743,7 @@ release_install_lock() { if [ "$lock_kind" = "mkdir" ]; then rm -rf "$LOCK_DIR" 2>/dev/null || true elif [ "$lock_kind" = "flock" ] || [ "$lock_kind" = "lockf" ]; then - exec 9>&- 2>/dev/null || true + exec 9>&- fi lock_kind="" } diff --git a/scripts/install/test_install_sh.py b/scripts/install/test_install_sh.py index bac85ed277..9776739367 100644 --- a/scripts/install/test_install_sh.py +++ b/scripts/install/test_install_sh.py @@ -135,6 +135,27 @@ class InstallShTest(unittest.TestCase): ) self.assertTrue(os.access(host_path, os.X_OK)) + def test_noninteractive_install_warns_about_existing_npm_codex(self) -> None: + with tempfile.TemporaryDirectory() as temp_dir: + root = Path(temp_dir) + archive, checksum, metadata = create_package_release(root) + (root / "bin").mkdir() + write_executable(root / "bin" / "codex", "#!/usr/bin/env node\n") + + result, _ = run_installer_in( + root, + VERSION, + metadata_json=metadata, + archive_path=archive, + checksum_path=checksum, + force_macos=True, + ) + + self.assertEqual(result.returncode, 0, result.stderr) + self.assertIn( + "Leaving the existing npm-managed Codex installed", result.stderr + ) + def test_releases_latest_installs_verified_package_by_default(self) -> None: with tempfile.TemporaryDirectory() as temp_dir: root = Path(temp_dir)