Skip to content

Find the repository root from the session location, not the process working directory - #3015

Merged
nohwnd merged 2 commits into
mainfrom
fix-reporoot-session-location
Aug 30, 2026
Merged

Find the repository root from the session location, not the process working directory#3015
nohwnd merged 2 commits into
mainfrom
fix-reporoot-session-location

Conversation

@nohwnd

@nohwnd nohwnd commented Aug 29, 2026

Copy link
Copy Markdown
Member

Found while writing the 6.2.0-alpha1 notes: I wrote a repository with Pester.BeforeContainer.ps1 at three levels, ran it, and none of them applied. It took two runs to work out why.

Run.RepoRoot decides which setup files apply, and its default is found by walking up for a .git directory. The walk runs in C# from Directory.GetCurrentDirectory(), the process working directory, and Set-Location does not change that:

pwsh                     # process working directory is now ~
cd ~/p/myrepo
Invoke-Pester ./tests    # RepoRoot is still ~, no Pester.BeforeContainer.ps1 applies

The run is green, the setup silently did nothing, and there is no warning. It is pre-existing, Run.RepoRoot shipped in 6.1.0, but #2993 made the whole folder cascade depend on it so it is worth fixing before the alpha goes out.

Change

FindRepoRoot takes the directory to start from, and Invoke-Pester resolves RepoRoot from $ExecutionContext.SessionState.Path.CurrentFileSystemLocation before the run, next to where the shuffle seed is resolved. That is the same source Pester.Parallel.ps1 already uses for the working directory it hands to workers.

Only when the option was not set. An explicit Run.RepoRoot is the user's to decide and is left alone.

The parameterless overload stays as the value an unused configuration object shows, so [PesterConfiguration]::Default still reports a directory rather than nothing.

Verification

Three tests next to the existing cascade tests:

  • the cascade applies after Set-Location with no RepoRoot set. It also asserts the process directory and the session location actually disagree, so it cannot pass by accident on a runner that happens to start in the right place
  • an explicit Run.RepoRoot survives the run
  • FindRepoRoot falls back to the directory it started from when there is no .git above it

The first one fails without the change (43/44) and passes with it (44/44). Full suite on PS 7.5 macOS: P phase clean, RSpec 2921 passed, 0 failed, 3 skipped.

about_PesterConfiguration.help.txt is regenerated by build.ps1 -Clean, so it is in the same commit.

Based on release-6.2.0-alpha1 (#3014) because it adds its entry to docs/NEXT-RELEASE.md, which that PR introduces. Retargets to main on its own once #3014 merges.

🤖

@nohwnd

nohwnd commented Aug 29, 2026

Copy link
Copy Markdown
Member Author

No checks run on this PR: ci.yml and code-analysis.yml only trigger for pull requests whose base is main, rel/* or dev/*, and this one is based on release-6.2.0-alpha1 so it matches none of them.

The branch contains both commits, so I dispatched the two workflows against it directly, which tests exactly the state that lands on main:

Once #3014 merges this retargets to main on its own and gets normal PR checks.

Worth considering separately: adding a base pattern for stacked release branches to ci.yml, or naming them dev/* so they are covered by what is already there.

🤖

Base automatically changed from release-6.2.0-alpha1 to main August 29, 2026 07:55
…orking directory

Run.RepoRoot decides which Pester.BeforeContainer.ps1 files apply, and its default is found
by walking up for a .git directory. The walk ran in C# from Directory.GetCurrentDirectory(),
the process working directory, and Set-Location does not change that. So a session that
started somewhere else and then changed directory into a repository kept a RepoRoot pointing
at the old place, and the whole setup chain silently did not apply, with nothing to say why:

    pwsh                     # process working directory is now ~
    cd ~/p/myrepo
    Invoke-Pester ./tests    # RepoRoot was ~, no Pester.BeforeContainer.ps1 applied

FindRepoRoot takes the directory to start from now, and Invoke-Pester resolves RepoRoot from
$ExecutionContext.SessionState.Path.CurrentFileSystemLocation before the run, next to where
the shuffle seed is resolved. Same place Pester.Parallel.ps1 already takes the working
directory it hands to workers. Only when the option was not set, an explicit RepoRoot is the
user's to decide and is left alone.

The parameterless overload stays as the value an unused configuration object shows, so
[PesterConfiguration]::Default still reports a directory rather than nothing.

Tests: the cascade applies after Set-Location with no RepoRoot set, and the test asserts the
two locations actually disagree so it cannot pass by accident; an explicit RepoRoot survives
the run; FindRepoRoot falls back to the directory it started from when there is no .git.
Verified the first one fails without the change (43/44) and passes with it (44/44). Full
suite on PS 7.5 macOS: P phase clean, RSpec 2921 passed, 0 failed, 3 skipped.

about_PesterConfiguration.help.txt is regenerated by build.ps1 -Clean, so it is in the same
commit.

🤖
@nohwnd
nohwnd force-pushed the fix-reporoot-session-location branch from 1ffed2f to 2528764 Compare August 29, 2026 07:55
The test set Run.RepoRoot to 'TestDrive:not-a-real-path-but-mine' to prove an explicit value
is not overwritten. Resolving the chain runs that value through GetFullPath, and the made up
path is not portable: on Unix it is a legal relative file name, on Windows it reads as a
drive qualifier and throws, so the run died and $r was not a result object. Both Windows
PowerShell 5.1 legs failed on it while every PS7 leg passed.

Use a real temp directory, and assert the run itself passed before reading the value back, so
a throw shows up as a failed run rather than as a missing property.

The two tests that cover the actual change both passed on 5.1.

🤖
@nohwnd
nohwnd merged commit b6eaa72 into main Aug 30, 2026
20 checks passed
@nohwnd
nohwnd deleted the fix-reporoot-session-location branch August 30, 2026 05:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant