Repository navigation
🪲[Bug]: Publish Module is failing #528
Description
Activity
- linked a pull request that will close this issue🪲 [Fix]: New module versions publish to the PowerShell Gallery #529
on Sep 1, 2026 MariusStorhaug commented
on Sep 1, 2026 MemberMore actionsArnaud CHARLES (@arnaudcharles) Checking it now! Thank you for the patience after all those changes :)
Just did some heady refactoring after seeing how to build agents and having the possibility of colocating actions into a reusable workflow from the same repo. Will validate the changes and check the compatibility ASAP.MariusStorhaug commented
on Sep 1, 2026 MemberMore actionsReviewed the scenario end to end against the PSWEE runs. There are two defects here; #529 fixes one of them.
Defect 1 — the crash (correctly diagnosed in this issue)
publish.ps1:148usedFind-PSResource ... -ErrorAction Stop. PSResourceGet raises a terminatingPackageNotFound(Microsoft.PowerShell.PSResourceGet.UtilClasses.ResourceNotFoundException) when the version is absent, so the existence probe introduced in #512 breaks every first-time publication, exactly as described.Verified locally: the regression test added in #529 fails against
mainand passes with the one-line change. #529 fixes the reported bug.One nit on the fix:
-ErrorAction SilentlyContinueswallows all errors, not just "not found". During a transient Gallery outage$publishedPackageis null, publish is attempted anyway, and if the version does already existPublish-PSResourcefails with a 409 — losing the resume behaviour the probe exists to provide. Narrowing to thePackageNotFound,Microsoft.PowerShell.PSResourceGet.Cmdlets.FindPSResourceerror ID keeps the original intent.Defect 2 — the wrong version was being published
Correct version 1.4.0 Version attempted 1.3.1 PSWEE PR #12 carries the
Minorlabel and merged at 19:46:58 asf8c59e6. Latest GitHub release and Gallery version were both 1.3.0, so the resolved version should have been 1.4.0. The Plan job resolved 1.3.1 via a patch bump.Cause chain:
- The
pushrun forf8c59e6(run33551501626) was cancelled one second after start. PSWEE's caller still uses the pre-v8 template:group: ${{ github.workflow }}-${{ github.ref }}withcancel-in-progress: true, and nounlabeledtype. The v8 contract requirescancel-in-progress: falseand thegithub.event.pull_request.number || github.refkey precisely so a release-capable push is never interrupted. - Recovery was attempted as a
workflow_dispatchonmain. InGet-PSModuleSettings/src/main.ps1:245, PR association for a commit is gated onif ($isPush -and $commitSha). A manual dispatch therefore yieldsContext.PullRequest = null,Resolve-PSModuleVersionlogs "Using direct default-branch release context with the default patch bump", and theMinorlabel is silently discarded.
Consequence: even with #529 merged, that dispatch would publish 1.3.1 instead of 1.4.0 — and 1.3.1 would then permanently occupy the Gallery, since Gallery versions cannot be reclaimed.
What should have happened
- The merge push to
mainshould have run to completion and published 1.4.0, because the associated merged PR carries theMinorlabel. - The Gallery lookup for a brand-new version should be a non-fatal "not found" and proceed to publish.
- A
workflow_dispatchrecovery on the default branch should resolve the merged PR forHEADand honour its version label, or refuse to release — rather than silently downgrading to Patch.
Suggested follow-ups
- Merge 🪲 [Fix]: New module versions publish to the PowerShell Gallery #529, ideally with the error filter narrowed to
PackageNotFound. - Track defect 2 separately:
workflow_dispatchon the default branch must resolve the merged PR for the dispatched SHA and honour its label, or fail loudly. - Arnaud CHARLES (@arnaudcharles) — PSWEE's caller workflow needs the v8 concurrency block (
cancel-in-progress: false, PR-or-ref key, and theunlabeledPR type). The merge push being cancellable is what forced the manual recovery in the first place. See Calling the workflow.
- The
arnaudcharles commented
on Sep 1, 2026 AuthorMore actionsThanks Marius Storhaug (@MariusStorhaug) for the quick answer.
Regarding PSWEE I did my first try with 1.3.1 but ended up moving to 1.4.0 as it make more sense. This is why copilot found an irregularity.
I will wait the publication of the fix and try again on 1.4.0- added a commit that references this issue
on Sep 2, 2026 MariusStorhaug commented
on Sep 2, 2026 MemberMore actionsMarius Storhaug (@MariusStorhaug) Applied the review nit on #529, and the narrowing exposed that the test harness could not actually observe the behaviour it asserted.
1. Probe narrowed to
PackageNotFound-ErrorAction SilentlyContinueswallowed every lookup failure. The probe now runs with-ErrorAction Stopand only treats thePackageNotFounderror ID as "not yet published":$publishedPackage = $null try { $publishedPackage = Find-PSResource -Name $name -Version $publishPSVersion -Repository PSGallery -ErrorAction Stop } catch { if ($_.FullyQualifiedErrorId -notlike 'PackageNotFound,*') { throw } Write-Host "$name $publishPSVersion is not on the PowerShell Gallery yet." }
Verified against the live Gallery — the two cases are cleanly distinguishable by error ID:
Scenario FullyQualifiedErrorIdAbsent version ( PSSemVer 99.99.99)PackageNotFound,…FindPSResourceAbsent module PackageNotFound,…FindPSResourceUnreachable repository (outage) HttpRequestCallFailure,…FindPSResourceThe
PackageNotFound,*prefix match keeps this robust if the cmdlet name in the ID ever changes.2. The recovery tests were not testing anything
Three defects in the harness, all found while validating the narrowed fix:
The assertions were vacuous.
Publish-PSResourcewas shimmed to set$script:publishInvoked = $true, butpublish.ps1runs via&in its own scope, so the flag never propagated back.$script:publishInvokedstayed$falseunconditionally — soShould -BeFalsepassed whether or not publish ran. Replaced with a hashtable captured byGetNewClosure(), which is shared by reference and does propagate. (NoteGetNewClosure()captures locals, so the collector must be assigned unqualified before being exposed as$script:.)The marker-file variant raced. The other case wrote a marker under
$env:GITHUB_WORKSPACE. Environment variables are process-wide and Pester's parallel runspaces share one process, so the marker landed in another test file'sTestDrive:DIAG marker-target=/private/tmp/Pester_icli/workspace/publish-invoked DIAG expected=/private/tmp/Pester_ptrc/workspace/publish-invokedThe not-found shim could not detect the bug. It used
$PSCmdlet.ThrowTerminatingError(...), which ignores-ErrorActionentirely — unlike the real cmdlet. That shim throws underStopandSilentlyContinue, so it could not tell the fix from the defect. Now usesWrite-Errorwith the realPackageNotFounderror ID, which honours-ErrorActionexactly as PSResourceGet does.Added a third case asserting a non-
PackageNotFoundfailure stays fatal and does not publish. Each test is confirmed to fail against the specific defect it guards:Implementation Test that catches it -ErrorAction Stop(original bug)publishes when the resolved version is not in the Gallery -ErrorAction SilentlyContinue(the nit)fails without publishing when the Gallery lookup errors for another reason Narrowed to PackageNotFoundall pass 3. Unrelated:
Test-Actionswas red on this branchThe 4
Get-NextPrereleaseNumberfailures were test pollution, not a version-resolution defect.Remove-Item -Path function:global:Xsilently no-ops —global:is a scope qualifier, not a valid provider path segment, and-ErrorAction SilentlyContinuehid the failure. TheFind-PSResourceshim therefore survivedAfterAlland shadowed the real cmdlet for later test files, soGet-NextPrereleaseNumbersplattedPrerelease = $trueinto the two-parameter shim. Same latent bug fixed for theghandgitshims inRelease-PSModule.WhatIf.Tests.ps1.Worth a separate issue:
Test-Actionsnever runs in parallel.github/workflows/Test-Actions.ymlbuilds a config withRun.Parallel/Shuffle, asserts the options applied, then discards it and creates a freshNew-PesterConfigurationfor the actual run. Parallel and shuffle are validated but never used, so theGITHUB_WORKSPACErace above could not have been caught in CI. I've left the workflow alone here to keep this PR scoped. The suite now passes both sequentially and with the intended parallel config (73/73, repeated runs), so enabling it should be safe.Status: all 52 checks green on
c8d1ade. Defect 2 (workflow_dispatchdiscarding the merged PR's label) is untouched and still needs its own issue.Arnaud CHARLES (@arnaudcharles) going to 1.4.0 is the right call — 1.3.1 was only ever an artifact of the cancelled push plus the patch-bump fallback.
MariusStorhaug commented
on Sep 2, 2026 MemberMore actionsReproduced independently in
MariusStorhaug/MariusTestModuleConfirmed the defect on a second module, in my own account, on a caller that is already correctly configured for v8 — so this is a clean reproduction of Defect 1 with no interference from Defect 2.
Failing run: MariusStorhaug/MariusTestModule run 33596331743 → Publish-Module job
The failure is byte-for-byte the reported one, at the same line of the same file:
Find-PSResource: /home/runner/work/MariusTestModule/MariusTestModule/_wf/.github/actions/Publish-PSModule/src/publish.ps1:148 Line | 148 | … edPackage = Find-PSResource -Name $name -Version $publishPSVersion -R … | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | Package with name 'MariusTestModule', version '0.4.13' could not be | found in repository 'PSGallery'. ##[error]Process completed with exit code 1.Why this reproduction is the cleaner signal
Trigger pushonmain(merge of #62,86edc38)Caller ref PSModule/Process-PSModule/.github/workflows/workflow.yml@v8Caller concurrency cancel-in-progress: false, PR-or-ref group keyPlan job success — resolved 0.4.13Publish-Module failure at the Gallery existence probe Publish-Site success Unlike the PSWEE case, this run was not cancelled and needed no manual
workflow_dispatchrecovery. The caller already carries the v8 concurrency block, and the resolved version was correct: Gallery latest and latest GitHub release were both0.4.12,0.4.13was the right next patch, and PR #62 carried no bump label (so autopatching applied correctly).That isolates the cause. Nothing about version resolution was wrong here — the run failed purely because the existence probe made an absent version fatal. Every new version on any module hits this, which matches "any first release, and every subsequent new version".
Blast radius confirmed
0.4.13reached neither destination:- PowerShell Gallery latest is still
0.4.12;0.4.13is absent. - No
0.4.13GitHub release exists — Publish-Module fails before release creation.
So the stage is fail-closed, not partially applied. Nothing needs cleanup before re-running, and no Gallery version was burned.
Correction to an earlier draft of this note: the daily scheduled
mainruns in this repo have also been failing since at least 2026-08-26, but not for this reason. Those runs complete with zero jobs and no downloadable logs, so they fail at workflow startup before any action executes. Unrelated to this defect, and not investigated here.- PowerShell Gallery latest is still
MariusStorhaug commented
on Sep 2, 2026 MemberMore actionsNext: end-to-end validation against the branch
The unit tests prove the probe logic in isolation, and #528 reproduces the defect end to end. What is still unproven is that the fix works in a real pipeline, so I am pointing
MariusStorhaug/MariusTestModuleat this PR's branch and driving a real publication through it.Approach
MariusTestModulecurrently callsPSModule/Process-PSModule/.github/workflows/workflow.yml@v8. I am opening a PR there that switches the caller to@copilot/fix-publish-module-errorand makes one trivial source change (a function description) so there is something to release.This works because
Publish-Module.ymlchecks out its own actions at the resolved workflow commit rather than a floating tag:- name: Checkout Process-PSModule uses: actions/checkout@... with: repository: ${{ job.workflow_repository }} ref: ${{ job.workflow_sha }} path: _wf
So changing the caller's
uses:ref is sufficient —_wf/.github/actions/Publish-PSModule/src/publish.ps1will be the fixed file fromc8d1ade, with no vendoring or pinning workarounds needed.What the reproduction gives us for free
The failed run left the Gallery at
0.4.12with no0.4.13release, so the module is a clean starting point:0.4.13is still an unpublished version, and it is exactly the version that previously failed. That makes this a direct before/after on the same version rather than an approximation.Success criteria
Stage Expected Plan resolves the next version Publish-Module (PR run) prereleases publish to the Gallery Publish-Module (merge to main)stable version publishes; no PackageNotFoundfailureGitHub release created for the new version The decisive signal is the merge-to-
mainpublication: the branch'sFind-PSResourceprobe must return "not found" without failing the job, then hand off toPublish-PSResource.I will also confirm the narrowed error filter did not break the resume path — re-running the publish once the version exists should skip the upload with the
♻️ Resuming Gallery-only publicationnotice rather than attempting a conflicting re-upload.Reporting results back here either way. If the fix does not hold end to end, that is the more useful finding.
MariusStorhaug commented
on Sep 2, 2026 MemberMore actionsEnd-to-end validation: the fix works
Validated against a real publication in
MariusStorhaug/MariusTestModulevia MariusStorhaug/MariusTestModule#63, with the caller pointed at@copilot/fix-publish-module-error. Both branches of the probe are now confirmed on live infrastructure.Branch 1 — new version publishes (the reported defect)
Run: 33597824748 → Publish-Module — success
##[group]Publish to PSGallery Publish module to PowerShell Gallery using API key from environment. MariusTestModule 0.4.13-validatepublishfixpr529001 is not on the PowerShell Gallery yet. ##[notice]https://www.powershellgallery.com/packages/MariusTestModule/0.4.13-validatepublishfixpr529001 Gallery publishing complete. Version: [0.4.13-validatepublishfixpr529001]That "is not on the PowerShell Gallery yet" line is the new code path, at the same
publish.ps1:148probe that previously terminated the job. Same repository, same module, same0.4.13base version that failed in run 33596331743 — this is a direct before/after, not an approximation.Independently confirmed the package is live on the Gallery, so the success is a real upload rather than a silently skipped stage.
Branch 2 — resume path intact (the review nit)
The concern with narrowing the filter was breaking the idempotent resume the probe exists to provide. Re-ran the same publish job with the version now present:
Re-run: job 100146802704 — success
##[notice]MariusTestModule 0.4.13-validatepublishfixpr529001 is already published to the PowerShell Gallery. Gallery publishing complete. Version: [0.4.13-validatepublishfixpr529001]No re-upload attempted, no 409. Release-PSModule also resumed correctly:
GitHub release [v0.4.13-...] already exists. Resuming its artifact upload.Summary
Condition Expected Result Version absent from Gallery log and publish ✅ published Version already on Gallery skip upload, continue ✅ skipped with ♻️noticeNon- PackageNotFoundfailurestay fatal ✅ covered by unit test Gallery state package live ✅ confirmed One thing worth noting
My first validation run came back all-green with
Publish-Moduleskipped — no publication, so the fix was untested despite the green checkmark. Cause: the PR carried no labels, and for an open PRReleaseTyperesolves toNone(AutoPatchingapplies to the merge, not the open PR). Adding theprereleaselabel produced the real publication.Flagging it because a green run here does not by itself mean the publish path executed. Anyone re-validating should confirm
Publish-Moduleactually ran and check for theis not on the PowerShell Gallery yetline, rather than trusting the overall run status.Still outstanding
- PR #63 is intentionally left as a draft and must not merge with the caller pinned to a branch. It reverts to
@v8once 🪲 [Fix]: New module versions publish to the PowerShell Gallery #529 ships in a tag. - Defect 2 (
workflow_dispatchon the default branch discarding the merged PR's label) is unchanged and still needs its own issue. Related observation from this exercise: theworkflow_dispatchI ran on the feature branch skipped publish entirely, which is correct — the defect is specific to dispatch on the default branch.
- PR #63 is intentionally left as a draft and must not merge with the caller pinned to a branch. It reverts to
MariusStorhaug commented
on Sep 2, 2026 MemberMore actionsConfirmed fixed in production —
v8.0.4v8now points at68696b6(released as v8.0.4), and I verified the narrowed probe is present at the tag.MariusStorhaug/MariusTestModulewas re-pointed to@v8and driven through a real release.The stable release path now works
MariusStorhaug/MariusTestModule#63 merged, triggering run 33609549477 → Publish-Module — success:
GalleryVersion : 0.4.13 MariusTestModule 0.4.13 is not on the PowerShell Gallery yet. ##[notice]https://www.powershellgallery.com/packages/MariusTestModule/0.4.13 Gallery publishing complete. Version: [0.4.13]0.4.13is the exact version that failed in run 33596331743. Same module, same version, same probe — now publishes.Verified independently on both destinations:
Destination Before After PowerShell Gallery latest 0.4.120.4.13GitHub release none for 0.4.13v0.4.13Coverage across both paths and both branches
Path Version Run Result Prerelease, branch build 0.4.13-…00133597824748 ✅ published Resume (version present) 0.4.13-…001re-run ✅ skipped upload Prerelease, released @v80.4.13-…00233608326141 ✅ published Stable, released @v80.4.1333609549477 ✅ published The stable path is the one that matters for consumers and was previously unproven — the earlier validation only exercised prereleases against a branch build. This closes that gap.
The validation PR's temporary branch pin has been reverted to
@v8and the PR is merged, so the test module is back on a supported ref with no leftover pin.Two notes from the release
- The post-merge
Workflow-Test [Default]push run failed, but not from this change:Unable to download artifact(s): Failed to ListArtifacts: … (403) Forbidden. GitHub infrastructure, non-retryable.WithManifestpassed and itsPublish-Modulesucceeded. - The
Releaserun for the merge sat ataction_requiredwith zero jobs until approved manually, which is why the tag lagged the merge by ~50 minutes. Every earlierReleaserun on 🪲 [Fix]: New module versions publish to the PowerShell Gallery #529 ran without approval, so this looks specific to thepull_request: closedevent on a PR authored byapp/copilot-swe-agent. Worth watching on the next merge — if it recurs, releases are effectively gated on a human click and that deserves its own issue.
Still open
Arnaud CHARLES (@arnaudcharles) the fix is live in
v8.0.4, so PSWEE 1.4.0 should publish now. Two things on your side:- Your caller still needs the v8 concurrency block (
cancel-in-progress: false, PR-or-ref group key, and theunlabeledPR type). The cancelled merge push is what forced the manual recovery that produced the wrong version — see Calling the workflow. - Until that is in place, avoid
workflow_dispatchon the default branch as a recovery route: Defect 2 below means it silently discards the merged PR's version label.
Defect 2 remains unfixed and untracked —
workflow_dispatchon the default branch resolves no associated pull request (PR association is gated on$isPushinGet-PSModuleSettings/src/main.ps1), so a manual recovery run discards the merged PR's version label and silently falls back to Patch. Higher blast radius than the bug just fixed, because Gallery versions cannot be reclaimed once taken. This issue can close on the fix that shipped, but Defect 2 needs its own issue before the analysis here is lost.- The post-merge
arnaudcharles commented
on Sep 3, 2026 AuthorMore actionsMoved back to v8 and working like expected ! Thanks Marius Storhaug (@MariusStorhaug)
Reacted by Marius Storhaug
Describe the bug
When the CI run, after checking all your changes, fixing BC in my repo I can still see this
For me there is an issue on the code on src/publish.ps1. Since every brand-new version is, by definition, not yet on the Gallery it cannot proceed. And due to -ErrorAction Stop we cannot go further.
In
.github/actions/Publish-PSModule/src/publish.ps1, region "Publish to PSGallery":Version information
NA
To reproduce
Push something on a repo using PSModule
Code snippet
Relevant output