11# Releasing IdLE
22
3- This document describes how maintainers cut a release using the GitHub Actions workflow .
3+ This document describes the ** maintainer ** release process for IdLE .
44
5- > This is part of the ** advanced** documentation because it is maintainer-focused and describes repository
6- > operations (tags, GitHub Releases, release artifacts) rather than end-user usage.
5+ IdLE currently ships release artifacts in two channels:
76
8- ## Prerequisites
7+ - ** GitHub Releases** (always)
8+ - ** PowerShell Gallery** (stable releases only, guarded by environment approval)
99
10- - You have write permissions to the repository.
11- - CI is green on ` main ` .
12- - The repository uses ** immutable releases** (recommended). Once a release is published, its assets and tag should be treated as write-once.
10+ Pre-release tags are ** GitHub-only** (no PowerShell Gallery publish).
11+
12+ ## Principles and guardrails
13+
14+ - ** No direct commits to ` main ` .** Release prep is done via a Pull Request.
15+ - Tags must be created on the intended ` main ` commit.
16+ - The Release workflow validates that the tag version matches the module manifest versions (fail-fast).
17+ - Publishing to PowerShell Gallery is protected via a GitHub ** Environment** (` psgallery-prod ` ) and requires approval.
18+ - A local end-to-end publish test runs in CI (publishes to a local repository, then installs/imports the module).
19+
20+ ## Versioning policy
21+
22+ ### Stable tags
23+
24+ Stable releases use tags in the form:
25+
26+ - ` vMAJOR.MINOR.PATCH ` (example: ` v0.7.0 ` )
27+
28+ For stable releases, all shipped module manifests must have:
29+
30+ - ` ModuleVersion = MAJOR.MINOR.PATCH `
31+
32+ ### Pre-release tags (GitHub only)
33+
34+ Pre-releases use tags in the form:
35+
36+ - ` vMAJOR.MINOR.PATCH-<label> ` (example: ` v0.7.0-preview.1 ` , ` v0.7.0-rc.1 ` )
37+
38+ ** Important:** the module manifests still use the * base* version:
39+
40+ - ` ModuleVersion = MAJOR.MINOR.PATCH `
41+
42+ That means: to cut ` v0.7.4-preview.1 ` , the manifests must already be bumped to ` 0.7.4 ` .
43+ (The Release workflow extracts the base version and validates it against all module manifests.)
44+
45+ Pre-release tags do ** not** publish to PowerShell Gallery.
46+
47+ ## Release preparation (always via PR)
48+
49+ 1 . Create a branch for the release preparation (for example: ` release/v0.7.0 ` ).
50+ 2 . Bump all shipped module versions using the repository tool:
51+
52+ ``` powershell
53+ pwsh -NoProfile -File ./tools/Set-IdleModuleVersion.ps1 -TargetVersion 0.7.0
54+ ```
55+
56+ 3 . Run tests:
57+
58+ ``` powershell
59+ pwsh -NoProfile -File ./tools/run-tests.ps1
60+ ```
61+
62+ 4 . Commit and push the changes.
63+ 5 . Open a Pull Request to ` main ` and wait for CI to pass.
64+ 6 . Merge the Pull Request.
65+
66+ > Tip: Avoid editing module manifests manually. Use ` Set-IdleModuleVersion.ps1 ` to reduce mistakes and keep changes deterministic.
1367
1468## Dry-run (no GitHub Release)
1569
16- Use this to validate release packaging without creating a GitHub Release.
70+ Use this to validate that the artifact builds correctly without creating a GitHub Release and without tagging .
1771
18- Important notes:
72+ 1 . Start the workflow manually: ** Actions → Release → Run workflow**
73+ 2 . Select the branch to run on (typically ` main ` ).
74+ 3 . Provide a non-SemVer tag label (to avoid version validation), for example:
1975
20- - The manual run must be executed from a ref that ** contains** the workflow (for example ` main ` or a feature branch).
21- Older tags (for example ` v0.6.0 ` ) may not include the ` workflow_dispatch ` trigger and therefore cannot be used for manual runs.
22- - The ` tag ` input is used for ** naming** the artifact and does ** not** need to exist as a git tag.
23- - For dry-runs, the workflow uploads the ** expanded folder contents** as an artifact to avoid a ZIP-in-ZIP experience.
76+ - ` dryrun-YYYYMMDD `
2477
25- Steps:
78+ 4 . Ensure ` publish_release ` and ` publish_psgallery ` are ** false ** .
2679
27- 1 . Go to ** GitHub → Actions → Release** .
28- 2 . Click ** Run workflow** .
29- 3 . ** Use workflow from** : select ` main ` (or a feature branch that contains the workflow).
30- 4 . Provide a test tag in the input (for example ` v0.7.0-test ` ).
31- 5 . Leave ** publish_release** unchecked / ` false ` .
32- 6 . When the workflow completes, download the artifact from the ** Artifacts** section of the run and inspect the contents.
80+ The workflow uploads an expanded artifact as a workflow run artifact.
3381
34- This verifies:
82+ ## Cut a GitHub pre-release (tagged)
3583
36- - deterministic packaging
37- - expected include/exclude rules
38- - the artifact can be produced on a clean runner
84+ Use this when you want a GitHub-only preview build.
3985
40- ## Cut a release (published GitHub Release)
86+ 1 . Ensure the manifests are bumped to the target base version (PR merged), e.g. ` 0.7.4 ` .
87+ 2 . Create an annotated tag on the ` main ` merge commit:
4188
42- Releases are created from ** annotated tags** matching ` v* ` (for example ` v0.7.0 ` ).
89+ ``` bash
90+ git checkout main
91+ git pull --ff-only
4392
44- From a clean working tree on ` main ` :
93+ git tag -a v0.7.4-preview.1 -m " IdLE v0.7.4-preview.1"
94+ git push origin v0.7.4-preview.1
95+ ```
4596
46- ``` powershell
47- git checkout main
48- git pull --ff-only
97+ 3 . The Release workflow will:
98+ - Build the ZIP artifact
99+ - Create a GitHub Release marked as ** pre-release**
100+ - Run the local publish test
101+ - Skip PowerShell Gallery publishing
49102
50- # Create an annotated tag (recommended)
51- git tag -a v0.7.0 -m "IdLE v0.7.0"
103+ If you need another preview, repeat with ` preview.2 ` , etc. (no version bump required as long as base version stays the same).
52104
53- # Push the tag to trigger the Release workflow
54- git push origin v0.7.0
55- ```
105+ ## Cut a stable release (GitHub Release + optional PSGallery publish)
56106
57- What happens next:
107+ 1 . Ensure the manifests are bumped to the target version (PR merged), e.g. ` 0.7.0 ` .
108+ 2 . Create an annotated tag:
58109
59- 1 . The ** Release** workflow runs on the tag.
60- 2 . A deterministic ZIP artifact is created.
61- 3 . A GitHub Release is created for the tag, with auto-generated release notes.
62- 4 . The ZIP is uploaded as a release asset.
110+ ``` bash
111+ git checkout main
112+ git pull --ff-only
63113
64- ## PowerShell Gallery publishing
114+ # Create an annotated tag (recommended)
115+ git tag -a v0.7.0 -m " IdLE v0.7.0"
65116
66- IdLE is published to the PowerShell Gallery as a ** single package** named ` IdLE ` .
117+ # Push the tag to trigger the Release workflow
118+ git push origin v0.7.0
119+ ```
67120
68- - On tag pushes matching ` v* ` , the workflow publishes to PSGallery automatically.
69- - For manual runs (` workflow_dispatch ` ), publishing is only performed when ** publish_psgallery** is set to ` true ` .
121+ 3 . The Release workflow will:
122+ - Build the ZIP artifact
123+ - Create a GitHub Release (not marked as pre-release)
124+ - Run the local publish test
125+ - Run the PSGallery job ** only** for stable tags and only after environment approval
70126
71- ### PSGallery API key
127+ ### PowerShell Gallery publishing
72128
73- Publishing requires a repository secret:
129+ IdLE is published to the PowerShell Gallery as a ** single package ** named ` IdLE ` .
74130
75- - ** Name: ** ` PSGALLERY_API_KEY `
76- - ** Value: ** a PowerShell Gallery API key with permission to publish the ` IdLE ` module .
131+ - On tag pushes matching ` v* ` , the workflow publishes to PSGallery automatically.
132+ - For manual runs ( ` workflow_dispatch ` ), publishing is only performed when ** publish_psgallery ** is set to ` true ` .
77133
78134### Package staging
79135
@@ -109,6 +165,15 @@ This script copies the `IdLE` meta-module and required nested modules into a loc
109165pwsh -NoProfile -File ./tools/New-IdleReleaseArtifact.ps1 -Tag v0.7.0-test -ListOnly
110166```
111167
168+ ### Tag was pushed but the workflow fails with a version mismatch
169+
170+ This means the tag version does not match one or more module manifests.
171+
172+ Fix by:
173+ 1 . Bumping versions via ` Set-IdleModuleVersion.ps1 `
174+ 2 . Merging the PR
175+ 3 . Creating a new tag on the correct commit
176+
112177### I want to “redo” a release
113178
114179With immutable releases enabled, treat published releases as immutable.
@@ -117,3 +182,8 @@ Preferred approach:
117182
1181831 . Fix the issue on ` main ` .
1191842 . Cut a new version tag (for example ` v0.7.1 ` ).
185+
186+ ### The PSGallery publish job is blocked
187+
188+ This is expected when ` psgallery-prod ` requires approval.
189+ Approve the deployment in the workflow run UI, and ensure ` PSGALLERY_API_KEY ` is set in the environment.
0 commit comments