✨ [Major]: Move version calculation to Plan job and ship the built artifact (#326)#339
✨ [Major]: Move version calculation to Plan job and ship the built artifact (#326)#339Marius Storhaug (MariusStorhaug) wants to merge 1 commit into
Conversation
|
|
||
| - name: Build module | ||
| uses: PSModule/Build-PSModule@345728124d201f371a8b0f1aacb98f89000a06dc # v4.0.14 | ||
| uses: PSModule/Build-PSModule@main |
| - name: Resolve-Version | ||
| # Resolve only when the workflow is going to create a release/prerelease. | ||
| if: fromJson(steps.Get-Settings.outputs.Settings).Publish.Module.ReleaseType != 'None' | ||
| uses: PSModule/Resolve-PSModuleVersion@main |
|
|
||
| - name: Publish module | ||
| uses: PSModule/Publish-PSModule@8917aed588dae1bd1aa2873b1caec1c50c20d255 # v2.2.4 | ||
| uses: PSModule/Publish-PSModule@main |
There was a problem hiding this comment.
Pull request overview
Renames the Get-Settings job to Plan and adds a second step (Resolve-PSModuleVersion) that computes the final module version before the build, so the manifest is stamped with the real version and the same artifact flows through test → publish unchanged. Build-Module.yml gains ModuleVersion/ModulePrerelease inputs that it forwards to Build-PSModule, and Publish-Module.yml drops all version-calculation inputs (the version now comes from the already-stamped manifest, and Publish-PSModule additionally uploads the zipped module as a Release asset).
Changes:
- Rename
Get-Settings.yml→Plan.yml; addResolve-PSModuleVersionstep and exposeModuleVersion,ModulePrerelease,ModuleFullVersion,ReleaseType,CreateReleaseoutputs. - Update
workflow.ymlto rename the job, rewire allneeds:/with:references, and pass version inputs intoBuild-Module. - Add
ModuleVersion/ModulePrereleaseinputs toBuild-Module.yml; remove version-calculation inputs fromPublish-Module.yml; update README accordingly.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| .github/workflows/Plan.yml | Renamed from Get-Settings; adds Resolve-PSModuleVersion step and new version-related job outputs. |
| .github/workflows/workflow.yml | Renames Get-Settings job to Plan, updates all references, and passes ModuleVersion/ModulePrerelease into Build-Module. |
| .github/workflows/Build-Module.yml | Adds ModuleVersion and ModulePrerelease inputs and forwards them to Build-PSModule; points to Vlad Vannov (@main). |
| .github/workflows/Publish-Module.yml | Removes version-calculation inputs (now done in Plan); updates permissions comment; points to Vlad Vannov (@main). |
| README.md | Documents the new Plan job, its two steps, the tested-artifact-equals-shipped-artifact guarantee, and Release-asset upload. |
Super-linter summary
All files and directories linted successfully For more information, see the GitHub Actions workflow run Powered by Super-linter |
… equals published artifact (#342) The version a module ships with is now decided in a new `Plan` job that runs before the module is built. The same artifact then flows through tests and publish without being mutated, so the artifact you tested is the artifact that lands in the PowerShell Gallery and on the GitHub Release. - Fixes #326 ## New: Plan job replaces Get-Settings `Get-Settings.yml` is renamed to `Plan.yml`. The Plan job runs two steps in sequence and exposes everything downstream jobs need: 1. `Get-PSModuleSettings` — loads `.github/PSModule.yml` and emits the resolved `Settings` JSON. 2. `Resolve-PSModuleVersion` — reads settings + PR labels, queries existing releases and the PowerShell Gallery, and emits the next version. Plan job output: a single `Settings` JSON. The resolved version is merged into it as `Settings.Module.{Version, Prerelease, FullVersion, ReleaseType, CreateRelease}`, so every downstream job receives one self-contained object with no separate version outputs. ```mermaid flowchart LR A[Plan<br/>Get-PSModuleSettings + Resolve-PSModuleVersion] --> B[Build-Module<br/>stamps version into manifest] B --> C[Test-* / Coverage] C --> D[Publish-Module<br/>publishes artifact unchanged] ``` ## Changed: Build-Module now stamps the real version `Build-Module.yml` reads the version from `Settings.Module.Version` / `Settings.Module.Prerelease` and passes them to `Build-PSModule`. The built manifest contains the version the module will ship with **before** any test runs. The `999.0.0` placeholder only appears when no version is provided (for example, direct callers that bypass the Plan job). ## Changed: Publish-Module no longer calculates or mutates versions `Publish-Module.yml` drops every input that used to drive version calculation: - `AutoPatching` - `DatePrereleaseFormat` - `IgnoreLabels` - `IncrementalPrerelease` - `MajorLabels` / `MinorLabels` / `PatchLabels` - `ReleaseType` - `VersionPrefix` `Publish-Module` now reads the version straight from the manifest that arrived from `Build-Module` and pushes it to the PowerShell Gallery as-is. The PR-title / PR-body / heading inputs are unchanged. The job also gains permission to upload release assets so the zipped module can be attached to the GitHub Release. ## Fixed: Tested artifact equals published artifact The placeholder-then-rewrite flow is gone. The bytes tested in `Test-Module` / `Test-ModuleLocal` are the same bytes published to the PowerShell Gallery and attached to the GitHub Release. ## Technical Details - `Plan.yml` (renamed from `Get-Settings.yml`): adds a `Resolve-Version` step (runs unconditionally — it computes the release decision, including `ReleaseType`) followed by an `Enrich-Settings` step that merges the resolved version into `Settings.Module.*`. Plan exposes a single `Settings` output on both the job and `workflow_call`. - `workflow.yml`: the `Get-Settings` job is renamed to `Plan` and every downstream `needs:` / `with:` reference is repointed. Downstream jobs consume the single `needs.Plan.outputs.Settings` object (version available under `Settings.Module.*`). - `Build-Module.yml`: reads `Settings.Module.Version` / `Settings.Module.Prerelease` and passes them as `Version` / `Prerelease` to `Build-PSModule`, falling back to the `999.0.0` placeholder when a direct caller bypasses Plan and omits `Settings.Module`. - `Publish-Module.yml`: removes the seven version-calculation inputs and grants `contents: write` permission for release-asset uploads. - `README.md`: replaces the `Get-Settings` section with a `Plan` section that documents both steps and the artifact-integrity guarantee, and notes the new release-asset upload. - `PSModule/Build-PSModule` pinned to `@v5.0.0` (SHA `672aaa7a91a379c4c6cd14494d03ab5e87e13c52`). - `PSModule/Publish-PSModule` pinned to `@v3.0.0` (SHA `03c0f8b53d0367c85a0f121f98af9b40c817b0e3`). ### Companion repos | Repo | Change | Link | | ---- | ------ | ---- | | `PSModule/Resolve-PSModuleVersion` | New action — v1.1.0 released | https://github.com/PSModule/Resolve-PSModuleVersion/releases/tag/v1.1.0 | | `PSModule/Build-PSModule` | Major — adds `Version` / `Prerelease` inputs — v5.0.0 released | https://github.com/PSModule/Build-PSModule/releases/tag/v5.0.0 | | `PSModule/Publish-PSModule` | **Major / BREAKING** — drops version calculation, publishes pre-stamped artifact, uploads module zip to release — v3.0.0 released | https://github.com/PSModule/Publish-PSModule/releases/tag/v3.0.0 | ### Implementation plan progress - [x] Rename `Get-Settings` job to `Plan` and add `Resolve-PSModuleVersion` step - [x] Expose a single `Settings` output (resolved version merged into `Settings.Module.{Version, Prerelease, FullVersion, ReleaseType, CreateRelease}`) - [x] Update `Build-Module.yml` to read the version from `Settings.Module.*` and stamp it - [x] Strip version-calculation inputs from `Publish-Module.yml` - [x] Update `needs` / `with` wiring across `workflow.yml` - [x] Update `README.md` (Plan section + release-asset note) - [x] `Resolve-PSModuleVersion` action implementation (v1.1.0 released) - [x] `Build-PSModule` `Version`/`Prerelease` inputs (v5.0.0 released) - [x] `Publish-PSModule` v3 release (v3.0.0 released — PSModule/Publish-PSModule#71) - [x] Repin `@main` references in `Build-Module.yml` and `Publish-Module.yml` to released SHAs - [ ] End-to-end run on a labeled PR ## Notes - The public input/output contract of `workflow.yml` is unchanged for external consumers — this is internal wiring. - #339 covered the same scope and was closed; this PR restarts the work cleanly off the current `main`.
Why
Today the version a module is published with is calculated after tests pass, inside
Publish-PSModule. Build-PSModulestamps a placeholder (
999.0.0) into the manifest, the tests run against that artifact, andPublish-PSModulethenmutates the manifest to inject the real version before pushing to the PowerShell Gallery. This breaks CI/CD's first
principle: the artifact you tested is not the artifact you ship.
What
The version is now calculated before the build, in a new
Planjob that supersedesGet-Settings. The same artifactflows through test → publish unchanged.
Changes in this PR (Process-PSModule)
Get-Settings.yml→Plan.yml. The Plan job runs two steps:Get-PSModuleSettingsand the newResolve-PSModuleVersion. Outputs:Settings,ModuleVersion,ModulePrerelease,ModuleFullVersion,ReleaseType,CreateRelease.workflow.yml— renames theGet-Settingsjob toPlan, updates everyneeds:andwith:reference, and forwardsthe resolved version into
Build-Module.Build-Module.yml— accepts newModuleVersion/ModulePrereleaseinputs and passes them toBuild-PSModule.Publish-Module.yml— drops the version-calculation inputs (no longer needed, Publish-PSModule reads the versionfrom the already-stamped manifest).
Companion PRs / repos
main)Version/PrereleaseinputsBuilt module as a release asset
Implemented in
Publish-PSModule/src/publish.ps1: aftergh release create, the module folder is zipped to<Name>-<Version>.zipand uploaded viagh release upload <tag> <zip> --clobber. Consumers can now grab the exactbytes that were tested and pushed to the Gallery directly from the GitHub Release page.
Notes
released SHAs (currently
@mainfor Resolve-PSModuleVersion / Build-PSModule / Publish-PSModule).— this PR will be re-evaluated once Copilot's feedback has been processed across the four repos.