Repository navigation
Release decisions use owned labels and effective settings - #109
Marius Storhaug (MariusStorhaug) wants to merge 27 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces a strict, “fail-closed” release-decision model based on a canonical, action-owned release: label set, removing legacy/bare label influence and eliminating default/automatic patching behavior.
Changes:
- Adds a PowerShell helper module to define canonical release labels and to resolve/validate release decisions from PR labels.
- Updates the main action logic to (a) provision canonical labels each run and (b) drive release/prerelease/skip decisions exclusively via the resolver.
- Updates documentation, action inputs, and workflows to reflect the new owned-label contract and required events/permissions; adds unit tests for the resolver.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
tests/Release-GHRepository.Helpers.Tests.ps1 |
Adds Pester coverage for canonical label definitions and release-decision resolution/rejection rules. |
src/Release-GHRepository.Helpers.psm1 |
Introduces canonical label definitions and the strict Resolve-ReleaseDecision validator. |
src/main.ps1 |
Provisions canonical labels and replaces legacy label/auto-patching logic with the resolver output. |
README.md |
Documents the owned-label contract, workflow requirements, and v2→v3 migration steps. |
action.yml |
Removes legacy label/auto-patching inputs and clarifies Prerelease input semantics. |
.github/workflows/Release.yml |
Ensures label transitions are evaluated (unlabeled) and grants issues: write for label provisioning. |
.github/workflows/Action-Test.yml |
Adds Pester unit tests and expands PR event types to include unlabeled. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
src/main.ps1:154
$createPrereleasecan become true for merged/closed pull requests when the PR targets a non-default branch (because$closedPullRequestonly covers closed-but-not-merged). That would create prereleases from closed PRs, conflicting with the intended “open pull request prerelease” behavior.
$createPrerelease = $releaseDecision.Prerelease -and -not $createRelease -and -not $closedPullRequest
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
.github/workflows/Release.yml:19
pull_request_targetsetsgithub.refto the base/default branch (e.g.refs/heads/main), so using${{ github.workflow }}-${{ github.ref }}collapses all PR runs into the same concurrency group. Withcancel-in-progress: true, activity on one PR can cancel an in-progress run for a different PR, which can interrupt release/prerelease creation or cleanup. Use a PR-scoped key (e.g. PR number) to isolate runs per PR (matching the README guidance).
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
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>
There was a problem hiding this comment.
🟡 Changes recommended
The prerelease-cleanup selection in src/main.ps1 can match and delete non-prerelease (stable) releases because it uses a broad substring tag filter without restricting to isPrerelease.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
- Files reviewed: 7/7 changed files
- Comments generated: 1
- Review effort level: Lite
There was a problem hiding this comment.
🟡 Changes recommended
Approval is blocked by two critical prerelease-cleanup matching bugs that can delete the wrong tags and a moderate skip-path issue that can fail validation unnecessarily.
3 open issues
1 resolved since last review
Review effort: Lite
There was a problem hiding this comment.
🔵 Needs a closer look
Human assessment is needed because critical hidden findings indicate the stable-release workflow may fail during authenticated tag pushes despite successfully creating the GitHub Release.
No open issues 🎉
3 resolved since last review
Review effort: Lite
|
Assessed the latest review summary's authenticated-tag-push concern against the actual default bootstrap. The read-only checkout does not leave Git unauthenticated in this path: GitHub-Script v1.9.0 calls Connect-GitHub, and GitHub 0.43.1 initializes the workflow installation context, then configures authenticated Git URL rewrites before the script runs. The actual final-head action job reports GitHub 0.43.1. Two anonymous bootstrap checks pass: they exercise the real context/Git-config functions with API, vault, CLI-login and Git-write boundaries mocked, then use real No code change is needed to enable persisted checkout credentials merely to silence this summary concern. The three reported resolver/cleanup/skip issues are fixed and resolved, and all final-head CI is green. The summary assessment is documented rather than called an automatic approval; the PR remains draft with its real decision-enforcement prerequisite still open. |
There was a problem hiding this comment.
🔵 Needs a closer look
Automated review should defer because the privileged workflow’s authenticated label, release, tag, and push operations plus GitHub event and checkout semantics cannot be validated end to end.
No open issues 🎉
Review effort: Lite
Solution-owned settings use the conventional filename `<name>.settings.yml`. The release solution uses `.github/release.settings.yml`; module repositories retain `.github/PSModule.yml` through `SettingsPath`, including module release settings. The documentation-content test file and CI documentation-index drift gate are removed. Functional tooling tests, linting, link validation, and site builds remain; no module migration or runtime loader is implemented here. <!-- ANNOUNCEMENT STOP --> ## Removed: Tests that lock documentation content `tests/PR-Format.Tests.ps1` is deleted in full at the user's request, including its PR-format, filename, naming, and repository-policy assertions. No replacement tests of checked-in documentation or workflow content are added. The Naming standard no longer claims test coverage for its prose. The follow-up audit covers all six remaining suites and both workflows. The remaining suites exercise scripts on temporary fixtures, PowerShell engine behavior, and plugin metadata/schema validity. They do not lock the actual documentation's wording or assert the actual workflows' contents. The user explicitly chose to retain these functional tool tests, together with linting, link validation, and site builds. <details> <summary>Technical details</summary> The entire 329-line documentation suite is absent, including all 39 assertions it contained. Historical audit comments and earlier test totals describe preceding iterations, not tests present in this candidate. No replacement prose or workflow-content tests were introduced. The complete scoped comparison is accepted main `aa9b5cecc69f4cbe6aa04a5dd70ff9cdadeeac3d` to candidate `8daf026a14036dee04786d371883e8871b5ec2f4`. The [latest bounded change](3d7c58e...8daf026) removes drift enforcement without changing any test suite or index-generator logic. | Changed surface | Standards checked | Framework or domain docs checked | Result | | --- | --- | --- | --- | | `tests/PR-Format.Tests.ps1` (deleted) | User-directed removal and test discovery | Existing Pester suite discovery | Aligned | | Naming enforcement statement | Naming, Natural Language, Markdown | None (no framework-specific docs) | Aligned | All 64 tests in the six retained functional suites pass on the current head, verified from the completed CI job. The six index-tool fixture cases also pass locally; these exercise optional diagnostics, regeneration, and line endings on temporary files, not drift in this repository's actual docs. No suite is rewritten to inspect the checked-in documentation or workflows. The [fresh exact-head review](#233 (review)) approves `8daf026a14036dee04786d371883e8871b5ec2f4` with zero new inline comments. All five required checks pass: [Lint](https://github.com/MSXOrg/docs/actions/runs/41497449037/job/125456000472), [Build](https://github.com/MSXOrg/docs/actions/runs/41497449037/job/125456000462), [Links](https://github.com/MSXOrg/docs/actions/runs/41497449037/job/125456000312), [Test](https://github.com/MSXOrg/docs/actions/runs/41497449037/job/125455999512), and [Cross-repository links](https://github.com/MSXOrg/docs/actions/runs/41497448823/job/125455993357). The earlier consistency thread remains resolved. Publishing is intentionally skipped for this PR. </details> <details> <summary>Related references</summary> - Resolves #232 </details> ## New: Solution-owned settings filenames identify their owner Use the owning solution's name for its conventional settings filename. The Naming standard defines this once; repository, YAML, and release guidance link to it. The rule does not rename tool-mandated manifests, lockfiles, workflow filenames, or arbitrary YAML files, and it does not impose one directory on every solution. Supported explicit custom paths remain governed by each reader's existing input contract. Module repositories keep `.github/PSModule.yml` through `SettingsPath`, including module release settings. The PSModule initiative records this supported exception and links to the framework's actual input and settings references. No module filename migration, second release settings file, or caller-input change is required here. The VS Code framework design retains `.github/vscode-extension.yml` as an explicit supported naming exception. Its settings keys and interface are unchanged; a filename change requires a verified reader and separate template/caller migration. <details> <summary>Technical details</summary> | Changed surface | Standards checked | Framework or domain docs checked | Result | | --- | --- | --- | --- | | `src/docs/Coding-Standards/Naming.md` | Naming, Natural Language, Markdown, standard template | None (no framework-specific docs) | Aligned | | `src/docs/Coding-Standards/YAML.md` | YAML, Naming, Markdown | None (no framework-specific docs) | Aligned | | `src/docs/Ways-of-Working/Repository-Standard.md` | Repository Standard, Naming, Markdown | Repository Governance required-files model | Aligned | | `src/docs/Initiatives/PSModule.md` | Documentation Model, Natural Language, Markdown | Process-PSModule workflow inputs and settings | Aligned | `Naming.md#solution-settings-files` owns the rule; `PSModule.md#module-settings` and the VS Code configuration surface own the supported exceptions. Related guidance links to those owners rather than defining another rule. The directly related obsolete framework overview link is corrected to its actual canonical site route. The module default was verified from Process-PSModule source `105e4dcefe1946782066aa50a5c7d3658319895a` and the [published workflow-input reference](https://psmodule.io/Process-PSModule/reference/workflow-inputs/). The [settings reference](https://psmodule.io/Process-PSModule/reference/settings/) owns module keys and defaults. Neither the workflow, its input, schema, nor enriched runtime settings object changes here. The earlier VS Code consistency finding remains addressed by its owning-guide exception, independently of the deleted assertion. The scoped issue-convergence search finds no additional complete ask satisfied by this naming slice; broader default-bump/keyed-route and lifecycle work stays separate. </details> ## Changed: Release settings use the release solution's canonical filename The optional release-solution file is `.github/release.settings.yml`, replacing the documented `release.config.yml` convention. Its `.github` location, settings keys, schema, defaults, precedence, omission behavior, applicability, and required decision validation are unchanged. All 17 original current-guidance substitutions remain. This repository has no settings file or runtime loader to rename. The former `.github/auto-release.yml` is migration evidence for the separately owned Release-GHRepository reader change, not a current alternative convention. `ConfigurationFile` remains the public input, distinct from its conventional default filename. This documentation PR does not deliver or release that reader. Consumers verify their producer revision and its migration record before adopting a changed default; module release settings remain under the supported `PSModule.yml` interface. <details> <summary>Technical details</summary> | Changed surface | Standards checked | Framework or domain docs checked | Result | | --- | --- | --- | --- | | Release Management spec and design | Documentation Model, Naming, Markdown | Applicability, defaults, overrides, and decision validation | Aligned | | VS Code framework design | Documentation Model, Naming, Markdown | Existing extension interface and release configuration | Aligned | | Automation Labels and PR Format | Natural Language, Markdown, owning standards | Release-route applicability and complete-record ownership | Aligned | The accepted release-range-first analysis, complete description example with one summary boundary, conditional release/default rules, Task/Bug planning, and repository-owned no-PR-template policy are preserved without tests of their prose. Runtime default/migration work belongs to PSModule/Release-GHRepository#109, not this source. No module file, loader, public input, Build/metadata/runtime schema, publisher, pin, permission, ruleset, marketplace, or consumer fleet change is included. </details> <details> <summary>Related references</summary> - References PSModule/Release-GHRepository#109 - References #196 - References #208 - References #209 </details> ## Changed: Documentation builds regenerate indexes without a drift gate CI generates documentation indexes before building the site instead of rejecting an out-of-date generated table. A documentation edit no longer needs to satisfy an index-drift gate. The generator updates only the build checkout; this change adds no bot commit or source synchronization. Optional local `-Check` diagnostics and functional tests of the generator remain available. Linting, link validation, and site builds still run. The contribution guide and script help describe this distinction; no tests inspect the actual workflow to enforce its contents. <details> <summary>Technical details</summary> | Changed surface | Standards checked | Framework or domain docs checked | Result | | --- | --- | --- | --- | | `.github/workflows/Docs.yml` | GitHub Actions, YAML | Existing documentation build pipeline | Aligned | | `.github/scripts/Update-DocumentationIndex.ps1` (help only) | PowerShell, Natural Language | Existing index generator interface | Aligned | | `.github/CONTRIBUTING.md` | Markdown, contribution guidance | Documentation authoring and build flow | Aligned | The index step runs normal generation with no `-Check` flag. The index-generator implementation and all functional test suites are unchanged. The local generation-then-build path succeeds with repository-pinned Zensical 0.0.59; the changed contribution guidance is lint-clean and the scoped diff has no whitespace errors. The exact-head CI Build job also successfully executes `Generate documentation indexes` followed by the site build. Temporary build environments and output are cleaned without changing shared dependencies. The Task records the audit, the user's selected boundary, and the completed verification. Its implementation and review gates are complete; the Task remains open for reviewed integration. This PR remains draft; native maintenance has `merge_pr=false`, GitHub auto-merge is off, and no live publication or merge is authorized. A later main change requires a refreshed comparison and exact-head validation. </details>


Repository and workflow maintainers must migrate conventional settings to
.github\release.settings.ymland replace legacy release labels andAutoPatchingwhen selecting this release. Owned labels override a validatedDefaultBump, whose documented default remainspatch; explicitCallerOverridesselect invocation-specific settings without GitHub-injected defaults masking repository settings.The caller migration and old-publisher bootstrap requirements are included below. This is a breaking engine update, not the later push-authoritative publisher delivery, and its draft source is not a production dependency.
Breaking: Owned release controls replace legacy labels and automatic patching
AutoPatching,IgnoreLabels,MajorLabels,MinorLabels, andPatchLabelsare removed from the action interface. Repository configuration containing those keys now fails instead of silently losing its intent.DefaultBumpaccepts exactly lowercasepatch,minor, ormajor; a valid inherited patch default is policy, not recovery from invalid input.Only the five labels below select release behavior. Bare labels, dependency-version labels, unknown namespaces, noncanonical casing, and the retired
release:pre-releasespelling do not select a bump. Without an owned bump or skip, the effective default applies. Multiple bump labels, orrelease:skipcombined with another owned release label, fail.release:patchrelease:minorrelease:majorrelease:prereleaserelease:skipExisting v2 references are unchanged. Apply this release-wide adoption path to callers using v2:
release:majorfor the new reader. Under the v2 defaults this ismajorplusrelease:major. A skipped transition similarly needs the oldNoReleasesignal plusrelease:skip. These are temporary signals on the active migration PR, not a historical relabeling campaign.AutoPatching: truewithDefaultBump: patch, or omitDefaultBumpto inherit patch. Chooseminorormajoronly when that is the intended default. There is nononeor date bump. WhereAutoPatching: falsepreviously suppressed unlabeled publication, applyrelease:skipto the affected active PR instead. Remove the four label-list keys and translate their active decisions to the owned set.issues: writealongside the existing release/comment permissions. Subscribe the release workflow toopened,reopened,synchronize,labeled,unlabeled, andclosedfor its release target, without workflow path filters that bypass decision validation. A privilegedpull_request_targetwriter must check out trusted base code, never an untrusted PR head. Validate candidate code in a separate read-only PR workflow. Queue publication without cancellation; serialize merged releases by target branch while isolating open-PR prereleases by PR number.CallerOverridessettingWhatIf: true. Confirm that inherited/default, explicit bump, prerelease, skip, conflicting-label, and invalid-setting cases produce the expected decision and source. KeepUsePRBodyAsReleaseNotesandUsePRTitleAsNotesHeadingtrue to preserve the complete authored title/body record; their existing opt-out settings remain supported in this bounded resolver delivery.Stable publication remains PR-state-driven in this delivery. Do not add push/manual stable-publication triggers or relabel historical merged PRs expecting validation-only behavior. Exact pushed-source authority, recovery/manual contexts, publication provenance, and controlled alias advancement are separate work in #108.
Technical details
The consumer-change baseline is the released
v2.0.3source750abed0ecab02394554b610dc3aa191e75e3248. The development candidate is03e20b8293dd8dfb41bead3255930a5edbb2e9bb; it is evidence for this change, not an authorized released dependency. The actual publication version, source, version base, and consumer-change baseline are resolved by the release process, not predicted here.The existing resolver coverage is retained, including all 32 owned-label subsets across all three defaults. The repository suite now has 167 passing cases. Eleven anonymous bootstrap experiments execute the immutable v2.0.3 controller and the candidate with real YAML/SemVer dependencies and write-denying CLI mocks: owned-major-only resolves patch under the old defaults; dual major resolves major under both readers; old skip needs
NoRelease, while the new reader honorsrelease:skip. The three filename cases prove that renaming only an old caller's file can discard its major policy; explicit compatible old-reader wiring preserves it. No release, tag, or production file is changed by those experiments.The repository's own post-merge writer checks out the trusted default branch and uses its local action. This makes the merged owned-label reader available for the producer's breaking decision. A separately pinned framework caller remains on its old reader until an authorized immutable engine release is adopted; the new label alone does not bootstrap that caller.
The integration template baseline inspected is
PSModule/Template-Action@634ca503a47a39ca26d72fa59c784da8118ae835. ItsAuto-Releaseworkflow still selects the old reader, lacks the new label permission/event contract, and is not a verified unchanged template for this release. A separate template/caller delivery is required; no compatible updated template commit is claimed here. The exact caller changes are specified above rather than left for consumers to infer from that template.The hosted review at
89b7766identified two cleanup-matching defects and unnecessary version parsing on skip; all three were reproduced with failing tests, fixed inb8767c4, and replied to/resolved. The subsequent user-directed settings-filename revision is verified at03e20b8: all 167 repository cases, eleven old-reader controls, two unchanged anonymous authentication checks, and exact-head hosted CI pass.The complete current-head review reports no open issues. Its summary defers end-to-end assessment of authenticated label/release/tag/push operations and GitHub event/checkout semantics; it is not an automated approval or evidence of live publication. No unauthorized publication or gate weakening is performed to manufacture that evidence.
The prior review at
b8767c4reports no open issues, but its complete summary asks for closer assessment of authenticated tag pushes. The default-bootstrap concern was evaluated against the actual GitHub 0.43.1 dependency in CI: account/context initialization calls Git authentication configuration before publication. Two passing anonymous checks exercise that real path with API/vault/writes mocked and prove native Git URL expansion without contacting a remote. The assessment is recorded with immutable dependency sources, not called an automatic approval or used to weaken checkout security.The PR stays draft because its native delivery issue is blocked by #112; main has no required-status-check rule, and that enforcement was not bypassed.
The scoped issue-convergence sweep checked the release-related open issues. This PR delivers #111. It does not deliver push authority in #108 or #61, the remaining runner work in #105, or governance enforcement in #112; those remain separate.
Related references
Breaking: Release settings use the canonical filename
ConfigurationFilenow defaults to.github\release.settings.yml, replacing.github\auto-release.yml. This is an actual reader change, not only a documentation rename. The input name, its custom-path capability, settings keys, scalar/file/typed-override precedence, and the patch default remain unchanged. ModulePSModule.ymland its distinctSettingsPathinterface are not migrated by this action release.For consumers using the former conventional file, make the following changes in the same reviewed caller adoption as the compatible release-engine reference:
.github\auto-release.ymlto.github\release.settings.ymland retain its intended valid settings. Apply the removed-key/owned-label migration from the preceding section in that same caller change. Do not rename only the file while an older production reader still relies on its old default; it would miss the configured policy.ConfigurationFile. If the caller explicitly supplied the old conventional path, remove that input to inherit the new default or change its value to.github\release.settings.yml. Other intentional custom paths remain supported through this input; no second conventional path or legacy alias is added.CallerOverridessettingWhatIf: true. Confirm that the new file is reported as read, the expected default/owned bump and its source are visible, and no GitHub write occurs. A legacy-only file or an explicitly selected old conventional path must produce a rename/compatible-reference diagnostic before any GitHub operation.When no conventional settings file exists, no file creation is required: valid documented defaults and existing caller inputs still apply. A consumer using a valid unrelated custom path has no filename edit beyond selecting the compatible released engine. Reading release records does not require installing every intervening version; this filename and reader must be adopted together, and no draft source is a production dependency.
The
.github\release.config.ymlname appears in earlier canonical guidance, but the releasedv2.0.3action does not automatically read it. A caller that deliberately selected that name throughConfigurationFileis using custom-path control, not a discovered alias. Inspect and preserve that explicit wiring or change it deliberately with the compatible reader; there is no inferred migration of a runtime loader that this action never had.Technical details
The filename result shares the released
v2.0.3source baseline and exact candidate identified above. The standalone settings revision isb8767c42b5140ea66e865cbd0142cd2f7c2cbde7to03e20b8293dd8dfb41bead3255930a5edbb2e9bb, kept separate from the full released-source comparison. Two ordinary commits separate the tested actual-reader change from its target-state documentation.Seventeen cases exercise the declared default and env forwarding, default-file loading without an injected
ConfigurationFile, valid absence, legacy-only/conflicting files, relative/normalized/absolute old selections, deliberate custom control, missing custom with legacy data, scalar/file/CallerOverrides/owned-label precedence, invalid new data and WhatIf no mutation. Sixteen fail against the prior reader before implementation; the existing custom-path case already passes. All 167 repository cases and eleven old-reader bootstrap experiments pass after the change.The default remains declared only in
action.yml. The controller resolves caller paths using PowerShell's provider-aware path resolver and checks the removed conventional path solely to reject it; it never reads it as fallback. No resolver helper export, settings key, input name, modulePSModule.yml, orPSMODULE_AUTO_RELEASE_INPUT_*environment namespace changes.Canonical correspondence is verified against MSXOrg/docs#233 at immutable candidate
734145479ede01a7ccdeb4eb29950d405ed99a09. The Naming standard owns<name>.settings.ymlonce, preserves documented explicit custom-path control, and requires reader-verified migration. This action declares and tests the corresponding.github\release.settings.ymldefault without changing its input or schema.The module-settings exception retains
.github/PSModule.ymlthroughSettingsPathand does not require an extra module release-settings file. Those distinct contracts are unchanged here. The canonical amendment is still a draft documentation candidate, not shipped runtime support or a production dependency.ConfigurationFiledefault, controller migration boundary and caller fixturesThe updated interface/head is shared with the Project coordinator and linked in the existing PSModule/Release-GHRepository#108 handoff. No distinct publication owner or working-copy incorporation is verified. No push-authority rewrite, production caller pin, module-settings migration, package/tag/release publication, or live governance change occurs here. The native #112 prerequisite and maintenance-only
merge_pr=falselimit remain.Related references
New: Explicit caller overrides preserve repository defaults and invocation intent
CallerOverridesis a string input containing a YAML or JSON mapping of explicit release-setting overrides. It is the supported invocation-over-repository channel. GitHub injects scalar action defaults even when a caller omits them, so individual scalar inputs retain their existing lower-than-file precedence instead of pretending to reveal whether the user explicitly supplied a default value.Effective settings resolve as shared defaults declared in
action.yml, scalar base inputs, repository settings from.github\release.settings.yml(or an intentionalConfigurationFilecustom path), then explicitCallerOverrides. An omitted{}mapping inherits repository settings. An owned bump label still overrides a valid effectiveDefaultBump. The action reports the effective setting/bump source.For a caller that must select minor while its repository normally selects major, use a block scalar or a JSON string, not a YAML object directly under
with:. Existing callers that need no invocation override can omit this input.Explicit false and empty supported text values are preserved. Booleans accept YAML Boolean values or case-insensitive strings containing exactly
trueorfalse; numeric and arbitrary truthy values are rejected. OnlyVersionPrefixand the existingDatePrereleaseFormataccept empty strings. Null, unknown, removed, or malformed values fail in every supplied scope even when a narrower scope or an owned label supplies a valid value. Remove the invalid lower-priority value rather than trying to mask it with an override.DatePrereleaseFormatremains a prerelease-suffix formatter, not date versioning.The file and override mapping accept the runtime release-setting names, excluding
CallerOverridesandConfigurationFilethemselves.Debug,Verbose,Version,Prerelease, andWorkingDirectoryremain separate dependency/runtime inputs. In particular,Prereleaseselects a prerelease GitHub module dependency; repository prerelease mode uses the owned label.Technical details
This result uses the same released v2.0.3/source baseline and development candidate identified in the breaking section. The typed override channel was selected explicitly for this delivery; it introduces no new orchestration framework or second bump algorithm.
The settings resolver validates each layer before applying it and returns the effective
DefaultBumpsource. The decision resolver retainsBump,Prerelease,Skip, andDefaultBumpApplied, addingBumpSource. Real-controller tests verify YAML and JSON overrides, inherited repository values despite injected scalar defaults, false/empty values, explicit-label precedence, source reporting, unmasked invalid inputs, and forced read-only validation over a validWhatIf: falsefile setting. All write commands are denied in these tests.CallerOverrides, configuration parsing and decision provenanceNo consumer edit is needed for the unchanged supported scalar settings/defaults when no invocation-specific override is required. A template using the old reader cannot yet consume this new input; its required release-reference/permission/event migration is covered in the breaking section.
Related references
Fixed: Prerelease publication and cleanup use validated source context
Open-PR prereleases target the exact validated 40-character head commit, not a potentially missing or colliding base-repository branch name. The normalized branch name still names the prerelease. A branch without an ASCII prerelease identifier fails only when prerelease mode requires it; valid stable/skipped contexts do not fail because an unused prerelease name is empty.
Cleanup locates the first numeric version core and compares its following prerelease identifier case-sensitively. Only the exact escaped identifier ending the tag or followed by a dot is eligible; later embedded hyphens and later version-like segments cannot select a candidate. Stable releases, invalid/non-version cores, longer identifiers, and regular-expression lookalikes are excluded. Empty and hyphenated version prefixes retain cleanup support. Closed skipped PRs still receive configured cleanup without parsing the latest version, even when that unrelated latest tag is malformed; stable GitHub Releases are never cleanup candidates.
Publication runs queue without cancellation. Merged-PR publication shares a target-branch concurrency key; open-PR prerelease runs remain isolated by PR number. This fixes the race introduced by making every publication PR-specific without bundling the later push-authority publisher.
Select this authorized release to obtain these fixes; no naming, note, or cleanup setting changes are required beyond the caller migration above.
WhatIfpreviews operations without executing label, release, tag, or comment writes.Technical details
The baseline and candidate are the same as the preceding results. Cases cover fork-style/colliding head refs, missing/mutable/malformed SHAs, exact cleanup boundaries, numeric stable versions, regex escaping, open/closed prerelease gating, a Git-validated non-ASCII branch in a skipped context, and the actual publishing workflow's no-cancellation/branch-serialization settings. PowerShell analysis, actionlint, Markdown lint, and the repository tests pass locally; final hosted CI/review is evaluated separately.
Branch-derived prerelease naming is intentionally retained. PR-unique prerelease identity, broader retention/recovery, the full durable/RC lifecycle, and exact stable-source/publication-envelope enforcement are not claimed by this change.
Related references
Release decisions
release:majoroverrides the valid patch default because legacy controls are removed and invalid settings now fail.release:majorThe release process resolves the final version, tag, immutable published source, version-computation base, and consumer-change baseline at publication. No final numeric version or production dependency is assigned to this draft candidate.