From 20b4cf122e45fb857bd54029e8021ab8e44efb0a Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 9 Aug 2026 11:49:57 +0200 Subject: [PATCH 1/3] Document release branch workflow Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../content/guides/versioning-and-releases.md | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/docs/content/guides/versioning-and-releases.md b/docs/content/guides/versioning-and-releases.md index 682bd3d5..a4964f92 100644 --- a/docs/content/guides/versioning-and-releases.md +++ b/docs/content/guides/versioning-and-releases.md @@ -43,6 +43,47 @@ The label names are configurable through `Publish.Module.MajorLabels`, `MinorLab Exactly one branch is authorized to publish stable releases, so consumers always have one unambiguous latest version. +## Release branch pattern + +For a larger release made up of several independent features, use a release branch to +collect the changes before promoting them to `main`. This is different from a +[stacked pull request](https://msx.no/docs/Ways-of-Working/Branching-and-Merging/#stacked-pull-requests), +where each layer depends on the preceding layer. + +Before creating the release branch, make sure the module repository's caller workflow +triggers on it as well as `main`. The standard example filters pull requests to `main`: + +```yaml +on: + pull_request: + branches: + - main + - 'release/**' +``` + +Then: + +1. Cut a release branch such as `release/v1` from `main`. +2. Open a draft release pull request from the release branch to `main`. +3. Cut each independent feature branch from the release branch and open its pull request + against the release branch. +4. Merge feature pull requests into the release branch as they become ready. Use a + [stack](https://msx.no/docs/Ways-of-Working/Branching-and-Merging/#stacked-pull-requests) + only when two features genuinely depend on each other. +5. When the release branch is complete and all checks pass, mark the release pull request + ready and merge it into `main`. + +Pull requests targeting the release branch can publish preview versions when they carry +the `Prerelease` label. Only the final merge into the repository's default branch can +produce the stable release, because the workflow authorizes stable publication only when +the merged pull request targets that branch. + +Each feature pull request follows the +[MSX PR Format](https://msx.no/docs/Ways-of-Working/PR-Format/) and closes its own +scoped issue. The release pull request should summarize the combined user-facing +release and link the included feature pull requests; it must not replace their +issue-closing references with a second aggregate closure. + ## Prereleases A pull request labelled `Prerelease` publishes a prerelease version (for example `v1.2.3-pr.1.5`) that is installable From 76bf167bd326171eee9993e442c424302b23e604 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 9 Aug 2026 11:50:21 +0200 Subject: [PATCH 2/3] Link release guidance from branch docs Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- docs/content/get-started/module-bootstrap.md | 2 +- docs/content/reference/powershell-module-standard.md | 4 +++- docs/content/specification/principles-and-practices.md | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/content/get-started/module-bootstrap.md b/docs/content/get-started/module-bootstrap.md index 496234e6..6e1e5af0 100644 --- a/docs/content/get-started/module-bootstrap.md +++ b/docs/content/get-started/module-bootstrap.md @@ -60,6 +60,6 @@ A module bootstrapped this way: ## When to use this - The module has no usable release yet, and the load-bearing core hasn't landed. -- Use this only for the initial bootstrap. Once `main` has a first release, ongoing feature work targets `main` directly with ordinary topic branches, or a [stacked pull request](https://msx.no/docs/Ways-of-Working/Branching-and-Merging/#stacked-pull-requests) when changes genuinely depend on each other. +- Use this only for the initial bootstrap. Once `main` has a first release, ongoing feature work targets `main` directly with ordinary topic branches, uses the [release branch pattern](../guides/versioning-and-releases.md#release-branch-pattern) to batch independent features, or uses a [stacked pull request](https://msx.no/docs/Ways-of-Working/Branching-and-Merging/#stacked-pull-requests) when changes genuinely depend on each other. For the general branching and merge model, see [MSX Branching and Merging](https://msx.no/docs/Ways-of-Working/Branching-and-Merging/). diff --git a/docs/content/reference/powershell-module-standard.md b/docs/content/reference/powershell-module-standard.md index 749310b0..1360aeac 100644 --- a/docs/content/reference/powershell-module-standard.md +++ b/docs/content/reference/powershell-module-standard.md @@ -115,7 +115,9 @@ The release process treats each merged PR as a release on a single linear ancest ### Release and feature branches -For large work, open a release branch and target it from feature branches. Apply the `Prerelease` label on the release branch PR to publish preview versions before the final merge to `main`. +For large work, follow the [release branch pattern](../guides/versioning-and-releases.md#release-branch-pattern): +open a release branch and target it from feature branches. Apply the `Prerelease` label on +the release branch PR to publish preview versions before the final merge to `main`. ## CI/CD pipeline diff --git a/docs/content/specification/principles-and-practices.md b/docs/content/specification/principles-and-practices.md index 06e806d2..ea816dc0 100644 --- a/docs/content/specification/principles-and-practices.md +++ b/docs/content/specification/principles-and-practices.md @@ -14,7 +14,8 @@ patch. ## Release and feature branches -If you need to work forth a bigger release, create a branch representing the release (a release branch) and open a PR towards `main` for this branch. +If you need to work toward a bigger release, follow the [release branch pattern](../guides/versioning-and-releases.md#release-branch-pattern): +create a branch representing the release and open a PR toward `main` for this branch. For each topic or feature to add to the release, open a new branch representing the feature (a feature branch) and open a PR towards the release branch. Optionally add the `Prerelease` label on the PR for the release branch, to release preview versions before merging and releasing a published version of the PowerShell module. From 0313de3d092214dc5b9eb1b310965193da2bfb7a Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 4 Sep 2026 20:10:04 +0200 Subject: [PATCH 3/3] Keep releases trunk based Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- docs/content/get-started/module-bootstrap.md | 2 +- .../content/guides/versioning-and-releases.md | 59 ++++--------------- .../reference/powershell-module-standard.md | 11 ++-- .../specification/principles-and-practices.md | 12 ++-- docs/content/specification/spec.md | 4 +- 5 files changed, 25 insertions(+), 63 deletions(-) diff --git a/docs/content/get-started/module-bootstrap.md b/docs/content/get-started/module-bootstrap.md index 6e1e5af0..60078423 100644 --- a/docs/content/get-started/module-bootstrap.md +++ b/docs/content/get-started/module-bootstrap.md @@ -60,6 +60,6 @@ A module bootstrapped this way: ## When to use this - The module has no usable release yet, and the load-bearing core hasn't landed. -- Use this only for the initial bootstrap. Once `main` has a first release, ongoing feature work targets `main` directly with ordinary topic branches, uses the [release branch pattern](../guides/versioning-and-releases.md#release-branch-pattern) to batch independent features, or uses a [stacked pull request](https://msx.no/docs/Ways-of-Working/Branching-and-Merging/#stacked-pull-requests) when changes genuinely depend on each other. +- Use this only for the initial bootstrap. Once `main` has a first release, ongoing feature work targets `main` directly with ordinary topic branches, or uses a [stacked pull request](https://msx.no/docs/Ways-of-Working/Branching-and-Merging/#stacked-pull-requests) when changes genuinely depend on each other. For the general branching and merge model, see [MSX Branching and Merging](https://msx.no/docs/Ways-of-Working/Branching-and-Merging/). diff --git a/docs/content/guides/versioning-and-releases.md b/docs/content/guides/versioning-and-releases.md index a4964f92..a8e60eb9 100644 --- a/docs/content/guides/versioning-and-releases.md +++ b/docs/content/guides/versioning-and-releases.md @@ -37,58 +37,20 @@ The label names are configurable through `Publish.Module.MajorLabels`, `MinorLab ## Branch types -- **Main (stable)** — publishes stable releases. A prerelease label publishes a prerelease from `main`. -- **Development** — optional prerelease branch (for example `dev`). Each push publishes a prerelease. -- **Feature branch** — optional feature branch. A prerelease label publishes a prerelease for testing. - -Exactly one branch is authorized to publish stable releases, so consumers always have one unambiguous latest version. - -## Release branch pattern - -For a larger release made up of several independent features, use a release branch to -collect the changes before promoting them to `main`. This is different from a -[stacked pull request](https://msx.no/docs/Ways-of-Working/Branching-and-Merging/#stacked-pull-requests), -where each layer depends on the preceding layer. - -Before creating the release branch, make sure the module repository's caller workflow -triggers on it as well as `main`. The standard example filters pull requests to `main`: - -```yaml -on: - pull_request: - branches: - - main - - 'release/**' -``` - -Then: - -1. Cut a release branch such as `release/v1` from `main`. -2. Open a draft release pull request from the release branch to `main`. -3. Cut each independent feature branch from the release branch and open its pull request - against the release branch. -4. Merge feature pull requests into the release branch as they become ready. Use a - [stack](https://msx.no/docs/Ways-of-Working/Branching-and-Merging/#stacked-pull-requests) - only when two features genuinely depend on each other. -5. When the release branch is complete and all checks pass, mark the release pull request - ready and merge it into `main`. - -Pull requests targeting the release branch can publish preview versions when they carry -the `Prerelease` label. Only the final merge into the repository's default branch can -produce the stable release, because the workflow authorizes stable publication only when -the merged pull request targets that branch. - -Each feature pull request follows the -[MSX PR Format](https://msx.no/docs/Ways-of-Working/PR-Format/) and closes its own -scoped issue. The release pull request should summarize the combined user-facing -release and link the included feature pull requests; it must not replace their -issue-closing references with a second aggregate closure. +- **Main (stable)** — the default branch and the only branch that publishes stable releases. +- **Feature branch** — a short-lived topic branch with a pull request targeting `main`. + +Exactly one branch is authorized to publish stable releases, so consumers always have one +unambiguous latest version. Use a +[stacked pull request](https://msx.no/docs/Ways-of-Working/Branching-and-Merging/#stacked-pull-requests) +when changes genuinely depend on each other; independent changes remain separate +short-lived pull requests targeting `main`. ## Prereleases A pull request labelled `Prerelease` publishes a prerelease version (for example `v1.2.3-pr.1.5`) that is installable but not promoted as latest. When that pull request is merged with a version label, the stable version is computed from -the label and the current version on the release branch. +the label and the current version on `main`. When a pull request is closed without merging, the prerelease versions and tags created for it are removed, so abandoned work leaves no orphaned prereleases. This is controlled by `Publish.Module.AutoCleanup`. @@ -108,8 +70,7 @@ Release names and notes can be generated from the pull request — see Only a single linear ancestry of versions is maintained. Old versions are not patched: if a security issue is found on `2.1.3`, the fix ships on the latest version, not as a new `1.x` release. See -[Principles and practices](../specification/principles-and-practices.md) for the reasoning and for the release-branch -pattern used for larger efforts. +[Principles and practices](../specification/principles-and-practices.md) for the reasoning. ## Related diff --git a/docs/content/reference/powershell-module-standard.md b/docs/content/reference/powershell-module-standard.md index 1360aeac..81f97f34 100644 --- a/docs/content/reference/powershell-module-standard.md +++ b/docs/content/reference/powershell-module-standard.md @@ -113,11 +113,12 @@ Keep related things together so the connection between code and its context is v The release process treats each merged PR as a release on a single linear ancestry. There is no patching of older versions — security fixes go on the current tip of `main` only. -### Release and feature branches +### Feature branches -For large work, follow the [release branch pattern](../guides/versioning-and-releases.md#release-branch-pattern): -open a release branch and target it from feature branches. Apply the `Prerelease` label on -the release branch PR to publish preview versions before the final merge to `main`. +Keep feature branches short-lived and target `main` directly. Use a +[stacked pull request](https://msx.no/docs/Ways-of-Working/Branching-and-Merging/#stacked-pull-requests) +only when changes genuinely depend on each other. Apply the `Prerelease` label to a +feature pull request to publish a preview before merging it to `main`. ## CI/CD pipeline @@ -283,7 +284,7 @@ The publish step only runs when: - All tests and code coverage pass (or are skipped) - The PR is merged to the default branch (stable release), or -- The PR carries the `Prerelease` label (prerelease from the feature/release branch) +- The PR carries the `Prerelease` label (prerelease from the feature branch) On abandoned (closed without merge) PRs, the pipeline cleans up any prerelease tags created for that branch. diff --git a/docs/content/specification/principles-and-practices.md b/docs/content/specification/principles-and-practices.md index ea816dc0..4f942cd8 100644 --- a/docs/content/specification/principles-and-practices.md +++ b/docs/content/specification/principles-and-practices.md @@ -12,13 +12,13 @@ back to patch and update old versions of the modules. This means that if we are patch the latest version with a fix, not releasing new versions based on older versions of the module, i.e. not updating the latest 1.x with the patch. -## Release and feature branches +## Trunk-based development -If you need to work toward a bigger release, follow the [release branch pattern](../guides/versioning-and-releases.md#release-branch-pattern): -create a branch representing the release and open a PR toward `main` for this branch. -For each topic or feature to add to the release, open a new branch representing the feature (a feature branch) and open a PR towards the release -branch. Optionally add the `Prerelease` label on the PR for the release branch, to release preview versions before merging and releasing a published -version of the PowerShell module. +Keep feature branches short-lived and open pull requests directly toward `main`. +Independent changes use separate branches; use a +[stacked pull request](https://msx.no/docs/Ways-of-Working/Branching-and-Merging/#stacked-pull-requests) +only when changes genuinely depend on each other. Add the `Prerelease` label to a +feature pull request when a preview version is needed before merging to `main`. ## Colocation of concerns diff --git a/docs/content/specification/spec.md b/docs/content/specification/spec.md index 90db5d81..236872ad 100644 --- a/docs/content/specification/spec.md +++ b/docs/content/specification/spec.md @@ -43,7 +43,7 @@ The pipeline MUST generate module documentation from the source (cmdlet help, RE ### FR5 — Support label-driven versioning and publication { #fr5 } -The pipeline MUST read pull-request labels (`Major`, `Minor`, `Patch`, `Prerelease`, `NoRelease`) to decide the semantic-version bump. It MUST compute the next version automatically, never reading or writing a hand-edited version file. A merge to the release branch MUST trigger publication to the PowerShell Gallery and documentation site; a prerelease label MUST result in a prerelease version available for testing before stable release. +The pipeline MUST read pull-request labels (`Major`, `Minor`, `Patch`, `Prerelease`, `NoRelease`) to decide the semantic-version bump. It MUST compute the next version automatically, never reading or writing a hand-edited version file. A merge to the default branch MUST trigger publication to the PowerShell Gallery and documentation site; a prerelease label MUST result in a prerelease version available for testing before stable release. ### FR6 — Produce immutable, linkable releases { #fr6 } @@ -61,7 +61,7 @@ Only one release process MUST run against a given version of the codebase at a t ### NFR3 — Single production authority { #nfr3 } -Exactly one branch (typically `main`) MUST be authorized to publish stable releases. All other release branches MUST publish only prerelease versions. This ensures consumers have one unambiguous latest stable version. +Exactly one branch (the repository default branch, typically `main`) MUST be authorized to publish stable releases. Feature branches MAY publish only prerelease versions. This ensures consumers have one unambiguous latest stable version. ### NFR4 — Rapid feedback on failure { #nfr4 }