From 63ed27565a01bdd2d92c622e7273d81ceea6bfd2 Mon Sep 17 00:00:00 2001 From: Trent Blackburn Date: Fri, 28 Aug 2026 17:21:35 -0400 Subject: [PATCH] docs: Refresh the job-isolation rationale in the fixture helpers The two-platyPS-majors conflict that originally justified the background jobs ended with the 1.x migration, so the comment described a constraint that no longer exists. The replacement drafted for it was also wrong: it credited Import-Module -Global, but Microsoft.PowerShell.PlatyPS resolves commands through the PSModuleInfo object rather than a session-state name lookup, and the generated markdown is byte-for-byte identical without -Global. State the reason that actually survives -- every docs command leaves Microsoft.PowerShell.PlatyPS loaded, and assemblies load per process rather than per runspace, so only a separate process starts clean -- and keep the original conflict as recorded history rather than as a live justification. Also note that Invoke-TestPSBuildPesterInJob's matrix has spanned a single Pester major since #172, so its job buys isolation rather than reach. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01G7WMiaQNgL3wULG4thw7nk --- tests/fixtures/FixtureHelpers.psm1 | 31 ++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/tests/fixtures/FixtureHelpers.psm1 b/tests/fixtures/FixtureHelpers.psm1 index 75530b2..3375dac 100644 --- a/tests/fixtures/FixtureHelpers.psm1 +++ b/tests/fixtures/FixtureHelpers.psm1 @@ -178,13 +178,25 @@ function Invoke-PSBuildCommandInJob { throwing keeps a failure legible: the test asserts on ErrorMessage instead of an opaque job error. - A job is used because some commands cannot be exercised in the caller's session. The - docs pipeline is the current example: platyPS 0.14.2 and Microsoft.PowerShell.PlatyPS - 1.x each load their own YamlDotNet.dll through NestedModules with different assembly - identities, so whichever imports second fails with "Assembly with same name is already - loaded". A separate runspace does not escape that; only a separate process does. Pester - recommends the same technique for session isolation, see - https://pester.dev/docs/usage/mocking. + A job is used because these commands leave the session different from how they found + it, and the session they would otherwise run in is Pester's. Every docs command loads + Microsoft.PowerShell.PlatyPS, which stays loaded once the command returns. That is a + declared, idempotent dependency rather than a hazard by itself, but it means the first + docs test silently changes the conditions every later test runs under, and a test that + needs the module absent has no way to get there. + + A separate runspace is not enough, because assemblies load per process rather than per + runspace, so unloading the module does not unload what it brought with it. Only a + separate process starts clean. Pester recommends the same technique for session + isolation, see https://pester.dev/docs/usage/mocking. + + This helper was originally written for a stronger reason that no longer applies: + during the migration in #105 the suite had to exercise platyPS 0.14.2 and + Microsoft.PowerShell.PlatyPS 1.x in one run, and the two cannot coexist at all -- + each loads its own YamlDotNet.dll through NestedModules with a different assembly + identity, so whichever imports second fails with "Assembly with same name is already + loaded" (PowerShell/platyPS#579). Only 1.x is a dependency now, so that conflict is + history; the session hygiene above is why the jobs stay. .PARAMETER ModulePath Path to the built PowerShellBuild module to import inside the job. .PARAMETER CommandName @@ -329,7 +341,10 @@ function Invoke-TestPSBuildPesterInJob { Testing Test-PSBuildPester means Pester testing Pester, so the job is doing two jobs at once: it gives the inner run its own session, and it lets that session pin a Pester version independently of the outer framework. Two Pester majors cannot coexist in one - session, so without the job the matrix could only ever cover the version already loaded. + session, so without the job the matrix could only ever cover the version already + loaded. Since #172 raised the floor to 6.0.0 the matrix spans one major, so today the + job buys isolation rather than reach -- but it is what would let a second major be + added back without the two runs interfering. .PARAMETER ModulePath Path to the built PowerShellBuild module to import inside the job. .PARAMETER InnerPesterVersion