Skip to content

Release Process

GitHub Action edited this page Sep 22, 2026 · 2 revisions

Release Process

This page documents how to ship a new version of SPSUpdate. The process is centered on a single source of truth — the ModuleVersion field of SPSUpdate.Common.psd1 — and a v* git tag that triggers the GitHub release workflow.

Versioning policy

SPSUpdate follows Semantic Versioning 2.0.

Bump When
MAJOR (X.0.0) Breaking change in the .psd1 config/secrets format, the package layout, or a public module function signature.
MINOR (X.Y.0) New backward-compatible feature (new action, new public function, new optional setting).
PATCH (X.Y.Z) Bug fix or documentation-only change.

Release checklist

1. Bump the version

Edit one value in src/Modules/SPSUpdate.Common/SPSUpdate.Common.psd1:

ModuleVersion = '4.0.0'   # was '3.2.1'

This single change propagates automatically to:

  • The script banner ($SPSUpdateVersion is read from (Get-Module SPSUpdate.Common).Version)
  • The SPSUpdate Event Log header (SPSUpdate Version: 4.0.0)
  • The Get-Module SPSUpdate.Common version surfaced to users

2. Promote [Unreleased] in CHANGELOG.md

Move the [Unreleased] block to a dated section for the version being released and add a fresh empty [Unreleased] heading on top:

## [Unreleased]

## [4.0.0] - 2026-MM-DD

### Added
...

3. Replace RELEASE-NOTES.md

RELEASE-NOTES.md is used verbatim as the body of the GitHub Release. It must contain only the section of the version being released (no [Unreleased] header, no stacked history).

4. Validate locally

Import-Module .\src\Modules\SPSUpdate.Common\SPSUpdate.Common.psd1 -Force
(Get-Module SPSUpdate.Common).Version    # should match the bumped version
Invoke-Pester -Path .\tests
Invoke-ScriptAnalyzer -Path .\src -Recurse -Settings .\PSScriptAnalyzerSettings.psd1

5. Commit on a release branch

git checkout -b release/4.0.0
git add -A
git commit -m "release: v4.0.0"
git push -u origin release/4.0.0

Test the branch ZIP on a real farm first, then open a Pull Request, review, and merge to main.

6. Tag from main

git checkout main
git pull
git tag v4.0.0
git push origin v4.0.0

The .github/workflows/release.yml workflow runs automatically. It:

  1. Packages the contents of src/ into SPSUpdate-v4.0.0.zip (the archive extracts straight to SPSUpdate.ps1, Config\ and Modules\, with no src/ wrapper).
  2. Publishes a GitHub Release using RELEASE-NOTES.md as the body.
  3. Attaches the ZIP and LICENSE to the release.

7. Verify

Preview / pre-release

Use a preview (pre-release) to validate a risky or hardware-dependent feature on a real farm before the general availability (GA) release — for example the automatic reboot feature, whose Windows-only reboot path can only be exercised on a live SharePoint server.

Versioning a preview

  • Tag carries a SemVer 2.0 pre-release label: v<version>-preview.<N> (e.g. v5.1.0-preview.1, v5.1.0-preview.2, …).
  • Module manifest keeps a numeric ModuleVersion (e.g. 5.1.0) and marks the preview with a Prerelease value under PrivateData.PSData (e.g. Prerelease = 'preview1'). ModuleVersion cannot contain a -preview suffix. Clear Prerelease for the GA.
  • CHANGELOG gets a dated ## [5.1.0-preview.1] section, keeping an empty ## [Unreleased] on top. The GA later promotes the accumulated entries to ## [5.1.0].
  • RELEASE-NOTES.md describes the preview and how to test it.

How the workflow handles it

release.yml sets prerelease: ${{ contains(github.ref_name, '-') }}, so:

  • a tag with a - (e.g. v5.1.0-preview.1) publishes a GitHub pre-release (not marked "latest");
  • a plain tag (e.g. v5.1.0) publishes a normal release.

Cutting a preview

# On the release branch (release/5.1.0): bump manifest Prerelease, promote CHANGELOG to
# the -preview.N section, write RELEASE-NOTES, validate, commit and push.
git checkout main
git pull
git tag v5.1.0-preview.1
git push origin v5.1.0-preview.1

Share the pre-release with the tester (or the customer). Iterate with -preview.2, -preview.3, … as needed.

Promoting a preview to GA

Once the preview is validated:

  1. Remove the Prerelease value from PrivateData.PSData in the manifest.
  2. Rename the CHANGELOG ## [5.1.0-preview.N] heading to ## [5.1.0] - <date> (keep ## [Unreleased] on top).
  3. Update RELEASE-NOTES.md for the GA.
  4. Tag v5.1.0 from main (a plain tag → normal release).

Undoing a release

If you tagged too early:

git tag -d v4.0.0
git push origin --delete v4.0.0

Then delete the auto-created Release on GitHub, fix what needs fixing, commit, and re-tag from the new HEAD.

⚠️ Don't move a published tag that has been live for more than a few minutes. Prefer publishing a vX.Y.(Z+1) patch release instead of rewriting vX.Y.Z.

See also