fix: run standalone updates noninteractively (#24637)

# Summary

The standalone update action currently downloads and runs the Codex
installer as an interactive command. When an existing managed Codex
install is present, accepting an update can therefore enter an installer
prompt instead of completing the update.

This change runs the standalone installer with `CODEX_NON_INTERACTIVE=1`
on macOS/Linux and Windows. The installer environment-variable support
is introduced by the parent PR; this PR wires that behavior into the
Codex CLI update action. The rendered Windows command remains
shell-safe, and long update commands wrap within the update-notice card.
The standard test target snapshots the standalone notice for both
platforms.

# Stack

1. [#21567](https://github.com/openai/codex/pull/21567) - Adds
environment-controlled release selection and noninteractive installer
behavior.
2. [#24637](https://github.com/openai/codex/pull/24637) - Runs
standalone updates with `CODEX_NON_INTERACTIVE=1`. (current)
3. [#24639](https://github.com/openai/codex/pull/24639) - Removes
explicit release argument inputs in favor of `CODEX_RELEASE`.

# Evidence

Standalone updater-shaped macOS install with an existing npm-managed
Codex on `PATH`:


https://github.com/user-attachments/assets/a27fe9e9-db3a-4c39-a514-24bd3d1f01e8

# Testing

Tests: targeted `codex-tui` update-action and update-notice snapshot
tests, Rust formatting, benchmark smoke validation, macOS live-terminal
standalone-update smoke testing, Windows ARM64 PowerShell
standalone-update smoke testing through Parallels, and CI.
This commit is contained in:
efrazer-oai
2026-05-27 09:45:10 -07:00
committed by GitHub
Unverified
parent 379511dcea
commit 5314f55097
5 changed files with 55 additions and 7 deletions
+2 -1
View File
@@ -52,7 +52,8 @@ impl HistoryCell for UpdateAvailableHistoryCell {
.width()
.min(usize::from(width.saturating_sub(4)))
.max(1);
with_border_with_inner_width(content.lines, inner_width)
let lines = adaptive_wrap_lines(content.lines, RtOptions::new(inner_width));
with_border_with_inner_width(lines, inner_width)
}
fn raw_lines(&self) -> Vec<Line<'static>> {
@@ -0,0 +1,11 @@
---
source: tui/src/history_cell/tests.rs
expression: rendered
---
╭─────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✨ Update available! 0.0.0 -> 9.9.9 │
│ Run sh -c 'curl -fsSL https://chatgpt.com/codex/install.sh | CODEX_NON_INTERACTIVE=1 sh' to update. │
│ │
│ See full release notes: │
│ https://github.com/openai/codex/releases/latest │
╰─────────────────────────────────────────────────────────────────────────────────────────────────────╯
@@ -0,0 +1,12 @@
---
source: tui/src/history_cell/tests.rs
expression: rendered
---
╭────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✨ Update available! 0.0.0 -> 9.9.9 │
│ Run powershell -ExecutionPolicy Bypass -c '$env:CODEX_NON_INTERACTIVE=1; irm │
│ https://chatgpt.com/codex/install.ps1 | iex' to update. │
│ │
│ See full release notes: │
│ https://github.com/openai/codex/releases/latest │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
+18
View File
@@ -1027,6 +1027,24 @@ fn web_search_history_cell_snapshot() {
insta::assert_snapshot!(rendered);
}
#[test]
fn standalone_unix_update_available_history_cell_snapshot() {
let cell =
UpdateAvailableHistoryCell::new("9.9.9".to_string(), Some(UpdateAction::StandaloneUnix));
let rendered = render_lines(&cell.display_lines(/*width*/ 110)).join("\n");
insta::assert_snapshot!(rendered);
}
#[test]
fn standalone_windows_update_available_history_cell_snapshot() {
let cell =
UpdateAvailableHistoryCell::new("9.9.9".to_string(), Some(UpdateAction::StandaloneWindows));
let rendered = render_lines(&cell.display_lines(/*width*/ 110)).join("\n");
insta::assert_snapshot!(rendered);
}
#[test]
fn web_search_history_cell_wraps_with_indented_continuation() {
let query = "example search query with several generic words to exercise wrapping".to_string();
+12 -6
View File
@@ -14,9 +14,9 @@ pub enum UpdateAction {
BunGlobalLatest,
/// Update via `brew upgrade codex`.
BrewUpgrade,
/// Update via `curl -fsSL https://chatgpt.com/codex/install.sh | sh`.
/// Update via `curl -fsSL https://chatgpt.com/codex/install.sh | CODEX_NON_INTERACTIVE=1 sh`.
StandaloneUnix,
/// Update via `irm https://chatgpt.com/codex/install.ps1|iex`.
/// Update via `$env:CODEX_NON_INTERACTIVE=1; irm https://chatgpt.com/codex/install.ps1 | iex`.
StandaloneWindows,
}
@@ -43,7 +43,10 @@ impl UpdateAction {
UpdateAction::BrewUpgrade => ("brew", &["upgrade", "--cask", "codex"]),
UpdateAction::StandaloneUnix => (
"sh",
&["-c", "curl -fsSL https://chatgpt.com/codex/install.sh | sh"],
&[
"-c",
"curl -fsSL https://chatgpt.com/codex/install.sh | CODEX_NON_INTERACTIVE=1 sh",
],
),
UpdateAction::StandaloneWindows => (
"powershell",
@@ -51,7 +54,7 @@ impl UpdateAction {
"-ExecutionPolicy",
"Bypass",
"-c",
"irm https://chatgpt.com/codex/install.ps1 | iex",
"$env:CODEX_NON_INTERACTIVE=1; irm https://chatgpt.com/codex/install.ps1 | iex",
],
),
}
@@ -140,7 +143,10 @@ mod tests {
UpdateAction::StandaloneUnix.command_args(),
(
"sh",
&["-c", "curl -fsSL https://chatgpt.com/codex/install.sh | sh"][..],
&[
"-c",
"curl -fsSL https://chatgpt.com/codex/install.sh | CODEX_NON_INTERACTIVE=1 sh"
][..],
)
);
assert_eq!(
@@ -151,7 +157,7 @@ mod tests {
"-ExecutionPolicy",
"Bypass",
"-c",
"irm https://chatgpt.com/codex/install.ps1 | iex"
"$env:CODEX_NON_INTERACTIVE=1; irm https://chatgpt.com/codex/install.ps1 | iex"
][..],
)
);