You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Default-branch recovery retains release intent and immutable artifacts - #531
Default-branch recovery retains the merged pull request's configured bump or skip intent and prevents a new dispatch from computing another version for an already-released commit. The bounded candidate rejects recognized prerelease ownership conflicts and unsafe GitHub asset replacement. This unmerged draft still has terminal-provenance and cleanup-mutation limits and depends on separately coordinated Gallery ownership/pre-publication safety work.
Fixed: Recovery retains the intended source, version, and artifact
A default-branch push and recovery dispatch use the same exact merged-PR association. Valid direct releases remain distinct. An unmatched association stops a release-capable event, not a documentation-only push; lookup errors propagate. Default-branch detection and associated PR base refs are case-sensitive full branch identities, so a similarly named tag or differently cased branch cannot select stable publication.
Normal framework callers need no configuration or invocation edit beyond selecting the eventual compatible release after the stated prerequisites are satisfied. Before retrying, retain the original run's resolved version/tag, source, and tested artifact. A tag must be unclaimed or resolve to that source, including annotated tags. Dispatch uses only the current default-branch tip; for older content or a commit that already has a GitHub release, rerun the original failed publication job rather than resolve another bump. Conflicting or unverifiable ownership requires reviewed forward-only reconciliation, never retagging or overwriting a version. This draft is not a production dependency.
The bounded GitHub publisher verifies tag/source affinity even when a release is absent and rechecks before upload. Missing uploads may resume for the original source. Existing bytes are retained only when their published SHA-256 digest matches; differing, ambiguous, or unverifiable assets fail. Uploads never use --clobber. The optional existing CommitSha input and original GITHUB_SHA context remain the source contract.
Prerelease creation and retry use the same immutable build SHA, not a mutable head branch. Complete authored or generated notes remain intact, followed by a controller-owned v1 provenance footer for the exact base repository, PR number, and source. Recognized existing footer evidence must agree with that producing context before resume/upload. Repository identity is case-insensitive; source identity is exact. Recognized conflicts stop before creation, upload, PR comment, or success output. Matching-owner missing-upload retries remain supported.
Remaining provenance limit: The frozen reader recognizes only a single-line terminal v1 comment. Wrapped or unsupported terminal comments return no evidence, and the known-owner-only guard can skip them. The exact-head owner assessment confirms this gap affects the candidate. The canonical terminal-comment correction and negative publisher coverage must come from the safety delivery or an explicitly authorized bounded correction; this PR does not claim unreadable provenance is safely handled.
Cleanup selection verifies producing-PR provenance and the actual tag commit. Another PR's records, conflicting sources, stable releases, and the currently published tag are excluded; legacy records without readable producing-PR/source proof are retained. Adopting this version does not rewrite or bulk-delete those records. WhatIf remains non-mutating.
Remaining mutation limit: Selection stores tag names, and the deletion loop does not freshly revalidate producing context, release identity, or tag/source ownership before gh release delete --cleanup-tag. A replacement claim after selection can reach deletion. Do not treat source-bound selection as concurrent-cleanup clearance. The coordinated correction must validate mutation identity and retain a tag when conditional ownership cannot be guaranteed. No live cleanup is authorized by this work.
Review disposition: Permanent matching-tag/source foreign repository/PR zero-upload tests and matching-owner/ordinary controls are committed and verified. The safety owner's exact-head assessment confirms the specific ask at review comment 4432389858 is satisfied. Its narrow thread disposition is coordinated separately from the complete review. The full summary still requests ownership/source/concurrent-cleanup assessment; no human approval, overall clearance, or clean review is inferred from Blessed=True.
Publication prerequisite:#513 must replace Gallery-only numeric-version guessing with proven same-source/same-artifact recovery, and #547 must run source-bound preflight before any Gallery mutation. The #548 module/version coordinate is a necessary prerequisite, not behavior present in this candidate. Tag/source agreement alone does not prove which same-version Gallery package/source won under another prefix. These systemic contracts remain separately owned and unimplemented here; the draft stays blocked for merge/publication.
Replacing AutoPatching with configurable DefaultBump and owned-label defaults remains the separately scoped #524. Its retained Skip finding and held test work are unchanged. No new scalar DefaultBump invocation interface, date strategy, Discord delivery, fleet migration, secret, permission, or rule change is introduced.
Technical details
Pushed and reviewed head: 50f16425797ec67375d47262c8c79d3507fb2b21. Guard commit 925cd0bb02aab31e4c110064a395bfe864f8d337 follows frozen helper/guard input d06a8775f5e37d14fc9e641ef364cb42ada260b0; comparison main is 64ffb1d87f86bd5d487891fdb140b78385a00531. Ordinary commits preserve all original/user work. The authorized source incorporation adds seven lines in Release-PSModule/src/release.ps1, with source blob exactly matching the owner's corrected patch, 9f7f1b3e03ced1dfb3e41515a29f37700dff6ec3. The authorized test-only commit adds 47 lines in Release-PSModule.WhatIf.Tests.ps1. No shared algorithm/helper or other safety-delivery change is taken.
Actual settings-controller and composed tests cover event/ref identity, important-change-before-association ordering, already-released commit rejection, and configured bump/skip decisions. Publisher behavior covers immutable source fallback, annotated/standalone/concurrently changed tags, matching asset retention, missing-upload retry, digest rejection, and preserved notes/provenance.
Permanent ownership regressions exercise the real publisher controller and footer decoder using the existing local GitHub mocks. Two cases keep tag/source matching but encode a foreign repository or PR. Each asserts zero uploads, an explicit conflict exception, and no success output. A matching-owner missing-upload case succeeds; the ordinary-retry control is unchanged. Against isolated original d06a877 source, both new conflicts fail with Expected 0, but got 1 upload while controls pass. With the actual guard all four selected cases pass. Supplemental session experiments also verify source mismatch and repository case equivalence. No real publication or guard/decoder replacement is used.
All 137 local action tests pass with actual shuffled/parallel execution; PowerShell analysis is clean. Environment-sensitive containers use a per-process mutex. Hosted parallel execution is not inferred from the discarded configuration probe. At this exact head, Test actions, Docs Build, Lint code base, and Docs Lint succeed. The real hosted suite reports 137 passed, 0 failed/skipped/not-run; the complete rollup is success with no omitted contexts.
The candidate composes with known #541 immutable 2001551566898e59efc764e68450c2238667d607 as tree 9ea691dcef75287a5d9e0d6fbaf775911e7234ed, also passing 137 tests. Neither PR was merged; #541 workflow/fixture/pipeline-doc changes were not copied into #531. This is evidence for those known immutable changes, not a later #541 head.
Full review 5723830059, submitted 2026-10-31T16:45:54Z, is explicitly bound to the current head. The runner exits 0 with zero new inline comments, but the complete summary says Needs a closer look and requests human assessment. Its retained coverage ask is now confirmed fulfilled by the exact-head owner assessment, not interpreted as whole-review clearance. Original guard thread PRRT_kwDOKhokxM6yRjac, root 4432028509, was resolved by Copilot after review of the incorporated guard. Specific coverage thread PRRT_kwDOKhokxM6ySa-k, root 4432389858, is handled only for its scoped ask, separately from the remaining review/native limits.
Remaining source limits are verified read-only: Release-PSModule.Helpers.psm1:100-102 returns no evidence on wrapped/unsupported terminal comments; cleanup.ps1:83,97-107 selects tag names then deletes without fresh release/tag mutation checks. General helper/controller/test writes remain held with the safety owner. No parallel fix, inferred cleanup authorization, draft production pin, or lifecycle framework is introduced.
Main's effective rules were read without a required-status-check rule. The coordinator owns the repository-only enforcement proposal and approval; documentation does not create enforcement. Test actions and Docs Lint/Build are path-filtered; universal Lint code base excludes docs-owned paths, so unconditional enforcement needs an applicability/coverage decision. Keep the coordinated preflight → Gallery recovery → bounded recovery composition and #531-before-#524 integration order; no unmerged change is described as delivered.
Release: Yes - the versioned framework's supported recovery, cleanup, prerelease retry, and GitHub artifact-resume correctness changes for module-maintainer integrations.
Version bump: Patch - explicit compatible-fix intent through release:patch. Released Release-GHRepository v2.0.3 still uses retained legacy Patch/Fix mappings that agree on patch; owned-label caller/check adoption is a separate prerequisite.
Mode: Stable - the target is the native default-branch release route. Final version/base, tag, immutable source, and change baseline are resolved by the release process, not predicted here.
A workflow_dispatch on the default branch is the documented recovery route for
a failed or cancelled release run. Pull request association was gated on
$isPush, so a dispatch resolved no pull request, saw no version label, and
silently applied the AutoPatching patch fallback.
Widen the gate to cover a manual dispatch on the default branch, so the same
association and selection path runs for the same merge commit.
Also fail loudly when a merged default-branch pull request is associated with
the commit but does not match it, instead of falling back to a patch bump. A
wrong version published to the PowerShell Gallery cannot be reclaimed.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Extract the gate, selection, and no-pull-request decision from main.ps1 into
Resolve-ReleasePullRequest, with the GitHub lookup injected as a script block.
The composed logic that produced the wrong version is now covered directly
rather than re-implemented in a test.
Add Get-DiscardedReleasePullRequest so a merged default-branch pull request that
does not match the released commit fails the run instead of silently applying a
patch bump. Open pull requests and non-default-branch merges are ignored, so a
direct push and a feature-branch push are unaffected.
Each new test was verified to fail against the specific defect it guards.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Marius Storhaug (MariusStorhaug)
changed the title
🪲 [Fix]: Manual dispatch on the default branch honours the merged pull request's version label
🪲 [Fix]: Manual dispatch on the default branch honors the merged pull request's version label
Oct 31, 2026
This PR addresses #530 by making default-branch manual dispatches resolve the merged pull request associated with the dispatched commit, preserving its version-label intent in the release pipeline.
Changes:
Shares commit-to-PR resolution between pushes and default-branch dispatches.
Rejects unmatched merged-PR associations while preserving legitimate direct releases and propagating lookup failures.
Adds association regressions and composed version-resolution tests without changing public workflow inputs or versioning defaults.
Marius Storhaug (MariusStorhaug)
changed the title
🪲 [Fix]: Manual dispatch on the default branch honors the merged pull request's version label
Default-branch recovery retains the merged pull request's release intent
Oct 31, 2026
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
Release recovery can double-bump versions or overwrite newer artifacts, while ambiguous ref handling can trigger unintended stable releases or delete unrelated prereleases and tags.
Marius Storhaug (MariusStorhaug)
changed the title
Default-branch recovery retains the merged pull request's release intent
Default-branch recovery retains release intent and immutable artifacts
Oct 31, 2026
The current PR's repository check does not establish who produced each candidate release. A fork PR and a base-repository PR can both use feature/a; because publication records only that short branch as target_commitish, cleanup for the base PR can delete the fork PR's release and tag. Persist and verify the producing PR/repository on each release, and retain records whose ownership cannot be established.
Verify ownership before reusing a Gallery-only version
This GitHub-only check allows a newer minor-labelled merge to reuse an older merge's Gallery-only version: for example, Gallery has 1.1.0 while GitHub remains at 1.0.0. Get-ResolvedModuleVersion reuses 1.1.0, Gallery publication skips the existing package, and GitHub receives the newer source and artifact under that version. Verify ownership before reusing a Gallery-only version, or reject the recovery and direct the maintainer to the original run.
This ownership check runs after Publish-Module.yml has already published to the PowerShell Gallery. If another source owns the tag but that Gallery version is absent, rerunning the older job permanently publishes its artifact before the conflict is rejected. Run the tag/source and existing-asset checks before Gallery publication too, retaining the release-side checks for races.
A 404 here proves only that the release is absent, not that the tag is unclaimed. If the tag already points to another commit, gh release create reuses it despite --target, and this action uploads the wrong source's artifact. Resolve and verify existing tags even without a release, and recheck ownership before uploading to cover concurrent tag creation.
Git permits distinct branches such as main and Main, but -eq treats them as equal. An associated PR merged into Main can therefore make a valid release on main fail as an unmatched merge. Use -ceq here and in Select-PullRequestForPush at line 108 so both rejection and selection respect branch identity.
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
The ownership guard lacks retry tests for matching releases with a conflicting repository or PR footer, including assertions that no asset is uploaded.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Default-branch recovery retains the merged pull request's configured bump or skip intent and prevents a new dispatch from computing another version for an already-released commit. The bounded candidate rejects recognized prerelease ownership conflicts and unsafe GitHub asset replacement. This unmerged draft still has terminal-provenance and cleanup-mutation limits and depends on separately coordinated Gallery ownership/pre-publication safety work.
Fixed: Recovery retains the intended source, version, and artifact
A default-branch push and recovery dispatch use the same exact merged-PR association. Valid direct releases remain distinct. An unmatched association stops a release-capable event, not a documentation-only push; lookup errors propagate. Default-branch detection and associated PR base refs are case-sensitive full branch identities, so a similarly named tag or differently cased branch cannot select stable publication.
Normal framework callers need no configuration or invocation edit beyond selecting the eventual compatible release after the stated prerequisites are satisfied. Before retrying, retain the original run's resolved version/tag, source, and tested artifact. A tag must be unclaimed or resolve to that source, including annotated tags. Dispatch uses only the current default-branch tip; for older content or a commit that already has a GitHub release, rerun the original failed publication job rather than resolve another bump. Conflicting or unverifiable ownership requires reviewed forward-only reconciliation, never retagging or overwriting a version. This draft is not a production dependency.
The bounded GitHub publisher verifies tag/source affinity even when a release is absent and rechecks before upload. Missing uploads may resume for the original source. Existing bytes are retained only when their published SHA-256 digest matches; differing, ambiguous, or unverifiable assets fail. Uploads never use
--clobber. The optional existingCommitShainput and originalGITHUB_SHAcontext remain the source contract.Prerelease creation and retry use the same immutable build SHA, not a mutable head branch. Complete authored or generated notes remain intact, followed by a controller-owned v1 provenance footer for the exact base repository, PR number, and source. Recognized existing footer evidence must agree with that producing context before resume/upload. Repository identity is case-insensitive; source identity is exact. Recognized conflicts stop before creation, upload, PR comment, or success output. Matching-owner missing-upload retries remain supported.
Remaining provenance limit: The frozen reader recognizes only a single-line terminal v1 comment. Wrapped or unsupported terminal comments return no evidence, and the known-owner-only guard can skip them. The exact-head owner assessment confirms this gap affects the candidate. The canonical terminal-comment correction and negative publisher coverage must come from the safety delivery or an explicitly authorized bounded correction; this PR does not claim unreadable provenance is safely handled.
Cleanup selection verifies producing-PR provenance and the actual tag commit. Another PR's records, conflicting sources, stable releases, and the currently published tag are excluded; legacy records without readable producing-PR/source proof are retained. Adopting this version does not rewrite or bulk-delete those records.
WhatIfremains non-mutating.Remaining mutation limit: Selection stores tag names, and the deletion loop does not freshly revalidate producing context, release identity, or tag/source ownership before
gh release delete --cleanup-tag. A replacement claim after selection can reach deletion. Do not treat source-bound selection as concurrent-cleanup clearance. The coordinated correction must validate mutation identity and retain a tag when conditional ownership cannot be guaranteed. No live cleanup is authorized by this work.Review disposition: Permanent matching-tag/source foreign repository/PR zero-upload tests and matching-owner/ordinary controls are committed and verified. The safety owner's exact-head assessment confirms the specific ask at review comment 4432389858 is satisfied. Its narrow thread disposition is coordinated separately from the complete review. The full summary still requests ownership/source/concurrent-cleanup assessment; no human approval, overall clearance, or clean review is inferred from
Blessed=True.Publication prerequisite: #513 must replace Gallery-only numeric-version guessing with proven same-source/same-artifact recovery, and #547 must run source-bound preflight before any Gallery mutation. The #548 module/version coordinate is a necessary prerequisite, not behavior present in this candidate. Tag/source agreement alone does not prove which same-version Gallery package/source won under another prefix. These systemic contracts remain separately owned and unimplemented here; the draft stays blocked for merge/publication.
Replacing
AutoPatchingwith configurableDefaultBumpand owned-label defaults remains the separately scoped #524. Its retained Skip finding and held test work are unchanged. No new scalar DefaultBump invocation interface, date strategy, Discord delivery, fleet migration, secret, permission, or rule change is introduced.Technical details
Pushed and reviewed head:
50f16425797ec67375d47262c8c79d3507fb2b21. Guard commit925cd0bb02aab31e4c110064a395bfe864f8d337follows frozen helper/guard inputd06a8775f5e37d14fc9e641ef364cb42ada260b0; comparison main is64ffb1d87f86bd5d487891fdb140b78385a00531. Ordinary commits preserve all original/user work. The authorized source incorporation adds seven lines inRelease-PSModule/src/release.ps1, with source blob exactly matching the owner's corrected patch,9f7f1b3e03ced1dfb3e41515a29f37700dff6ec3. The authorized test-only commit adds 47 lines inRelease-PSModule.WhatIf.Tests.ps1. No shared algorithm/helper or other safety-delivery change is taken.Actual settings-controller and composed tests cover event/ref identity, important-change-before-association ordering, already-released commit rejection, and configured bump/skip decisions. Publisher behavior covers immutable source fallback, annotated/standalone/concurrently changed tags, matching asset retention, missing-upload retry, digest rejection, and preserved notes/provenance.
Permanent ownership regressions exercise the real publisher controller and footer decoder using the existing local GitHub mocks. Two cases keep tag/source matching but encode a foreign repository or PR. Each asserts zero uploads, an explicit conflict exception, and no success output. A matching-owner missing-upload case succeeds; the ordinary-retry control is unchanged. Against isolated original d06a877 source, both new conflicts fail with
Expected 0, but got 1upload while controls pass. With the actual guard all four selected cases pass. Supplemental session experiments also verify source mismatch and repository case equivalence. No real publication or guard/decoder replacement is used.All 137 local action tests pass with actual shuffled/parallel execution; PowerShell analysis is clean. Environment-sensitive containers use a per-process mutex. Hosted parallel execution is not inferred from the discarded configuration probe. At this exact head, Test actions, Docs Build, Lint code base, and Docs Lint succeed. The real hosted suite reports 137 passed, 0 failed/skipped/not-run; the complete rollup is success with no omitted contexts.
The candidate composes with known #541 immutable
2001551566898e59efc764e68450c2238667d607as tree9ea691dcef75287a5d9e0d6fbaf775911e7234ed, also passing 137 tests. Neither PR was merged; #541 workflow/fixture/pipeline-doc changes were not copied into #531. This is evidence for those known immutable changes, not a later #541 head.Full review
5723830059, submitted2026-10-31T16:45:54Z, is explicitly bound to the current head. The runner exits 0 with zero new inline comments, but the complete summary says Needs a closer look and requests human assessment. Its retained coverage ask is now confirmed fulfilled by the exact-head owner assessment, not interpreted as whole-review clearance. Original guard threadPRRT_kwDOKhokxM6yRjac, root4432028509, was resolved by Copilot after review of the incorporated guard. Specific coverage threadPRRT_kwDOKhokxM6ySa-k, root4432389858, is handled only for its scoped ask, separately from the remaining review/native limits.Remaining source limits are verified read-only:
Release-PSModule.Helpers.psm1:100-102returns no evidence on wrapped/unsupported terminal comments;cleanup.ps1:83,97-107selects tag names then deletes without fresh release/tag mutation checks. General helper/controller/test writes remain held with the safety owner. No parallel fix, inferred cleanup authorization, draft production pin, or lifecycle framework is introduced.Main's effective rules were read without a required-status-check rule. The coordinator owns the repository-only enforcement proposal and approval; documentation does not create enforcement.
Test actionsand DocsLint/Buildare path-filtered; universalLint code baseexcludes docs-owned paths, so unconditional enforcement needs an applicability/coverage decision. Keep the coordinated preflight → Gallery recovery → bounded recovery composition and #531-before-#524 integration order; no unmerged change is described as delivered.Related references
Release decisions
release:patch. Released Release-GHRepository v2.0.3 still uses retained legacyPatch/Fixmappings that agree on patch; owned-label caller/check adoption is a separate prerequisite.release:patch. Non-owned compatibility labels are retained. The PR stays draft while terminal-provenance/cleanup-mutation limits, full-summary assessment, Resume source-bound Gallery-only publication on retry #513/Validate source-bound ownership before module publication #547/package-coordinate prerequisites, enforcement, or production requirements remain open.