Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `apm install -g --target codex` now honors `CODEX_HOME` for user-scope
Codex MCP config writes, falling back to `~/.codex/config.toml` when unset.
(closes #1861) (#1863)
- Windows pip fallback no longer terminates early when native pip writes
stderr under `$ErrorActionPreference = "Stop"`. (closes #1874) (#1876)

## [0.21.0] - 2026-06-19

Expand Down
22 changes: 14 additions & 8 deletions install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -265,14 +265,20 @@ function Install-ViaPip {
}
$pipIndexArgs = Get-PipIndexArgs
try {
if ($pipCmd -like "* -m pip") {
$output = & $pythonCmd -m pip install --user @pipIndexArgs apm-cli 2>&1
$pipExitCode = $LASTEXITCODE
$output | Write-Host
} else {
$output = & $pipCmd install --user @pipIndexArgs apm-cli 2>&1
$pipExitCode = $LASTEXITCODE
$output | Write-Host
$previousErrorActionPreference = $ErrorActionPreference
try {
$ErrorActionPreference = "Continue"
if ($pipCmd -like "* -m pip") {
$output = & $pythonCmd -m pip install --user @pipIndexArgs apm-cli 2>&1
$pipExitCode = $LASTEXITCODE
$output | Write-Host
} else {
$output = & $pipCmd install --user @pipIndexArgs apm-cli 2>&1
$pipExitCode = $LASTEXITCODE
$output | Write-Host
}
} finally {
$ErrorActionPreference = $previousErrorActionPreference
}
if ($pipExitCode -ne 0) {
Write-ErrorText "pip install failed (exit code $pipExitCode)."
Expand Down
25 changes: 25 additions & 0 deletions tests/unit/test_enterprise_bootstrap_installers.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,31 @@ def test_unix_installer_fail_closed_asset_exit_code() -> None:
assert "APM_RELEASE_BASE_URL is not configured" in combined


def test_windows_pip_fallback_scopes_native_stderr_error_action_guard() -> None:
"""install.ps1 must not let native pip stderr terminate fallback."""
text = _read_repo_file("install.ps1")
body = text.split("function Install-ViaPip {", 1)[1].split(
"function Write-ManualInstallHelp {", 1
)[0]
Comment on lines +174 to +177

previous_guard = "$previousErrorActionPreference = $ErrorActionPreference"
continue_guard = '$ErrorActionPreference = "Continue"'
restore_guard = "$ErrorActionPreference = $previousErrorActionPreference"
python_pip_call = "$output = & $pythonCmd -m pip install --user @pipIndexArgs apm-cli 2>&1"
pip_call = "$output = & $pipCmd install --user @pipIndexArgs apm-cli 2>&1"

assert previous_guard in body
assert continue_guard in body
assert restore_guard in body
assert body.count(continue_guard) == 1
assert body.index(previous_guard) < body.index(continue_guard)
assert body.index(continue_guard) < body.index(python_pip_call)
assert body.index(continue_guard) < body.index(pip_call)
assert body.index(python_pip_call) < body.index("finally {")
assert body.index(pip_call) < body.index("finally {")
assert body.index("finally {") < body.index(restore_guard)


def test_windows_installer_uses_auth_on_first_ghes_metadata_fetch() -> None:
"""install.ps1 should not make an unauthenticated GHES metadata request first."""
text = _read_repo_file("install.ps1")
Expand Down
Loading