Skip to content

ReleaseAutomationTest new failures in 7.7.0-preview.1: module-path / MyDocuments test assumptions (3 distinct cases) #27343

@jshigetomi

Description

@jshigetomi

Summary

Multiple tests fail in the ReleaseAutomationTest comparison of 7.7.0-preview.1 against the 7.6.0-rc.1 baseline. They share a common theme - how MyDocuments / SHARED_MODULES / $PSHOME/Modules paths interact with elevated, service-account, and ZIP/TAR distribution sessions - but split into distinct root causes.

# Case Lanes Root cause Tracking
1 ModuleIntrinsics.GetPSModulePath API tests All elevated Linux/macOS lanes (User variant); all elevated Windows + Linux/macOS lanes (Machine variant, test 100145) User variant: sudo -E drops HOME; Machine variant: cross-platform PSModulePath construction regression - top suspect PR #26565 This issue (below)
2 Module-path construction tests fail on portable (ZIP/TAR) and additional lanes WindowsServer2016ZIP - Unelevated, ubuntu22 TAR, mariner ARM64, macOS TAR, macOS, linux ARM32, debian12, azurelinux30 Downstream of PR #26565 ("Refactor the module path construction code"), which is not in v7.6.0-rc.1 Tracked in #27346
3 PSResourceGet / PowerShellGet AllUsers install All elevated lanes (Windows / Linux / macOS, portable + package-installed) Confirmed regression vs rc.1; top suspect is PR #26565 (AddToPath -> UpdatePath rewrite) - same code path as #27346. Unrelated to #27305 This issue (below)

All cases appear as "New Failure" because the ReleaseAutomationTest comparator matches failures by test name/ID against the baseline; tests added, renamed, or running for the first time on a newly-enabled lane in release/v7.7.0-preview.1 are reported as new.

First failing build: ReleaseAutomationTest-27557-ps-671171.


Shared context: PR #27305 "Enable usage in AppContainers"

release/v7.7.0-preview.1 commit 1218a29b8 (merged to master via bec015ffc / PR #27266) changed ModuleIntrinsics.GetPersonalModulePath on Windows from:

Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)

to:

Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments,
                          Environment.SpecialFolderOption.DoNotVerify)

SpecialFolderOption.None returns "" if the folder does not physically exist; DoNotVerify always returns a non-empty path. It also added SafeDoesPathExist in FileSystemProvider.cs for AppContainer-friendly drive-root validation. PR #26269 made the same DoNotVerify switch in CorePsPlatform.SafeDeriveFromSpecialFolder earlier.

This change is correct for AppContainer scenarios but is only directly relevant to Case 1. Case 3 is independent of #27305 (see Case 3 for details).

Delta between v7.6.0-rc.1 and release/v7.7.0-preview.1 relevant to these cases

1218a29b8 [release/v7.7.0-preview.1] Enable usage in AppContainers (#27305)
7498139ba Update `Microsoft.PowerShell.PSResourceGet` version to 1.2.0 (#27003)
212c5f97e Update to .NET 11 SDK and update dependencies (#26783)
012529a96 Update Microsoft.PowerShell.PSResourceGet version to 1.2.0-rc3 (#26753)
276989fa5 Update Microsoft.PowerShell.PSResourceGet version to 1.2.0-rc1 (#26691)
592668bd0 Refactor the module path construction code to make it more robust and easier to maintain (#26565)
2a49561af Update `Microsoft.PowerShell.PSResourceGet` to `v1.2.0-preview5` (#26589)
c7ee0d294 Fix checks for local user config file paths (#26269)

Case 1 - ModuleIntrinsics.GetPSModulePath "User" on elevated lanes

Lanes affected

  • Linux: mariner_ARM64, Ubuntu22, debian12, linux_Arm32, ubi9
  • macOS: macOS, macOS Tar
  • Windows: win_arm64, Windows Server 2016

Sample failure

Expected '/root/.local/share/powershell/Modules' to be found in collection
@('/home/cloudtest/PSPackage/download/PowerShell/Modules',
  '/home/cloudtest/PSPackage/download/Test/test/tools/Modules',
  '/home/cloudtest/.local/share/powershell/Modules'),
but it was not found.
at <ScriptBlock>, test/powershell/engine/Module/ModulePath.Tests.ps1: line 247
247:         $currentModulePathElements | Should -Contain $mPath

Root cause

The test assumes [ModuleIntrinsics]::GetPSModulePath("User") must already be present in the inherited $env:PSModulePath, which does not hold for the elevated test leg:

  1. The elevated leg is launched via sudo -E pwsh ... from build.psm1#L2020.
  2. sudo -E preserves $env:PSModulePath from the launching user (cloudtest) but most sudoers configurations reset HOME to /root.
  3. GetPSModulePath("User") is computed live from the new HOME via Platform.SelectProductNameForDirectory(USER_MODULES), producing /root/.local/share/powershell/Modules.
  4. The inherited $env:PSModulePath still contains /home/cloudtest/.local/share/powershell/Modules, so $currentModulePathElements | Should -Contain $mPath fails.

The same shape applies on elevated Windows lanes - the elevated process is launched from a wrapper that already established PSModulePath, and elevation/service-account contexts can produce a different MyDocuments folder than the one baked into the inherited PSModulePath. PR #27305 surfaces the Windows variant because DoNotVerify now returns a value that previously would have been "".

Fix

This is a test bug. Two reasonable options:

Option A - Skip when elevation crossed a user boundary (smallest change):

# test/powershell/engine/Module/ModulePath.Tests.ps1, inside the "User" case
if ($Name -eq ''User'') {
    $userPath = [System.Management.Automation.ModuleIntrinsics]::GetPSModulePath(''User'')
    if ($currentModulePathElements -notcontains $userPath) {
        Set-ItResult -Skipped -Because ''Elevation session has a different HOME/MyDocuments than the launching user; the inherited PSModulePath does not reflect current user-scope.''
        return
    }
}

Option B - Reconcile $env:PSModulePath after elevation (in the test harness):

Add to the elevated test entry point (e.g. around build.psm1#L2020):

$env:PSModulePath = [System.Management.Automation.ModuleIntrinsics]::GetModulePath(
    $env:PSModulePath, $null, $null)

Option A is lower-risk. Option B also makes Install-Module -Scope CurrentUser inside elevated legs behave more intuitively.


Case 3 - PSResourceGet / PowerShellGet AllUsers install on all elevated lanes

Tests

ID (preview.1 run) Describe/It File
100798 PSResourceGet - Module tests (Admin) - Should install a module correctly to the required location with AllUsers scope test/powershell/Modules/Microsoft.PowerShell.PSResourceGet/Microsoft.PowerShell.PSResourceGet.Tests.ps1#L241-L249
101755 PowerShellGet - Module tests (Admin) - Should install a module correctly to the required location with AllUsers scope test/powershell/Modules/PowerShellGet/PowerShellGet.Tests.ps1#L172-L178

Note: ReleaseAutomationTest test IDs are run-relative and not stable between runs. The same It blocks were tracked as 100120 / 100144 in an earlier draft; only test names are stable.

Lanes affected (all elevated)

  • win_arm64
  • WindowsServer2016ZIP
  • ubuntu22_TAR, ubuntu22
  • ubi9
  • arm64
  • macOS TAR, macOS
  • linux_arm32
  • debian12
  • azurelinux30

The coverage spans both portable (ZIP/TAR) and package-installed lanes, ruling out portable-distribution-only theories.

Confirmed regression

Both tests passed on the v7.6.0-rc.1 baseline (confirmed via the rc.1 ReleaseAutomationTest xUnit output: both result="Success" success="True" executed="True" for PSResourceGet - Module tests (Admin) and PowerShellGet - Module tests (Admin)). They now fail on preview.1, so this is a real product-side regression, not a comparator artifact.

Key assertion

Install-[Module|PSResource] -Name $TestModule -Scope AllUsers -ErrorAction Stop
$module = Get-Module $TestModule -ListAvailable
$module.ModuleBase.StartsWith($script:programFilesModulesPath) | Should -BeTrue

$programFilesModulesPath is built from [Platform]::SelectProductNameForDirectory("SHARED_MODULES"), which on Linux is hardcoded:

// src/System.Management.Automation/CoreCLR/CorePsPlatform.cs
case XDG_Type.SHARED_MODULES:
    return "/usr/local/share/powershell/Modules";

That value does not depend on HOME / sudo -E, so this case is NOT caused by #27305. The test files themselves are unchanged between v7.6.0-rc.1 and release/v7.7.0-preview.1 (git log v7.6.0-rc.1..release/v7.7.0-preview.1 -- <path> returns no commits), so it is not a rename/new-test artifact either.

Real candidates (delta commits between v7.6.0-rc.1 and release/v7.7.0-preview.1)

Commit Why it matters Case relevance
7498139ba - PR #27003 bump Microsoft.PowerShell.PSResourceGet to 1.2.0 (final GA) New GA could change Install-PSResource -Scope AllUsers install path logic Top suspect for 100120
012529a96 - PR #26753 PSResourceGet 1.2.0-rc3 Same codebase, interim step Secondary for 100120
592668bd0 - PR #26565 "Refactor module path construction" Rewrote UpdatePath, static-initialized SetModulePath, changed dedup to use Path.TrimEndingDirectorySeparator + HashSet<string> Top suspect for 100144
212c5f97e - PR #26783 .NET 10 -> .NET 11 SDK Runtime GetFolderPath / path semantics can shift subtly across SDK majors Possible, lower likelihood
1218a29b8 / bec015ffc - PR #27305 AppContainers Windows-only behavior change Unrelated

PowerShellGet 2.2.5 was not version-bumped between the two releases. Because 101755 also regressed and PowerShellGet itself did not change, the PSResourceGet 1.2.0 GA bump cannot be the sole explanation - a shared product-side change is required. The strongest single-suspect candidate that would explain regressions in both Install-PSResource -Scope AllUsers (test 100798) and Install-Module -Scope AllUsers (test 101755) is PR #26565 (592668bd0), via the same AddToPath -> UpdatePath rewrite already confirmed responsible for the test 108309 regression tracked in #27346.

Likely mechanism

The failing assertion is:

$module = Get-Module $TestModule -ListAvailable
$module.ModuleBase.StartsWith($script:programFilesModulesPath, [StringComparison]::OrdinalIgnoreCase) | Should -BeTrue

$script:programFilesModulesPath is byte-identical between rc.1 and preview.1 (/usr/local/share/powershell/Modules on Linux, $env:ProgramFiles/PowerShell/Modules on Windows). The install cmdlet is documented to land AllUsers-scoped modules under that root, so the only way the assertion fails is if Get-Module -ListAvailable returns a $module whose ModuleBase is not under $programFilesModulesPath - i.e. another copy of the module is being resolved first from a different PSModulePath entry.

Get-Module -ListAvailable enumerates PSModulePath in order. PR #26565 changed:

  • AddToPath -> UpdatePath (HashSet<string> dedup using Path.TrimEndingDirectorySeparator)
  • insertPosition now advances after each insert (forward order), where rc.1's AddToPath did not advance it (reverse order)
  • Static static ModuleIntrinsics() { SetModulePath(); } initializer added

Any of these can change the relative ordering of (a) the AllUsers install root and (b) other paths on PSModulePath that may also contain a copy of $TestModule (e.g. test-tools modules folder, downloaded test scaffolding). If a non-programFilesModulesPath location now sorts earlier on preview.1, Get-Module -ListAvailable | Select-Object -First 1 returns it, and StartsWith($programFilesModulesPath) fails.

This is consistent with the regression being across all elevated lanes (the change is in path construction, not platform-specific) and with PowerShellGet 2.2.5 being unchanged (the bug isn't in the install cmdlet, it's in which copy Get-Module -ListAvailable resolves first).

Fix plan

  1. Verify the mechanism. On a preview.1 build, on any failing lane, after Install-PSResource -Name $TestModule -Scope AllUsers run Get-Module $TestModule -ListAvailable | Select-Object Name, ModuleBase and inspect (a) which paths are returned and (b) the current $env:PSModulePath ordering. Compare against rc.1.
  2. If mechanism confirmed: the fix lives in ModuleIntrinsics.GetModulePath / UpdatePath and is the same family of change as the Test failures from module-path refactor PR #26565: tests 103778 / 103842 / 108309 fail on ZIP/TAR/portable distribution lanes #27346 fix - either always include psHomeModulePath alongside HKLM (as proposed in Test failures from module-path refactor PR #26565: tests 103778 / 103842 / 108309 fail on ZIP/TAR/portable distribution lanes #27346) or restore rc.1's reverse-insertion ordering for the affected branch.
  3. If mechanism not confirmed: widen the bisect across the delta commits above (top suspects remain Refactor the module path construction code to make it more robust and easier to maintain #26565, then PSResourceGet 1.2.0 GA Update Microsoft.PowerShell.PSResourceGet version to 1.2.0 #27003 for 100798 only, then .NET 11 SDK Update to .NET 11 SDK and update dependencies #26783).

Branch strategy

Both remaining cases exist on master as well as release/v7.7.0-preview.1:

Per .github/instructions/code-review-branch-strategy.instructions.md, release branches should not carry workarounds for issues that also exist on master.


Files affected

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    Issue-BugIssue has been identified as a bug in the product

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions