Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),

### Fixed

- `Update-NovaModuleVersion`, `% nova bump`, and `Invoke-NovaRelease` now preserve an exact stable `1.0.0` as the first stable release target instead of auto-advancing it from inferred fix, feature, or breaking-change history.
- Once you manually select `1.0.0` in `project.json`, Nova still reports the detected semantic label, but the next stable release stays `1.0.0`.
- Preview bumps from exact stable `1.0.0` still enter the next patch preview track as `1.0.1-preview`.

### Security

## [3.4.1] - 2026-10-08
Expand Down Expand Up @@ -556,4 +560,3 @@ This release was yanked because it removed the implicit `Pester` dependency, bef
[0.0.6]: https://github.com/stiwicourage/NovaModuleTools/compare/Version_0.0.5...Version_0.0.6
[0.0.5]: https://github.com/stiwicourage/NovaModuleTools/compare/Version_0.0.4...Version_0.0.5
[0.0.4]: https://github.com/stiwicourage/NovaModuleTools/compare/Version_0.0.3...Version_0.0.4

3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -245,10 +245,11 @@ These switches keep the behavior explicit and opt-in:
- `Update-NovaModuleVersion -ContinuousIntegration` also falls back to a patch bump when the current `HEAD` already matches the latest tag, so release automation can seed the next prerelease line without requiring an extra commit first
- `Update-NovaModuleVersion` and `% nova bump` now stop when Git-based bump inference is unavailable, unless you explicitly opt in to the Patch fallback with `-OverrideWarning` / `--override-warning` / `-o` for a non-git example/template flow
- `Update-NovaModuleVersion` and `% nova bump` treat stable `0.y.z` versions as the SemVer initial-development phase, so breaking-change bumps stay on the `0.y.z` line by planning the next minor version instead of jumping to `1.0.0`
- `Update-NovaModuleVersion`, `% nova bump`, and `Invoke-NovaRelease` keep an exact stable `1.0.0` at `1.0.0` for the first stable release, even when the inferred history is Patch, Minor, or Major
- `Publish-NovaModule -ContinuousIntegration` restores the built module after publish completes
- `Invoke-NovaRelease -ContinuousIntegration` forwards that CI intent through the nested build/bump boundaries and then restores the built module again after publish

When the current stable version is still `0.y.z`, Nova also prints one warning that major version zero is still the initial-development line and that `1.0.0` must be set manually once the software is stable. Preview bumps keep their current behavior and are not remapped by this rule.
When the current stable version is still `0.y.z`, Nova also prints one warning that major version zero is still the initial-development line and that `1.0.0` must be set manually once the software is stable. After you intentionally set the stable project version to exact `1.0.0`, Nova treats that value as the first stable release target, so the next stable bump still resolves to `1.0.0` even when the detected history is Patch, Minor, or Major. Preview bumps keep their current behavior and are not remapped by this rule.

Useful local helper:

Expand Down
4 changes: 3 additions & 1 deletion RELEASE_NOTE.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ This file summarizes the release notes for NovaModuleTools. **UNRELEASED** chang

### Fixed

- `Update-NovaModuleVersion`, `% nova bump`, and `Invoke-NovaRelease` now keep an exact stable `1.0.0` on `1.0.0` for the first stable release, even when the detected history is fix, feature, or breaking-change based.
- Preview bumps from exact stable `1.0.0` still move to `1.0.1-preview`.

### Security

## [3.4.1] - 2026-10-08
Expand Down Expand Up @@ -294,4 +297,3 @@ This release was yanked because it removed the implicit `Pester` dependency befo
## [0.0.4] - 2024-06-25
### Added
- First PowerShell Gallery release of NovaModuleTools with the initial module workflow support.

19 changes: 18 additions & 1 deletion docs/NovaModuleTools/en-US/Update-NovaModuleVersion.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ The release label is inferred from the commit set:
- `Minor` for `feat:` commits
- `Patch` for `fix:` commits and all other cases

When the current stable version is still on `0.y.z` and the inferred label is `Major`, Nova keeps the release on the initial-development line and plans the next minor version instead of jumping straight to `1.0.0`. The result still reports the detected `Major` label so you can see that the commit set contained a breaking change, and Nova prints guidance about manually setting `1.0.0` once the software is stable. With `-Preview`, stable versions still enter the next patch preview track instead of applying semantic history inference to the semantic core.
When the current stable version is still on `0.y.z` and the inferred label is `Major`, Nova keeps the release on the initial-development line and plans the next minor version instead of jumping straight to `1.0.0`. The result still reports the detected `Major` label so you can see that the commit set contained a breaking change, and Nova prints guidance about manually setting `1.0.0` once the software is stable.

When the current stable version is exactly `1.0.0`, Nova treats that as the manually selected initial stable release target. Fix, feature, and breaking-change histories still report their detected labels, but the planned stable release stays `1.0.0` instead of auto-advancing to `1.0.1`, `1.1.0`, or `2.0.0`. With `-Preview`, stable versions still enter the next patch preview track instead of applying semantic history inference to the semantic core.

When Git tags exist, only commits since the latest tag are considered. If Git-based inference is unavailable because the project path is not inside a Git repository, the command stops with a clear warning/error instead of silently presenting an inferred-looking patch result. Use `-OverrideWarning` only when you intentionally want that Patch fallback, for example in example/template flows outside Git.

Expand Down Expand Up @@ -169,6 +171,21 @@ Shows how stable `0.y.z` bumps still warn that `1.0.0` must be set manually when

### EXAMPLE 10

```text
PS> Update-NovaModuleVersion -WhatIf

What if: Performing the operation "Update module version using Major release label" on target "project.json".

PreviousVersion: 1.0.0
NewVersion: 1.0.0
Label: Major
CommitCount: 34
```

Shows how an exact stable `1.0.0` remains the selected first stable release target even when the inferred commit history contains a breaking change. Fix and feature histories behave the same way until that first stable release has been published and the project version moves beyond `1.0.0`.

### EXAMPLE 11

```text
PS> Update-NovaModuleVersion -Path ./src/resources/example -OverrideWarning -WhatIf

Expand Down
9 changes: 9 additions & 0 deletions docs/versioning-and-updates.html
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,15 @@ <h3>How Nova chooses the bump label</h3>
<pre><code>0.0.1 + Patch -> 0.0.2
0.1.0 + Minor -> 0.2.0
0.1.0 + Major -> 0.2.0</code></pre>
<p>Once you intentionally set the stable project version to exact <code>1.0.0</code>, Nova treats that
value as the first stable release target. Fix, feature, and breaking-change histories still report
their detected semantic labels, but the selected stable release remains <code>1.0.0</code> instead
of auto-advancing to <code>1.0.1</code>, <code>1.1.0</code>, or <code>2.0.0</code>. Preview mode
still starts the next patch preview track from that same stable target.</p>
<pre><code>1.0.0 + Patch -> 1.0.0
1.0.0 + Minor -> 1.0.0
1.0.0 + Major -> 1.0.0
1.0.0 + Major + -Preview -> 1.0.1-preview</code></pre>
<p>When Git tags exist, Nova uses commits since the latest tag. When Git-based inference is unavailable
because the project path is not inside a Git repository, Nova stops instead of silently presenting a
normal-looking patch result. Use <code>-OverrideWarning</code> or the CLI form <code>% nova bump
Expand Down
2 changes: 1 addition & 1 deletion project.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"ProjectName": "NovaModuleTools",
"Description": "NovaModuleTools is an enterprise-focused build tool for PowerShell module development, with a strong emphasis on structure, maintainability, and build for automated CI/CD pipelines.",
"Version": "3.4.1",
"Version": "3.4.2-preview",
"Preamble": [
"Set-StrictMode -Version Latest",
"$ErrorActionPreference = 'Stop'"
Expand Down
22 changes: 22 additions & 0 deletions src/private/release/GetNovaVersionUpdatePlan.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ function Get-NovaVersionPartForUpdatePlan {
[switch]$PreviewRelease
)

if (Test-NovaVersionShouldPreserveInitialStableReleaseTarget -CurrentVersion $CurrentVersion -PreviewRelease:$PreviewRelease) {
return Get-NovaVersionPartObject -CurrentVersion $CurrentVersion
}

if ($PreviewRelease) {
if (-not [string]::IsNullOrWhiteSpace($CurrentVersion.PreReleaseLabel)) {
return Get-NovaVersionPartObject -CurrentVersion $CurrentVersion
Expand All @@ -67,3 +71,21 @@ function Get-NovaVersionPartForUpdatePlan {

return Get-NovaVersionPartForLabel -CurrentVersion $CurrentVersion -Label $Label
}

function Test-NovaVersionShouldPreserveInitialStableReleaseTarget {
[CmdletBinding()]
param(
[Parameter(Mandatory)][semver]$CurrentVersion,
[switch]$PreviewRelease
)

if ($PreviewRelease) {
return $false
}

if (-not [string]::IsNullOrWhiteSpace($CurrentVersion.PreReleaseLabel)) {
return $false
}

return $CurrentVersion.Major -eq 1 -and $CurrentVersion.Minor -eq 0 -and $CurrentVersion.Patch -eq 0
}
34 changes: 34 additions & 0 deletions tests/private/release/GetNovaVersionUpdatePlan.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,45 @@ Describe 'Get-NovaVersionPartForUpdatePlan' {
}
}

Describe 'Test-NovaVersionShouldPreserveInitialStableReleaseTarget' {
It 'returns true for exact stable 1.0.0 without preview mode' {
Test-NovaVersionShouldPreserveInitialStableReleaseTarget -CurrentVersion ([semver]'1.0.0') | Should -BeTrue
}

It 'returns false when preview mode is requested' {
Test-NovaVersionShouldPreserveInitialStableReleaseTarget -CurrentVersion ([semver]'1.0.0') -PreviewRelease | Should -BeFalse
}

It 'returns false when the current version is already a prerelease' {
Test-NovaVersionShouldPreserveInitialStableReleaseTarget -CurrentVersion ([semver]'1.0.0-preview01') | Should -BeFalse
}
}

Describe 'Get-NovaVersionUpdatePlan' {
It 'returns a plan with project file and new version' {
$info = [pscustomobject]@{ProjectJSON='/project.json'; Version='1.2.3'}
$plan = Get-NovaVersionUpdatePlan -ProjectInfo $info -Label Patch
$plan.ProjectFile | Should -Be '/project.json'
$plan.NewVersion.ToString() | Should -Be '1.2.4'
}

It 'keeps exact stable 1.0.0 regardless of inferred release label' -ForEach @(
@{ Scenario = 'fix commits'; Label = 'Patch' }
@{ Scenario = 'feature commits'; Label = 'Minor' }
@{ Scenario = 'breaking commits'; Label = 'Major' }
) {
$info = [pscustomobject]@{ProjectJSON='/project.json'; Version='1.0.0'}

$plan = Get-NovaVersionUpdatePlan -ProjectInfo $info -Label $Label

$plan.NewVersion.ToString() | Should -Be '1.0.0' -Because "$Scenario should respect a manually selected initial stable release target"
}

It 'keeps preview mode on the next patch preview track for exact stable 1.0.0' {
$info = [pscustomobject]@{ProjectJSON='/project.json'; Version='1.0.0'}

$plan = Get-NovaVersionUpdatePlan -ProjectInfo $info -Label Major -PreviewRelease

$plan.NewVersion.ToString() | Should -Be '1.0.1-preview'
}
}
Loading