Skip to content

Module releases use configurable defaults and owned labels - #524

Open
Marius Storhaug (MariusStorhaug) wants to merge 26 commits into
mainfrom
namespaced-release-labels
Open

Marius Storhaug (MariusStorhaug) wants to merge 26 commits into
mainfrom
namespaced-release-labels

Conversation

@MariusStorhaug

@MariusStorhaug Marius Storhaug (MariusStorhaug) commented Aug 28, 2026 •

Copy link
Copy Markdown
Member

Consumers selecting the next compatible major replace Publish.Module.AutoPatching with DefaultBump and adopt the owned release-label defaults or preserve intentional custom mappings. An explicit configured bump label overrides the effective default; a valid default is sufficient without a bump label. This producer candidate is unmerged and remains blocked by a late module-Skip/prerelease decision finding and the shared publication-safety prerequisites.

Breaking: Release defaults are explicit and caller-controlled through settings

Publish.Module.AutoPatching is removed and rejected, including when DefaultBump is also present. Publish.Module.DefaultBump accepts exactly patch, minor, or major; omission inherits the shared patch default. It applies to normal and direct default-branch releases. Null, empty, invalid, or unknown publication settings fail instead of silently falling back or being masked by a label.

Default mappings are release:major, release:minor, release:patch, release:prerelease, and release:skip; prerelease is one word. All five settings remain supported and consumer-configurable: MajorLabels, MinorLabels, PatchLabels, PrereleaseLabels, and IgnoreLabels. Intentional mappings, including legacy/custom vocabularies, remain authoritative. Labels outside those configured mappings do not supply release intent.

The existing settings-file/SettingsPath surface is preserved. No scalar invocation-level DefaultBump workflow input is declared or approved by this PR. Select a settings file with the intended details; do not infer an invocation override interface from the proposed cross-repository contract. The upstream action-specific choice of typed CallerOverrides does not extend this framework's approved surface.

Adopt the released compatible major as one coordinated change:

  1. If settings contain AutoPatching: true, remove that key and use DefaultBump: patch, another deliberately chosen supported level, or the omitted-key patch default. Do not supply both keys.
  2. If settings contain AutoPatching: false, remove it and choose the effective default explicitly. There is no boolean equivalent that disables defaults. Use the configured skip label for changes that must not release, or Publish.Module.Skip: true to disable repository-wide module publication while retaining validation. Do not treat an invalid default as a no-release policy. The repository-Skip/prerelease edge must be corrected before this draft becomes an adoptable release.
  3. When adopting the canonical mappings, provision and apply release:patch, release:minor, release:major, release:prerelease, and release:skip. Retain intentional custom mapping settings where applicable. No label deletion, historical relabeling, or fleet migration is required here.
  4. Prerelease intent uses one explicit bump or the effective default. Skip is valid only without configured bump/prerelease intent. Ensure the caller's existing PR event subscription includes unlabeled so removing an override recomputes the effective default and removing prerelease mode stops publication.
  5. Apply these edits together with selection of the published next-compatible-major framework reference. Do not send the new key to the current v8 line, move v8 across this boundary, or use an unmerged producer branch/SHA as a production dependency. No intermediate installation is required by this change.
  6. Validate the selected settings and preview the explicit/default bump, custom mappings, direct-release use, skip, and prerelease transitions through the existing pipeline before publication. Consumers already using the released settings contract and intentional mappings need no additional edit beyond selecting the compatible release.
Publish:
  Module:
    DefaultBump: minor

This repository setting makes minor the effective level when no configured bump label exists. A configured patch or major label overrides it. Publish.Module.DefaultBumpSource is derived runtime evidence, not an authorable input.

Technical details

The immutable composed candidate is 0fb4234056b3bd4574c58cd4edd6dff2544d70f6. Its separately scoped settings delta is compared with frozen recovery head d06a8775f5e37d14fc9e641ef364cb42ada260b0; comparison main is 64ffb1d87f86bd5d487891fdb140b78385a00531. Existing branches and original/user commits are preserved. The default PR target remains main; recovery is the prerequisite integration layer, not a claim that its unmerged changes are delivered.

Resolve-PSModulePublishSetting owns effective defaults, all five configurable mappings, unknown-key/removed-key rejection, and shared-versus-settings provenance. The schema rejects AutoPatching and unknown publication properties while explicitly allowing derived runtime resolution fields. Get-PublishConfiguration rejects mixed legacy input and retains mappings; the release decision records label/default source rather than inventing patch recovery.

Frozen-head baseline evidence: 176 full action tests pass with actual shuffled parallel suite execution locally; the real hosted 176-test suite, Lint code base, Docs Lint, and Docs Build succeed at this exact head. Eighteen uncovered contract cases fail before correction and pass afterward; two module-Skip behavior cases and the actual schema unknown-key case are also demonstrated. PowerShell analysis is clean. The Zensical build succeeds. Both documented full-default YAML examples validate against the actual schema after correcting the pre-existing Name: null example to omit the key; this changes guidance, not Name resolution behavior. Hosted parallel execution is not inferred from the existing discarded configuration probe. These baseline successes do not cover or close the newly reproduced Skip/prerelease creation-flag gap.

Normal workflow inputs, settings-file formats, SettingsPath, cleanup settings, version prefix, and prerelease formatting controls remain supported. No secret, permission, runtime, date strategy, or Discord change is introduced. No external template is edited or declared ready. The default/with-manifest caller fixtures retain their interfaces; later caller/template authoring work is separately coordinated and must provide compatible immutable evidence before release adoption.

Changed surface Standards checked Framework docs checked Result
Publication settings and JSON schema PowerShell, Functions, Error Handling, Testing Authorable settings and derived runtime contract Fixed in this PR
Effective default/mapping provenance PowerShell, Testing Plan and module-version authority Aligned
Target-state settings/release/reference guidance Markdown, Natural Language Current supported behavior; no release migration guide Fixed in this PR

The old PR record's retained-AutoPatching, release:pre-release, unconditional direct patch, and historic complete-validation claims were corrected from immutable code evidence. The approved replacement direction is retained. The original issue's obsolete retained-boolean wording must not be read as evidence to revert that decision.

Related references

Fixed: Preview, prerelease, and skip events use one validated decision

Open non-publishing PR previews validate the same explicit/default level and conflicts instead of being mistaken for closed-PR cleanup. Removing a bump override while prerelease mode remains uses the effective default; removing prerelease mode stops publication. A valid configured skip label stops new-version resolution. Closed-PR cleanup remains non-publishing and ignores obsolete/conflicting release labels.

Open decision blocker: Repository-wide Publish.Module.Skip disables publication-enabled state, but the resolver still leaves or re-enables CreatePrerelease in Release, Prerelease, and None modes. Review comment 4432039974 is reproduced by preserved uncommitted behavior tests. Both creation flags must remain false, including after the final non-publishing-preview branch, while retaining the configured local bump. This fix remains separately owned by #524, not absorbed into #547/#513. Overlapping resolver/helper/publisher/caller writes wait until the publication-safety contract freezes or its owner explicitly hands back the file. No implementation is changed here; the actual fix and reviewed composition are required before readiness.

No extra caller input or per-PR bump label is required for a valid default. Consumers using the preserved caller interface need only the settings/label adoption above and its existing unlabeled event subscription after the complete compatible release is available.

Technical details

Normalized event state distinguishes closed cleanup from open preview. All five mapping settings, including custom prerelease and ignore mappings, feed the same conflict validation. Actual settings-controller tests check publication-enabled state for module Skip; the late decision edge remains open in thread PRRT_kwDOKhokxM6yRlG6, root comment 4432039974, review 5723280955. Source and label precedence remain settings-driven and do not depend on PR author or an unrelated label namespace.

The bounded diagnosis is two-part: initialization clears only CreateRelease, then the final if (-not $shouldPublish) unconditionally enables CreatePrerelease. That sends Get-NextModuleVersion into prerelease-counter resolution even with repository publication disabled. Clearing both flags early alone would be incomplete. The eventual separate #524 correction must preserve normal non-publishing previews, configured bump/default validation, mappings, label conflicts, and closed cleanup without changing the safety owner's Gallery ownership algorithm or caller contract.

The separate pagination allegation is resolved as a verified false positive. Exact CI-supported GitHub module 0.43.1 already follows RelationLink.next, and PowerShell .Response enumeration consumes all returned pages. The actual settings controller rejects an already-released commit found in the second response after 100 prereleases, without emitting settings output. A second pagination implementation is not needed.

Local test-only additions in two files are preserved, not pushed. The targeted shuffled/parallel run executes 97 cases: 91 pass and six Skip regressions fail as expected. Three cover both creation flags in Release/Prerelease/None modes; three compose the decision into actual version resolution and require zero calls to the owned prerelease-counter boundary. Configured default and explicit-label local bumps remain asserted. The positive normal preview still resolves its counter to v1.3.0-feature007, and the 101-release pagination control passes. Both changed test files have zero analyzer diagnostics. This is evidence for the retained diagnosis, not a green replacement candidate or a claim that the review fix is delivered.

Changed surface Standards checked Framework docs checked Result
Event routing, open preview, and skip behavior PowerShell, Error Handling, Testing Plan/scenario contract and release decision Exception - Skip/prerelease creation remains open
Focused/helper/controller fixtures Pester, Testing Action test layout and real controller boundaries Aligned

The bounded recovery ancestor is frozen separately; its retry/footer consistency finding remains with the publication-safety owner and unresolved. This PR does not implement the systemic publication-safety contracts in #513 and #547. Their overlapping version-resolver/Gallery-publisher/caller changes remain coordinated under one owner, without taking this separate DefaultBump/Skip fix. A clean current-head review, including summary/suppressed findings, remains a readiness gate.

Related references
Release decisions
  • Release: Yes - supported module-maintainer settings and default release behavior change incompatibly; this is a versioned framework/native producer route even without a shared release-management workflow.
  • Version bump: Major is the selected release:major intent for the removed boolean and changed default mappings/direct-release behavior. The current native caller still pins released Release-GHRepository v2.0.3 at 750abed0ecab02394554b610dc3aa191e75e3248; that reader ignores the owned major label and can resolve patch. That incorrect production result is rejected as a publication prerequisite, not claimed as a verified major release. A stable released immutable compatible engine and its verified caller/check integration are required.
  • Mode: Stable - the target remains main. Final version/base coordinates, tag, immutable source, and consumer-change baseline are resolved by the release process; no numeric release is assigned here and v8 is not moved.
  • Labels: release:major. This PR stays draft until the Skip/prerelease finding, Default-branch recovery retains release intent and immutable artifacts #531/Resume source-bound Gallery-only publication on retry #513/Validate source-bound ownership before module publication #547, compatible upstream production interfaces, current-head review/checks, and enforced required release-decision validation are satisfied. Current main has no required-status-check rule; documentation does not create enforcement.

@MariusStorhaug Marius Storhaug (MariusStorhaug) changed the title 🌟 [Major]: Module release decisions fail closed 🌟 [Major]: Module releases use owned label defaults Aug 28, 2026
@github-actions

github-actions Bot commented Aug 28, 2026 •

Copy link
Copy Markdown

Super-linter summary

Language Validation result
CHECKOV Pass ✅
CSS Pass ✅
CSS_PRETTIER Pass ✅
GITHUB_ACTIONS Pass ✅
GITHUB_ACTIONS_ZIZMOR Pass ✅
GITLEAKS Pass ✅
GIT_MERGE_CONFLICT_MARKERS Pass ✅
HTML Pass ✅
JAVASCRIPT_ES Pass ✅
JAVASCRIPT_PRETTIER Pass ✅
MARKDOWN Pass ✅
NATURAL_LANGUAGE Pass ✅
POWERSHELL Pass ✅
PRE_COMMIT Pass ✅
SPELL_CODESPELL Pass ✅
TRIVY Pass ✅
YAML Pass ✅

All files and directories linted successfully

For more information, see the GitHub Actions workflow run

Powered by Super-linter

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates Process-PSModule’s default release-intent label contract to use an owned release: namespace (and documents that contract), so downstream release/version decisions default to repository-owned labels instead of potentially colliding dependency metadata.

Changes:

  • Switch default publish/version label mappings to release:major|minor|patch|pre-release|skip (while preserving consumer overrides via .github/PSModule.yml).
  • Centralize publish-default resolution in Resolve-PSModulePublishSetting, and publish the same defaults in the settings JSON schema.
  • Update docs and Pester coverage to reflect and validate the new canonical defaults and override behavior.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated no comments.

Show a summary per file
File Description
docs/content/specification/spec.md Updates the FR5 contract and Gherkin scenarios to use release:* default labels.
docs/content/specification/principles-and-practices.md Updates guidance for prerelease flows using the configured prerelease label (default release:pre-release).
docs/content/specification/design.md Aligns design text with the new canonical default label set and override location.
docs/content/reference/settings.md Updates documented settings defaults to the release:* namespace and adds prerelease defaults.
docs/content/reference/scenario-matrix.md Updates prerelease requirements text to reference the configured prerelease label and resolved bump.
docs/content/reference/repository-standard.md Updates repository expectations to the new default label namespace and override guidance.
docs/content/reference/powershell-module-standard.md Updates label tables/examples and prerelease behavior documentation to release:* defaults.
docs/content/guides/versioning-and-releases.md Updates the versioning guide to the new label namespace and clarifies conflict-handling behavior.
docs/content/get-started/your-first-release.md Updates “first release” walkthrough tables/text to the new default labels and conflict semantics.
.github/workflows/workflow.yml Adjusts workflow commentary to describe prerelease conditions in terms of intent + resolved bump.
.github/actions/Resolve-PSModuleVersion/tests/Resolve-PSModuleVersion.Helpers.Tests.ps1 Updates version-resolution tests to use release:* defaults and adds coverage for canonical/overridden mappings.
.github/actions/Get-PSModuleSettings/tests/Get-PSModuleSettings.Helpers.Tests.ps1 Adds tests asserting canonical defaults, consumer override preservation, and schema defaults parity.
.github/actions/Get-PSModuleSettings/src/Settings.schema.json Publishes schema defaults for AutoPatching and the label mapping settings.
.github/actions/Get-PSModuleSettings/src/main.ps1 Uses the new publish-settings resolver when constructing normalized settings output.
.github/actions/Get-PSModuleSettings/src/Get-PSModuleSettings.Helpers.psm1 Introduces Resolve-PSModulePublishSetting to own and centralize canonical defaults.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Marius Storhaug (MariusStorhaug) added a commit to MSXOrg/docs that referenced this pull request Aug 29, 2026
Release guidance now defines one owned `release:` label set:
`release:patch`, `release:minor`, `release:major`,
`release:pre-release`, and `release:skip`. Release automation ignores
bare and unrelated labels, so only explicit release decisions affect
published versions.

## Changed: One release label contract

Release Management, Automation Labels, PR Format, Natural Language
examples, and the VS Code Extension Framework now use the same
namespaced values. Prereleases use `release:pre-release` with one bump
label, while non-releasing changes use `release:skip` alone.

## Changed: Ad hoc releases are optional

A labeled pull request merge is the required release path.
Implementations may add `workflow_dispatch` only when they need an
explicit ad hoc mechanism; it must use the same release controls and
require its decision and release-note context as inputs. Empty pull
requests and direct pushes are not release workarounds.

---
<details>
<summary>Technical details</summary>

- Replaced `release:none` and the unnamespaced `Prerelease` label.
- Defined valid and invalid combinations for the five owned release
labels.
- Made `workflow_dispatch` an optional implementation extension rather
than a mandatory release interface.
- Preserved the mainline removal of dependency-tool label guidance while
resolving the branch update.

| Changed surface | Standards checked | Framework docs checked | Result
|
| --- | --- | --- | --- |
| `src/docs/Capabilities/release-management/**` | Natural Language,
Markdown | Release Management | Aligned |
| Release-label references under `src/docs/**` | Natural Language,
Markdown | Automation Labels, PR Format, VS Code Extension Framework |
Aligned |

</details>

<details>
<summary>Relevant issues (or links)</summary>

### Related work

- References PSModule/Release-GHRepository#109
- References PSModule/Process-PSModule#524

</details>

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
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>
@MariusStorhaug Marius Storhaug (MariusStorhaug) changed the title 🌟 [Major]: Module releases use owned label defaults 🌟 [Major]: Module releases use configurable defaults and owned labels Oct 31, 2026
@MariusStorhaug Marius Storhaug (MariusStorhaug) changed the title 🌟 [Major]: Module releases use configurable defaults and owned labels Module releases use configurable defaults and owned labels Oct 31, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Two active issues remain: release lookup is limited to the first 100 releases, and skip mode leaves prerelease creation enabled, allowing contradictory version-resolution behavior.

2 open issues

Review effort: Lite

Comment on lines +314 to +317
$shouldPublish = ($createRelease -or $createPrerelease) -and $Configuration.Skip -ne $true
if ($Configuration.Skip -eq $true) {
$createRelease = $false
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed. A new behavior test with Skip = true and ReleaseType = Prerelease fails because CreatePrerelease remains true while ShouldPublish is false. The fix must also prevent the final non-publishing-preview branch from re-enabling creation, while retaining the configured local bump. I preserved the failing test and transferred it under the coordinated resolver ownership; no shared implementation has been changed. This thread and the draft/readiness blocker remain open.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fix stays separately scoped to #524; it is not part of #547/#513. I retain its diagnosis/tests/record, while overlapping resolver/publisher/caller writes wait for the publication-safety contract to freeze or the file to be handed back.

The expanded tests now reproduce both failures in Release, Prerelease, and None modes: three creation-flag assertions fail, and three composed version-resolution tests observe a prerelease-counter call despite repository Skip. A positive non-publishing preview still resolves its counter correctly. Targeted run: 91 passed, 6 expected failures. The root cause includes the final unconditional non-publishing-preview branch, so clearing flags only at initialization would be incomplete. No implementation or fix is pushed, and this thread remains open.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release:major Publish a major release.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Default module release decisions to namespaced labels

2 participants