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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed

- Fixed `nova bump` and `Update-NovaModuleVersion` so nested project folders now reuse parent Git repository history for bump inference instead of silently falling back to `Patch`.
- Fixed `nova bump` and `Update-NovaModuleVersion` so non-git bump flows now stop with a clear override-warning requirement instead of silently presenting `Patch | Commits: 0` as if it were an inferred result.

### Security

Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,9 @@ 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`
- `Publish-NovaModule -ContinuousIntegration` restores the built module after publish completes
Expand Down
48 changes: 45 additions & 3 deletions docs/NovaModuleTools/en-US/Update-NovaModuleVersion.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Updates the project version in `project.json` based on git commit history.
### __AllParameterSets

```text
PS> Update-NovaModuleVersion [[-Path] <string>] [-Preview] [-ContinuousIntegration] [-WhatIf] [-Confirm] [<CommonParameters>]
PS> Update-NovaModuleVersion [[-Path] <string>] [-Preview] [-ContinuousIntegration] [-OverrideWarning] [-WhatIf] [-Confirm] [<CommonParameters>]
```

## DESCRIPTION
Expand Down Expand Up @@ -49,8 +49,10 @@ reports the detected `Major` label so you can see that the commit set contained
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.
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.

If the repository exists but has no commits yet, the command stops with: `Cannot bump version because the repository
has no commits yet. Create an initial commit first.`
Expand Down Expand Up @@ -186,6 +188,19 @@ CommitCount: 34
Shows how stable `0.y.z` bumps still warn that `1.0.0` must be set manually when the API becomes stable, while
breaking-change commits on that line continue to plan the next minor version instead of jumping straight to `1.0.0`.

### EXAMPLE 10

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

WARNING: Cannot infer the version bump label from Git history because no Git repository was found for this project path. Use -OverrideWarning to continue intentionally with a Patch fallback.

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

Shows how to opt in explicitly to the Patch fallback when a project lives outside a Git repository and Nova therefore
cannot infer the semantic label from commit history.

## PARAMETERS

### -Path
Expand Down Expand Up @@ -259,6 +274,30 @@ AcceptedValues: [ ]
HelpMessage: ''
```

### -OverrideWarning

Allow the version bump to continue with the explicit Patch fallback when Git-based inference is unavailable.

Use this only when you intentionally want to bump a project outside a Git repository, for example in example/template
flows where no commit history exists.

```yaml
Type: System.Management.Automation.SwitchParameter
DefaultValue: False
SupportsWildcards: false
Aliases: [ ]
ParameterSets:
- Name: (All)
Position: Named
IsRequired: false
ValueFromPipeline: false
ValueFromPipelineByPropertyName: false
ValueFromRemainingArguments: false
DontShow: false
AcceptedValues: [ ]
HelpMessage: ''
```

### CommonParameters

This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable,
Expand Down Expand Up @@ -291,6 +330,9 @@ reflect the new version.
When `-ContinuousIntegration` is used with a real update, the command re-activates the built `dist/` module first. When
combined with `-WhatIf`, Nova still previews the bump without changing the loaded module state.

When Git-based inference is unavailable, `Update-NovaModuleVersion` now requires `-OverrideWarning` before it continues
with the intentional Patch fallback.

## RELATED LINKS

- https://github.com/stiwicourage/NovaModuleTools/blob/main/docs/NovaModuleTools/en-US/Get-NovaProjectInfo.md
Expand Down
13 changes: 9 additions & 4 deletions docs/commands.html
Original file line number Diff line number Diff line change
Expand Up @@ -476,10 +476,13 @@ <h3><code>Update-NovaModuleVersion</code> / <code>% nova bump</code></h3>
<ul class="plain-list">
<li><strong>Best for:</strong> Git-driven semantic version updates</li>
<li><strong>Key parameters:</strong> <code>-Path</code>, <code>-Preview</code>,
<code>-ContinuousIntegration</code>, or the CLI form <code>--preview</code> /
<code>-p</code> and <code>--continuous-integration</code> / <code>-i</code></li>
<li><strong>Notable behavior:</strong> falls back to a patch bump when the folder is not a
Git repository, but throws when the repository exists and has no commits yet
<code>-ContinuousIntegration</code>, <code>-OverrideWarning</code>, or the CLI form
<code>--preview</code> / <code>-p</code>, <code>--continuous-integration</code> /
<code>-i</code>, and <code>--override-warning</code> / <code>-o</code></li>
<li><strong>Notable behavior:</strong> stops when Git-based inference is unavailable, unless
you explicitly opt in to the Patch fallback with <code>-OverrideWarning</code> /
<code>--override-warning</code> / <code>-o</code>; it still throws when the repository
exists and has no commits yet
</li>
<li><strong>Major-zero rule:</strong> stable <code>0.y.z</code> projects keep
breaking-change
Expand All @@ -504,10 +507,12 @@ <h3><code>Update-NovaModuleVersion</code> / <code>% nova bump</code></h3>
</div>
<div class="surface-example__surface" data-command-surface="powershell">
<pre><code>PS&gt; Update-NovaModuleVersion -Preview -WhatIf
PS&gt; Update-NovaModuleVersion -Path ./src/resources/example -OverrideWarning -WhatIf
PS&gt; Update-NovaModuleVersion -ContinuousIntegration</code></pre>
</div>
<div class="surface-example__surface" data-command-surface="command-line" hidden>
<pre><code>% nova bump --preview --what-if
% nova bump --override-warning --what-if
% nova bump --continuous-integration
% nova bump --preview --confirm</code></pre>
</div>
Expand Down
11 changes: 8 additions & 3 deletions docs/versioning-and-updates.html
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,12 @@ <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>When Git tags exist, Nova uses commits since the latest tag. When the folder is not a Git repository,
Nova falls back to a patch bump. When the repository exists but has no commits yet, Nova stops with
a clear error.</p>
<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
--override-warning</code> / <code>% nova bump -o</code> only when you intentionally want that
Patch fallback for an example/template flow outside Git. When the repository exists but has no
commits yet, Nova still stops with a clear error.</p>
<p>Nova treats prerelease versions as previews of a specific semantic version target. That means a bump
does not blindly carry prerelease labels such as <code>preview7</code> into the next major, minor,
or
Expand Down Expand Up @@ -215,11 +218,13 @@ <h3>How Nova chooses the bump label</h3>
<div class="surface-example__surface" data-command-surface="powershell">
<pre><code>PS&gt; Update-NovaModuleVersion -WhatIf
PS&gt; Update-NovaModuleVersion -Preview -WhatIf
PS&gt; Update-NovaModuleVersion -Path ./src/resources/example -OverrideWarning -WhatIf
PS&gt; Update-NovaModuleVersion -ContinuousIntegration</code></pre>
</div>
<div class="surface-example__surface" data-command-surface="command-line" hidden>
<pre><code>% nova bump --what-if
% nova bump --preview --what-if
% nova bump --override-warning --what-if
% nova bump --continuous-integration
% nova bump --confirm</code></pre>
</div>
Expand Down
2 changes: 2 additions & 0 deletions src/private/cli/ConvertFromNovaBumpCliArgument.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,7 @@ function ConvertFrom-NovaBumpCliArgument {
'-p' = 'Preview'
'--continuous-integration' = 'ContinuousIntegration'
'-i' = 'ContinuousIntegration'
'--override-warning' = 'OverrideWarning'
'-o' = 'OverrideWarning'
}
}
1 change: 1 addition & 0 deletions src/private/cli/GetNovaCliArgumentRoutingState.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ function Get-NovaCliLegacyOptionReplacement {
'-installed' = "'--installed' or '-i'"
'-local' = "'--local' or '-l'"
'-moduledirectorypath' = "'--path' or '-p'"
'-overridewarning' = "'--override-warning' or '-o'"
'-packagepath' = "'--path' or '-p'"
'-packagetype' = "'--type' or '-t'"
'-path' = "'--path' or '-p'"
Expand Down
38 changes: 37 additions & 1 deletion src/private/release/GetNovaVersionUpdateWorkflowContext.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,54 @@ function Get-NovaVersionUpdateWorkflowContext {
param(
[Parameter(Mandatory)][string]$ProjectRoot,
[switch]$PreviewRelease,
[switch]$ContinuousIntegrationRequested
[switch]$ContinuousIntegrationRequested,
[switch]$OverrideWarningRequested
)

$projectInfo = Get-NovaProjectInfo -Path $ProjectRoot
$commitMessages = @(Get-GitCommitMessageForVersionBump -ProjectRoot $ProjectRoot)
Assert-NovaVersionBumpInferenceAvailability -ProjectRoot $ProjectRoot -CommitMessages $commitMessages -OverrideWarningRequested:$OverrideWarningRequested
$label = Get-NovaVersionLabelForBump -ProjectRoot $ProjectRoot -CommitMessages $commitMessages -ContinuousIntegrationRequested:$ContinuousIntegrationRequested
$labelResolution = Get-NovaVersionUpdateLabelResolution -ProjectInfo $projectInfo -Label $label -PreviewRelease:$PreviewRelease
$versionUpdatePlan = Get-NovaVersionUpdatePlan -ProjectInfo $projectInfo -Label $labelResolution.EffectiveLabel -PreviewRelease:$PreviewRelease

return Get-NovaVersionUpdateWorkflowContextObject -ProjectRoot $ProjectRoot -ProjectInfo $projectInfo -CommitMessages $commitMessages -Label $label -EffectiveLabel $labelResolution.EffectiveLabel -AdvisoryMessage $labelResolution.AdvisoryMessage -VersionUpdatePlan $versionUpdatePlan -PreviewRelease:$PreviewRelease -ContinuousIntegrationRequested:$ContinuousIntegrationRequested
}

function Assert-NovaVersionBumpInferenceAvailability {
[CmdletBinding()]
param(
[Parameter(Mandatory)][string]$ProjectRoot,
[AllowEmptyCollection()][string[]]$CommitMessages = @(),
[switch]$OverrideWarningRequested
)

if ($CommitMessages.Count -gt 0) {
return
}

if (Test-GitRepositoryIsAvailable -ProjectRoot $ProjectRoot) {
return
}

$message = Get-NovaVersionBumpInferenceUnavailableMessage
Write-Warning $message

if ($OverrideWarningRequested) {
Write-Verbose 'Continuing version bump because OverrideWarning was specified and Git-based bump inference is unavailable.'
return
}

Stop-NovaOperation -Message $message -ErrorId 'Nova.Workflow.VersionBumpInferenceUnavailable' -Category InvalidOperation -TargetObject $ProjectRoot
}

function Get-NovaVersionBumpInferenceUnavailableMessage {
[CmdletBinding()]
param()

return 'Cannot infer the version bump label from Git history because no Git repository was found for this project path. Use -OverrideWarning / --override-warning / -o to continue intentionally with a Patch fallback, for example in example or template flows.'
}

function Get-NovaVersionUpdateLabelResolution {
[CmdletBinding()]
param(
Expand Down
6 changes: 3 additions & 3 deletions src/public/UpdateNovaModuleVersion.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ function Update-NovaModuleVersion {
param(
[string]$Path = (Get-Location).Path,
[switch]$Preview,
[switch]$ContinuousIntegration
[switch]$ContinuousIntegration,
[switch]$OverrideWarning
)

$projectRoot = (Resolve-Path -LiteralPath $Path).Path
Expand All @@ -12,7 +13,7 @@ function Update-NovaModuleVersion {
return $ciActivation.Result
}

$workflowContext = Get-NovaVersionUpdateWorkflowContext -ProjectRoot $projectRoot -PreviewRelease:$Preview -ContinuousIntegrationRequested:$ContinuousIntegration
$workflowContext = Get-NovaVersionUpdateWorkflowContext -ProjectRoot $projectRoot -PreviewRelease:$Preview -ContinuousIntegrationRequested:$ContinuousIntegration -OverrideWarningRequested:$OverrideWarning
$shouldRun = $PSCmdlet.ShouldProcess($workflowContext.Target, $workflowContext.Action)
$result = Invoke-NovaVersionUpdateWorkflow -WorkflowContext $workflowContext -ShouldRun:$shouldRun -WhatIfEnabled:$WhatIfPreference
if ($null -eq $result) {
Expand All @@ -23,4 +24,3 @@ function Update-NovaModuleVersion {

return $result
}

11 changes: 11 additions & 0 deletions src/resources/cli/help/bump.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
'When the current stable version is 0.y.z, Nova keeps breaking-change bumps on the initial-development line and plans the next minor version instead of jumping to 1.0.0.',
'Set 1.0.0 manually once the software is stable. After that, nova bump can increment major versions normally.',
'Use --preview when you want an explicit prerelease iteration instead of the next stable semantic version.',
'When Git-based bump inference is unavailable, nova bump stops unless you opt in to the Patch fallback with --override-warning.',
'For more information, documentation, and examples, visit:',
'https://www.novamoduletools.com/versioning-and-updates.html#bump'
)
Expand Down Expand Up @@ -40,6 +41,12 @@
Long = '--continuous-integration'
Placeholder = ''
Description = 'Re-import the built dist module before the version bump workflow starts so later CI steps keep using the correct built module state.'
},
@{
Short = '-o'
Long = '--override-warning'
Placeholder = ''
Description = 'Allow an intentional Patch fallback when Git-based bump inference is unavailable, for example in example or template flows outside a Git repository.'
}
)
Examples = @(
Expand All @@ -58,6 +65,10 @@
@{
Command = 'nova bump --continuous-integration --what-if'
Description = 'Preview the next version by using the CI-safe routed bump entrypoint without changing project.json.'
},
@{
Command = 'nova bump --override-warning --what-if'
Description = 'Preview the explicit Patch fallback when Git-based bump inference is unavailable outside a Git repository.'
}
)
}
2 changes: 2 additions & 0 deletions tests/CoverageGaps.Cli.TestSupport.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ function Get-TestNovaCliRoutedParserCaseList {
@{Arguments = @('-p'); Property = 'Preview'}
@{Arguments = @('--continuous-integration'); Property = 'ContinuousIntegration'}
@{Arguments = @('-i'); Property = 'ContinuousIntegration'}
@{Arguments = @('--override-warning'); Property = 'OverrideWarning'}
@{Arguments = @('-o'); Property = 'OverrideWarning'}
)
}
@{
Expand Down
36 changes: 36 additions & 0 deletions tests/CoverageGaps.ReleaseInternals.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,42 @@ Describe 'Coverage gaps for release and git internals' {
}
}

It 'Assert-NovaVersionBumpInferenceAvailability throws a clear error when Git-based bump inference is unavailable' {
InModuleScope $script:moduleName {
$projectRoot = Join-Path $TestDrive 'no-git-project-for-override-guard'
New-Item -ItemType Directory -Path $projectRoot -Force | Out-Null

$warningMessages = @()
$thrown = $null
try {
Assert-NovaVersionBumpInferenceAvailability -ProjectRoot $projectRoot -CommitMessages @() -WarningVariable warningMessages
}
catch {
$thrown = $_
}

$thrown | Should -Not -BeNullOrEmpty
$thrown.Exception.Message | Should -Be 'Cannot infer the version bump label from Git history because no Git repository was found for this project path. Use -OverrideWarning / --override-warning / -o to continue intentionally with a Patch fallback, for example in example or template flows.'
$thrown.FullyQualifiedErrorId | Should -Be 'Nova.Workflow.VersionBumpInferenceUnavailable'
$thrown.CategoryInfo.Category | Should -Be ([System.Management.Automation.ErrorCategory]::InvalidOperation)
$thrown.TargetObject | Should -Be $projectRoot
($warningMessages -join [Environment]::NewLine) | Should -Match '-OverrideWarning / --override-warning / -o'
}
}

It 'Assert-NovaVersionBumpInferenceAvailability warns but continues when OverrideWarningRequested is set' {
InModuleScope $script:moduleName {
$projectRoot = Join-Path $TestDrive 'no-git-project-for-override-continue'
New-Item -ItemType Directory -Path $projectRoot -Force | Out-Null

$records = @(& {Assert-NovaVersionBumpInferenceAvailability -ProjectRoot $projectRoot -CommitMessages @() -OverrideWarningRequested} 3>&1)

{ $null = $records } | Should -Not -Throw
@($records | Where-Object {$_ -is [System.Management.Automation.WarningRecord]}).Count | Should -Be 1
(@($records | Where-Object {$_ -is [System.Management.Automation.WarningRecord]} | ForEach-Object Message) -join [Environment]::NewLine) | Should -Match 'Cannot infer the version bump label from Git history'
}
}

It 'Get-GitCommitMessageForVersionBump uses the shared git adapter to resolve tagged commit history' {
InModuleScope $script:moduleName {
$projectRoot = Join-Path $TestDrive 'mocked-git-history'
Expand Down
Loading
Loading