fix(install): don't crash the PowerShell installer when $PROFILE is unset (#2469)
## Description The PowerShell installer (`scripts/install.ps1`) crashes at the very end on any machine where PowerShell cannot resolve the current user's profile path. `Ensure-ProfileBlock` locates the profile with: ```powershell $profileDir = Split-Path -Parent $PROFILE ``` `$PROFILE` is an empty string when PowerShell cannot compute the profile path for the current user, which happens for a fresh account with no Documents folder yet, a service or CI context, or a redirected profile. `Split-Path -Parent ''` then throws: ``` Split-Path : Cannot bind argument to parameter 'Path' because it is an empty string. ``` Because the script runs under `$ErrorActionPreference = 'Stop'`, that terminates the whole installer with a non-zero exit, even though it happens after the `headroom` wrapper and the persistent User PATH entry were already written. The user sees a scary Split-Path error and assumes the install failed. ## Fix Skip the profile convenience block when `$PROFILE` is empty and log why. `Ensure-PathEntry` already persists the User PATH for new sessions, so the only thing skipped is auto-refreshing PATH inside the current profile file, which does not exist in that environment anyway. Well-behaved environments with a real `$PROFILE` are unchanged. ## Type of Change - [x] Bug fix (non-breaking change that fixes an issue) - [ ] New feature (non-breaking change that adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update - [ ] Performance improvement - [ ] Code refactoring (no functional changes) ## Changes Made - `scripts/install.ps1`: early-return from `Ensure-ProfileBlock` with an informational message when `$PROFILE` is null or empty, before the `Split-Path` call. ## Testing - [x] Unit tests pass (`pytest`) - [x] Linting passes (`ruff check .`) - [x] Type checking passes (`mypy headroom`) - [ ] New tests added for new functionality - [ ] Manual testing performed ### Test Output ```text $ python -m pytest tests/test_install/test_native_installers.py -q 1 passed, 1 skipped # The PowerShell lifecycle test was failing on main before this change and now passes: $ python -m pytest "tests/test_install/test_native_installers.py::test_powershell_native_installer_supports_persistent_docker_lifecycle" -q 1 passed ``` ## Real Behavior Proof - Environment: Windows 11, Python 3.12, Windows PowerShell 5.1, project venv (`uv sync --extra proxy`), pytest in the venv. - Exact command / steps: ran `install.ps1` under a temp `USERPROFILE` with no Documents folder (the same setup the installer test uses). Confirmed `$PROFILE` resolves to an empty string in that context and that `Split-Path -Parent $PROFILE` throws there, then re-ran the installer test with the fix. - Observed result: before the fix the installer aborted with `Split-Path : Cannot bind argument to parameter 'Path' because it is an empty string` and exit code 1 (and the test failed); after the fix the installer completes, writes the wrapper and PATH entry, logs that it skipped the profile update, and the test passes. Ran against the actual script. - Not tested: a real end-user account whose Documents folder is redirected to a network share. ## Review Readiness - [x] I have performed a self-review - [x] This PR is ready for human review ## Checklist - [x] My code follows the project's style guidelines - [x] I have performed a self-review of my code - [x] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] I have updated the CHANGELOG.md if applicable
This commit is contained in:
@@ -36,6 +36,19 @@ function Ensure-PathEntry {
|
||||
function Ensure-ProfileBlock {
|
||||
param([string]$PathEntry)
|
||||
|
||||
# $PROFILE is empty when PowerShell cannot resolve the profile path for the
|
||||
# current user (a fresh account with no Documents folder, a service/CI
|
||||
# context, a redirected profile). Split-Path below would then throw
|
||||
# "Cannot bind argument to parameter 'Path' because it is an empty string",
|
||||
# and with $ErrorActionPreference = 'Stop' that aborts the whole installer
|
||||
# AFTER the wrapper and persistent User PATH were already written. Skip the
|
||||
# profile convenience block instead: Ensure-PathEntry has already persisted
|
||||
# the PATH for new sessions.
|
||||
if ([string]::IsNullOrEmpty($PROFILE)) {
|
||||
Write-Info 'Skipping PowerShell profile update: $PROFILE is not set in this environment (PATH was still updated for new sessions).'
|
||||
return
|
||||
}
|
||||
|
||||
$markerStart = '# >>> headroom docker-native >>>'
|
||||
$markerEnd = '# <<< headroom docker-native <<<'
|
||||
$escapedPathEntry = $PathEntry.Replace("'", "''")
|
||||
|
||||
Reference in New Issue
Block a user