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
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,13 @@ Keep stable `Update-NovaModuleVersion` / `% nova bump` releases on the SemVer ma
minor version instead of auto-jumping to `1.0.0`.
- Stable `0.y.z` bump results now print one warning about manually setting `1.0.0` once the software is stable,
while breaking-change bumps still report the detected `Major` label.
- `-Preview` behavior is unchanged.
- Make `Update-NovaModuleVersion -Preview` / `% nova bump --preview` enter the preview track deterministically from
stable versions.
- Stable versions now always become the next patch preview, for example `0.2.0 -> 0.2.1-preview`, instead of
reusing semantic history inference for the semantic core.
- Existing prerelease versions still keep their current semantic core and continue the prerelease sequence.
- Running the bump without `-Preview` still finalizes or advances prerelease versions by Nova's normal semantic
rules.

### Deprecated

Expand Down
16 changes: 9 additions & 7 deletions docs/NovaModuleTools/en-US/Update-NovaModuleVersion.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ project repository, chooses a semantic version bump label, calculates the next s
version back to `project.json`.

Use `-Preview` when you want an explicit prerelease-continuation bump instead of the default prerelease finalization
behavior. In preview mode, stable versions first calculate the normal semantic bump target and then append
`-preview`. Existing prerelease versions keep the same semantic core and preserve the current prerelease stem while
behavior. In preview mode, stable versions always enter the next patch preview track by incrementing the patch version
and appending `-preview`. Existing prerelease versions keep the same semantic core and preserve the current prerelease
stem while
appending or incrementing trailing digits. Any bare prerelease label now starts at `01` for predictable ordering,
for example `preview -> preview01`, `preview09 -> preview10`, `rc -> rc01`, `rc1 -> rc2`, and
`SNAPSHOT -> SNAPSHOT01`.
Expand All @@ -45,7 +46,8 @@ The release label is inferred from the commit set:
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. `-Preview` behavior stays unchanged.
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 Git tags exist, only commits since the latest tag are considered. If the folder is not a Git repository, the
command falls back to a patch bump.
Expand Down Expand Up @@ -120,13 +122,13 @@ PS> Update-NovaModuleVersion -Preview -WhatIf
What if: Performing the operation "Update module version using Minor release label" on target "project.json".

PreviousVersion: 1.5.3
NewVersion: 1.6.0-preview
NewVersion: 1.5.4-preview
Label: Minor
CommitCount: 12
```

Shows how `-Preview` keeps the normal bump label selection but emits a preview target when the current version is
stable.
Shows how `-Preview` keeps the detected semantic label for reporting but deterministically enters the next patch preview
track when the current version is stable.

### EXAMPLE 6

Expand Down Expand Up @@ -211,7 +213,7 @@ HelpMessage: ''

Opt into preview bump mode.

When the current version is stable, Nova calculates the normal semantic target and appends `-preview`. When the current
When the current version is stable, Nova increments the patch version and appends `-preview`. When the current
version already has any prerelease label, Nova keeps the same semantic core version and increments the current
prerelease suffix instead of finalizing or advancing to another release line. Any prerelease stem without a trailing
number starts at `01`, while labels that already include a number simply increment that number.
Expand Down
8 changes: 6 additions & 2 deletions src/private/release/GetNovaVersionUpdatePlan.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,12 @@ function Get-NovaVersionPartForUpdatePlan {
[switch]$PreviewRelease
)

if ($PreviewRelease -and -not [string]::IsNullOrWhiteSpace($CurrentVersion.PreReleaseLabel)) {
return Get-NovaVersionPartObject -CurrentVersion $CurrentVersion
if ($PreviewRelease) {
if (-not [string]::IsNullOrWhiteSpace($CurrentVersion.PreReleaseLabel)) {
return Get-NovaVersionPartObject -CurrentVersion $CurrentVersion
}

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

return Get-NovaVersionPartForLabel -CurrentVersion $CurrentVersion -Label $Label
Expand Down
18 changes: 18 additions & 0 deletions src/private/release/GetNovaVersionUpdateWorkflowContext.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ function Get-NovaVersionUpdateLabelResolution {
$effectiveLabel = $Label
$advisoryMessage = $null
$currentVersion = Get-NovaCurrentVersionForUpdatePlan -ProjectInfo $ProjectInfo
if (Test-NovaVersionUpdateUsesPreviewPatchFallback -CurrentVersion $currentVersion -PreviewRelease:$PreviewRelease) {
$effectiveLabel = 'Patch'
}

if (Test-NovaVersionUpdateUsesInitialDevelopmentAdvisory -CurrentVersion $currentVersion -PreviewRelease:$PreviewRelease) {
$advisoryMessage = Get-NovaInitialDevelopmentVersioningMessage
}
Expand All @@ -40,6 +44,20 @@ function Get-NovaVersionUpdateLabelResolution {
}
}

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

if (-not $PreviewRelease) {
return $false
}

return [string]::IsNullOrWhiteSpace($CurrentVersion.PreReleaseLabel)
}

function Test-NovaVersionUpdateUsesInitialDevelopmentAdvisory {
[CmdletBinding()]
param(
Expand Down
28 changes: 14 additions & 14 deletions tests/CoverageGaps.ReleaseInternals.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,9 @@ Describe 'Coverage gaps for release and git internals' {
}
}

It 'Get-NovaVersionUpdatePlan appends a preview label to the normal bump target when preview mode starts from stable' -ForEach @(
@{CurrentVersion = '1.5.3'; Label = 'Major'; ExpectedVersion = '2.0.0-preview'}
@{CurrentVersion = '1.5.3'; Label = 'Minor'; ExpectedVersion = '1.6.0-preview'}
It 'Get-NovaVersionUpdatePlan enters the next patch preview track from stable versions regardless of the inferred label' -ForEach @(
@{CurrentVersion = '1.5.3'; Label = 'Major'; ExpectedVersion = '1.5.4-preview'}
@{CurrentVersion = '1.5.3'; Label = 'Minor'; ExpectedVersion = '1.5.4-preview'}
@{CurrentVersion = '1.5.3'; Label = 'Patch'; ExpectedVersion = '1.5.4-preview'}
) {
InModuleScope $script:moduleName -Parameters @{TestCase = $_} {
Expand Down Expand Up @@ -170,14 +170,14 @@ Describe 'Coverage gaps for release and git internals' {
ExpectedPlanLabel = 'Minor'
}
@{
Name = 'preview mode remains unchanged'
Name = 'preview mode enters the next patch preview from stable major-zero versions'
CurrentVersion = '0.1.0'
Label = 'Major'
PreviewRelease = $true
PlannedVersion = '1.0.0-preview'
ExpectedEffectiveLabel = 'Major'
PlannedVersion = '0.1.1-preview'
ExpectedEffectiveLabel = 'Patch'
ExpectedAdvisoryPattern = $null
ExpectedPlanLabel = 'Major'
ExpectedPlanLabel = 'Patch'
}
) {
InModuleScope $script:moduleName -Parameters @{TestCase = $_} {
Expand Down Expand Up @@ -284,9 +284,9 @@ Describe 'Coverage gaps for release and git internals' {
$updatedProject = Get-Content -LiteralPath $projectJsonPath -Raw | ConvertFrom-Json

$result.PreviousVersion | Should -Be '1.2.3'
$result.NewVersion | Should -Be '1.3.0-preview'
$result.NewVersion | Should -Be '1.2.4-preview'
$result.Applied | Should -BeTrue
$updatedProject.Version | Should -Be '1.3.0-preview'
$updatedProject.Version | Should -Be '1.2.4-preview'
$updatedProject.Package.Auth.HeaderName | Should -Be 'Authorization'
$updatedProject.Package.Repositories.Count | Should -Be 1
($updatedProject.Package.Repositories[0] -is [string]) | Should -BeFalse
Expand All @@ -301,7 +301,7 @@ Describe 'Coverage gaps for release and git internals' {
Mock Get-NovaVersionUpdatePlan {
[pscustomobject]@{
ProjectFile = '/tmp/project.json'
NewVersion = [semver]'1.3.0-preview'
NewVersion = [semver]'1.2.4-preview'
}
}
Mock Read-ProjectJsonData {
Expand All @@ -322,12 +322,12 @@ Describe 'Coverage gaps for release and git internals' {

$result.ProjectFile | Should -Be '/tmp/project.json'
$result.PreviousVersion | Should -Be '1.2.3'
$result.NewVersion | Should -Be '1.3.0-preview'
$result.NewVersion | Should -Be '1.2.4-preview'
$result.Applied | Should -BeTrue
Assert-MockCalled Read-ProjectJsonData -Times 1 -ParameterFilter {$ProjectJsonPath -eq '/tmp/project.json'}
Assert-MockCalled Write-ProjectJsonData -Times 1 -ParameterFilter {
$ProjectJsonPath -eq '/tmp/project.json' -and
$Data.Version -eq '1.3.0-preview' -and
$Data.Version -eq '1.2.4-preview' -and
$Data.Package.Repositories[0].Name -eq 'staging'
}
}
Expand All @@ -338,7 +338,7 @@ Describe 'Coverage gaps for release and git internals' {
Mock Get-NovaVersionUpdatePlan {
[pscustomobject]@{
ProjectFile = '/tmp/project.json'
NewVersion = [semver]'1.3.0-preview'
NewVersion = [semver]'1.2.4-preview'
}
}
Mock Read-ProjectJsonData {
Expand All @@ -352,7 +352,7 @@ Describe 'Coverage gaps for release and git internals' {

$result.ProjectFile | Should -Be '/tmp/project.json'
$result.PreviousVersion | Should -Be '1.2.3'
$result.NewVersion | Should -Be '1.3.0-preview'
$result.NewVersion | Should -Be '1.2.4-preview'
$result.Applied | Should -BeFalse
Assert-MockCalled Read-ProjectJsonData -Times 1 -ParameterFilter {$ProjectJsonPath -eq '/tmp/project.json'}
Assert-MockCalled Write-ProjectJsonData -Times 0
Expand Down
45 changes: 38 additions & 7 deletions tests/NovaCommandModel.BumpAndCli.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,36 @@ Describe 'Nova command model - bump and CLI confirmation behavior' {
}
}

It 'Get-NovaVersionUpdateWorkflowContext keeps the detected label but enters the next patch preview track from a stable version' {
InModuleScope $script:moduleName {
Mock Get-NovaProjectInfo {
[pscustomobject]@{
ProjectName = 'NovaModuleTools'
Version = '1.5.3'
ProjectJSON = '/tmp/project.json'
}
}
Mock Get-GitCommitMessageForVersionBump {@('feat: add change')}
Mock Get-NovaVersionLabelForBump {'Minor'}
Mock Get-NovaVersionUpdatePlan {
[pscustomobject]@{
NewVersion = [semver]'1.5.4-preview'
}
}

$result = Get-NovaVersionUpdateWorkflowContext -ProjectRoot '/tmp/project' -PreviewRelease

$result.Label | Should -Be 'Minor'
$result.EffectiveLabel | Should -Be 'Patch'
$result.NewVersion | Should -Be '1.5.4-preview'
Assert-MockCalled Get-NovaVersionUpdatePlan -Times 1 -ParameterFilter {
$ProjectInfo.ProjectName -eq 'NovaModuleTools' -and
$Label -eq 'Patch' -and
$PreviewRelease
}
}
}

It 'Get-NovaVersionUpdateWorkflowContext carries ContinuousIntegrationRequested when requested' {
InModuleScope $script:moduleName {
Mock Get-NovaProjectInfo {
Expand Down Expand Up @@ -423,11 +453,11 @@ Describe 'Nova command model - bump and CLI confirmation behavior' {
}

It 'Update-NovaModuleVersion -WhatIf returns the expected next version without persisting it when <Name>' -ForEach @(
@{Name = 'the default bump flow is used'; CurrentVersion = '1.0.0'; CommitMessages = @('feat: add change'); Label = 'Minor'; NewVersion = '1.1.0'; Preview = $false}
@{Name = 'preview mode starts from a stable version'; CurrentVersion = '1.5.3'; CommitMessages = @('feat: add change'); Label = 'Minor'; NewVersion = '1.6.0-preview'; Preview = $true}
@{Name = 'preview mode zero-pads compact preview labels for gallery ordering'; CurrentVersion = '1.5.3-preview'; CommitMessages = @('fix: patch bug'); Label = 'Patch'; NewVersion = '1.5.3-preview01'; Preview = $true}
@{Name = 'preview mode starts any bare prerelease stem at 01'; CurrentVersion = '1.5.3-SNAPSHOT'; CommitMessages = @('feat!: breaking api'); Label = 'Major'; NewVersion = '1.5.3-SNAPSHOT01'; Preview = $true}
@{Name = 'preview mode continues an existing prerelease version'; CurrentVersion = '1.5.3-rc1'; CommitMessages = @('feat!: breaking api'); Label = 'Major'; NewVersion = '1.5.3-rc2'; Preview = $true}
@{Name = 'the default bump flow is used'; CurrentVersion = '1.0.0'; CommitMessages = @('feat: add change'); Label = 'Minor'; EffectiveLabel = 'Minor'; NewVersion = '1.1.0'; Preview = $false}
@{Name = 'preview mode enters the next patch preview track from a stable version'; CurrentVersion = '1.5.3'; CommitMessages = @('feat: add change'); Label = 'Minor'; EffectiveLabel = 'Patch'; NewVersion = '1.5.4-preview'; Preview = $true}
@{Name = 'preview mode zero-pads compact preview labels for gallery ordering'; CurrentVersion = '1.5.3-preview'; CommitMessages = @('fix: patch bug'); Label = 'Patch'; EffectiveLabel = 'Patch'; NewVersion = '1.5.3-preview01'; Preview = $true}
@{Name = 'preview mode starts any bare prerelease stem at 01'; CurrentVersion = '1.5.3-SNAPSHOT'; CommitMessages = @('feat!: breaking api'); Label = 'Major'; EffectiveLabel = 'Major'; NewVersion = '1.5.3-SNAPSHOT01'; Preview = $true}
@{Name = 'preview mode continues an existing prerelease version'; CurrentVersion = '1.5.3-rc1'; CommitMessages = @('feat!: breaking api'); Label = 'Major'; EffectiveLabel = 'Major'; NewVersion = '1.5.3-rc2'; Preview = $true}
) {
InModuleScope $script:moduleName -Parameters @{TestCase = $_} {
param($TestCase)
Expand Down Expand Up @@ -459,9 +489,10 @@ Describe 'Nova command model - bump and CLI confirmation behavior' {
$result.PreviousVersion | Should -Be $TestCase.CurrentVersion
$result.NewVersion | Should -Be $TestCase.NewVersion
$result.Label | Should -Be $TestCase.Label
Assert-MockCalled Get-NovaVersionUpdatePlan -Times 1 -ParameterFilter {$Label -eq $TestCase.Label}
$result.EffectiveLabel | Should -Be $TestCase.EffectiveLabel
Assert-MockCalled Get-NovaVersionUpdatePlan -Times 1 -ParameterFilter {$Label -eq $TestCase.EffectiveLabel}
Assert-MockCalled Get-NovaVersionUpdatePlan -Times 1 -ParameterFilter {
$Label -eq $TestCase.Label -and
$Label -eq $TestCase.EffectiveLabel -and
([bool]$PreviewRelease) -eq ([bool]$TestCase.Preview)
}

Expand Down
2 changes: 1 addition & 1 deletion tests/NovaCommandModel.TestSupport/CliProjectSupport.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ function Assert-TestNovaCliWhatIfResultMap {

$ResultMap.Bump.Text | Should -Match 'Version plan: 0\.0\.1 -> 0\.1\.0 \| Label: Minor \| Commits: 1'
$ResultMap.BumpCi.Text | Should -Match 'Version plan: 0\.0\.1 -> 0\.1\.0 \| Label: Minor \| Commits: 1'
$ResultMap.PreviewBump.Text | Should -Match 'Version plan: 0\.0\.1 -> 0\.1\.0-preview \| Label: Minor \| Commits: 1'
$ResultMap.PreviewBump.Text | Should -Match 'Version plan: 0\.0\.1 -> 0\.0\.2-preview \| Label: Minor \| Commits: 1'
$ResultMap.Bump.Text | Should -Not -Match 'Version bumped to :'
$ResultMap.PreviewBump.Text | Should -Not -Match 'Version bumped to :'
((Get-Content -LiteralPath $ProjectJsonPath -Raw | ConvertFrom-Json).Version) | Should -Be '0.0.1'
Expand Down
Loading