Repository navigation
psake 5.x spike: assess breakage under psake 5.0.4 (clean bump, no extras) #155
Description
Activity
- addedenhancementNew feature or requestNew feature or requestwayfinder:taskWayfinder ticket: manual work that unblocks a decisionWayfinder ticket: manual work that unblocks a decision
on Aug 20, 2026 - added a parent issue
on Aug 20, 2026 Spike result: MIGRATE
Ran the clean bump (no #117 extras). Under the abort criterion agreed before the spike, the
consumer-facingPowerShellBuild/psakeFile.ps1survives psake 5.0.4 with zero changes —
no task renames, no$PSBPreferencechange. So psake 5.x stays in v1.0.0.Method
requirements.psd1pinspsake = '4.9.0'; PSGallery is at 5.0.4. Rather than swap the pin
(which leaves the other version visible and shadowing), each run used an isolated module root
prepended toPSModulePath, so exactly one psake version was resolvable — verified for the
parent session and forStart-Jobchildren, which matters becausebuild.tests.ps1and
IBTasks.tests.ps1spawn child builds.Run Result Full suite, psake 4.9.1 (baseline) 428 passed / 0 failed Full suite, psake 5.0.4 418 passed / 12 failed Full suite, psake 5.0.4 + the one-line fix below 428 passed / 0 failed Full suite, psake 4.9.1 + the same fix 428 passed / 0 failed (no regression) Checked against the official guide
psake/psake docs/migration-v4-to-v5.md
lists four breaking changes. None apply here:default.ps1no longer auto-detected — we pass-buildFile ./psakeFile.ps1explicitlypsake.ps1/psake.cmdremoved — we already useImport-Module psake+Invoke-psake- .NET Framework < 4.0 unsupported — no
Frameworkcalls anywhere $frameworkglobal removed — not used
The only
$framework/config_defaultmatches in the repo are a local function parameter and
a string literal insideBuild/Convert-PSAke.ps1, an unrelated psake→Invoke-Build converter.
OutputHandler/ColoredOutput/psake-config.ps1are likewise unused.The guide also confirms two things the spike measured directly:
$psake.build_successis
explicitly still supported, andInvoke-psakenow returns aPsakeBuildResult.API surface: a superset, no removals we touch
Taskkeeps every v4 parameter and addsDefinition;PropertiesaddsHashtable;
FormatTaskName,Get-PSakeScriptTasks -BuildFile, andInvoke-Psake's
-BuildFile/-TaskList/-NoLogo/-Parametersare unchanged. Verified working under 5.0.4:$psake.context.currentTaskName— used atPowerShellBuild/psakeFile.ps1lines 178, 201, 213$psake.context.Peek().Tasks.Keys— line 381$psake.build_success—build.ps1, andtests/TestModule/build.ps1(the consumer simulation)
Renamed but unused by this repo:
Exec→Execute,-notr→-NoTimeReport, and
Include'sfileNamePathToInclude→Path/LiteralPath. (TheInclude = ...hits in
psakeFile.ps1andBuild-PSBuildModule.ps1areCopy-Itemhashtable keys, not the psake
keyword.)The 12 failures: one latent bug in our own test file
All 12 came from a single container,
tests/Manifest.tests.ps1, failing with:InvalidOperationException: A 'break' or 'continue' statement with a label that does not match
any enclosing loop escaped from your code. (pester/Pester#2669)Root cause, isolated to a two-file reproducer:
Set-BuildEnvironment -ForceinBeforeAll.
BuildHelpers'Get-BuildVariableusesbreakinsideswitchblocks; called from a Pester
BeforeAll, that break unwinds out of the block. psake 4.9.x's call structure absorbs it,
psake 5.0.4's (Invoke-BuildPlan.ps1,& $task.Action) does not, so Pester fails the container.Pester file with Set-BuildEnvironment in BeforeAll, run inside a psake task: psake 4.9.1 => Passed psake 5.0.4 => Failed Same file without that call: psake 4.9.1 => Passed psake 5.0.4 => PassedThis is not documented in the upstream migration guide — worth reporting to BuildHelpers,
and worth knowing for any consumer whose Pester tests callSet-BuildEnvironment.Fix is one line —
build.ps1already callsSet-BuildEnvironment -ForcebeforeInvoke-psake,
so the call insideBeforeAllis redundant during a build:if (-not $env:BHProjectName) { Set-BuildEnvironment -Force }
A dummy enclosing loop (
foreach ($once in 1) { ... }) does not absorb it — tested and
rejected. Committed onspike/psake-5x
(5ec9a01) for the migration PR to pick up. StandaloneInvoke-Pesterwith a cleared
environment still passes 10/0, so the guard does not break out-of-build runs.One consumer-visible behavior change
Invoke-psakenow emits aPsakeBuildResultto the pipeline (Success,Duration,Tasks,
ErrorMessage, ...) where v4 emitted nothing. Any consumer whosebuild.ps1assigns or pipes
the result ofInvoke-psakegets an object that was not there before. Ours ignores it, so this
is a migration-guide entry, not a code change.Correction to an earlier read: I initially measured the failing build exiting
0, which
would have meant CI going green on a red build. That was an artifact of my harness —exitin
a&-invoked script sets$LASTEXITCODEwithout terminating the wrapper. Measured directly,
$psake.build_successisFalseandbuild.ps1's computed exit code is1. No exit-code
regression. LikewiseTask default { <action> }is rejected by 4.9.1 too — a pre-existing
quirk, not a psake 5 change.Not attempted, by design
Task caching (
Inputs/Outputs), LLM Pester output, externalPesterConfigurationfile
support, andFormat-PSBuildResult— the #117 extras. They stay out of v1.0.0.Follow-up
Migration work is now specifiable and is filed as #161. Given the consumer-facing psakeFile
needs no changes, it is a single small PR, not a chain.Resolved: MIGRATE. psake 5.x stays in v1.0.0 — the consumer-facing psakeFile needs no changes. Findings and evidence in the resolution comment above; migration work filed as #161.
Part of #120 (Phase 2 — psake 5.x bump).
Question
What actually breaks under psake 5.x, and does the damage stay inside this repository or reach consumers?
Two psake files are in play and they carry very different risk:
psakeFile.ps1at the repo root — this repo's own build. Breakage here is ours to fix.PowerShellBuild/psakeFile.ps1— the consumer-facing task definitions that every downstreambuild.ps1dot-sources. Breakage here is a breaking change for everyone.Scope
Keep this spike clean.
requirements.psd1currently pinspsake = '4.9.0'; PSGallery is at 5.0.4. Bump the pin, run the build, record what happens.Explicitly out of scope for the spike — these are what sank the previous attempt (#117, closed): task caching via
Inputs/Outputs, LLM-mode Pester output, externalPesterConfigurationfile support, and the new publicFormat-PSBuildResultfunction. Those are 1.1.0 features, not a dependency bump.Known reproducer
psake 5.0.4 installed side by side with the pinned 4.9.0 already shadows it on at least one maintainer machine and fails
Manifest.tests.ps1. That failure is a starting point, not necessarily the whole story — confirm whether it is a genuine 5.x incompatibility or an artifact of two psake versions being visible at once.Abort criterion (agreed before the spike, deliberately)
PowerShellBuild/psakeFile.ps1survives 5.x with only mechanical changes.$PSBPreferencecontract that consumers'build.ps1files depend on.This criterion is fixed in advance so the call is made on the findings rather than on sunk cost. Record which side the spike landed on, with evidence, as the resolution comment.
Done when
The findings are posted here and the migrate/cut call is made. Migration PR(s) are then created as follow-ups — their number and shape depend on what this spike finds, so they are deliberately not charted yet.