Skip to content

Commit 849d3bc

Browse files
committed
#215 feat: enhance New-NovaModulePackage with progress reporting and next-step guidance
refactor(New-NovaModulePackage): align with terminal-ux-design principles Fixes #224
1 parent 491fa54 commit 849d3bc

6 files changed

Lines changed: 202 additions & 11 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
2626
- `Invoke-NovaBuild` now shows progress for the main build phases, ends with the output module directory plus the next suggested validation step, and explains the refreshed session when `-ContinuousIntegration` reloads the built module.
2727
- `Invoke-NovaCli` now treats blank command input as root help, reports unknown commands with clearer recovery guidance, and ships a dedicated PlatyPS help topic for the PowerShell wrapper surface.
2828
- `Invoke-NovaRelease` now shows progress for the main release phases, ends with the publish target plus a next-step hint, and uses a plan summary instead of a success summary when `-WhatIf` previews the release.
29+
- `New-NovaModulePackage` now shows progress for build validation and artifact creation, ends with the package target plus the next suggested deployment step, and uses a package-plan summary in `-WhatIf` mode.
2930

3031
### Deprecated
3132

RELEASE_NOTE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ This file summarizes the release notes for NovaModuleTools. **UNRELEASED** chang
2222
- `Invoke-NovaBuild` now shows progress for the main build phases, ends with the output module directory plus the next suggested validation step, and explains the refreshed session when `-ContinuousIntegration` reloads the built module.
2323
- `Invoke-NovaCli` now treats blank command input as root help, reports unknown commands with clearer recovery guidance, and ships a dedicated help topic for the PowerShell wrapper surface.
2424
- `Invoke-NovaRelease` now shows progress for the main release phases, ends with the publish target plus a next-step hint, and uses a plan summary instead of a success summary when `-WhatIf` previews the release.
25+
- `New-NovaModulePackage` now shows progress for build validation and artifact creation, ends with the package target plus the next suggested deployment step, and uses a package-plan summary in `-WhatIf` mode.
2526

2627
### Deprecated
2728

docs/NovaModuleTools/en-US/New-NovaModulePackage.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ Use `-OverrideWarning` only when you intentionally want the nested build to cont
3535

3636
The package is written to `artifacts/packages/` by default. You can override generic package metadata through the optional `Package` section in `project.json`.
3737

38+
During a packaging run, Nova shows progress for the build-validation phase and the artifact-creation phase. When packaging completes, Nova prints the package target together with the next suggested step. In `-WhatIf` mode, Nova ends with a package-plan summary instead of a package-created summary.
39+
3840
Use this `project.json` shape when you want to control package types and the package output directory:
3941

4042
```json
@@ -275,6 +277,8 @@ When `-SkipTests` is used, only `Test-NovaBuild` is skipped. Build still runs.
275277

276278
Files under `src/public` are expected to contain exactly one top-level function each. `-OverrideWarning` bypasses that guard only for the current packaging run.
277279

280+
Use `Ctrl+C` if you need to stop a running packaging workflow before the package artifacts are created.
281+
278282
## RELATED LINKS
279283

280284
- [Invoke-NovaBuild](./Invoke-NovaBuild.md)

src/private/package/InvokeNovaPackageWorkflow.ps1

Lines changed: 133 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,140 @@ function Invoke-NovaPackageWorkflow {
55
[switch]$ShouldRun
66
)
77

8-
Invoke-NovaBuildValidation -WorkflowContext $WorkflowContext
8+
$whatIfEnabled = Test-NovaPackageWorkflowWhatIfEnabled -WorkflowContext $WorkflowContext
9+
$progressActivity = 'Creating Nova package artifacts'
910

10-
if (-not $ShouldRun) {
11-
return
11+
try {
12+
Invoke-NovaPackageWorkflowStep -Activity $progressActivity -Status (Get-NovaPackageValidationStatus -WorkflowContext $WorkflowContext) -PercentComplete 30 -Action {
13+
Invoke-NovaBuildValidation -WorkflowContext $WorkflowContext
14+
}
15+
16+
if (-not $ShouldRun) {
17+
if ($whatIfEnabled) {
18+
Write-NovaPackageWorkflowResult -WorkflowContext $WorkflowContext -WhatIfEnabled
19+
}
20+
21+
return
22+
}
23+
24+
$artifacts = Invoke-NovaPackageWorkflowStep -Activity $progressActivity -Status 'Creating package artifacts' -PercentComplete 85 -Action {
25+
Invoke-NovaPackageArtifactCreation -WorkflowContext $WorkflowContext
26+
}
27+
} finally {
28+
Write-Progress -Activity $progressActivity -Completed
29+
}
30+
31+
Write-NovaPackageWorkflowResult -WorkflowContext $WorkflowContext -Artifacts $artifacts
32+
return $artifacts
33+
}
34+
35+
function Invoke-NovaPackageWorkflowStep {
36+
[CmdletBinding()]
37+
param(
38+
[Parameter(Mandatory)][string]$Activity,
39+
[Parameter(Mandatory)][string]$Status,
40+
[Parameter(Mandatory)][int]$PercentComplete,
41+
[Parameter(Mandatory)][scriptblock]$Action
42+
)
43+
44+
Write-Progress -Activity $Activity -Status $Status -PercentComplete $PercentComplete
45+
& $Action
46+
}
47+
48+
function Test-NovaPackageWorkflowWhatIfEnabled {
49+
[CmdletBinding()]
50+
param(
51+
[Parameter(Mandatory)][pscustomobject]$WorkflowContext
52+
)
53+
54+
return ($WorkflowContext.WorkflowParams.ContainsKey('WhatIf') -and $WorkflowContext.WorkflowParams.WhatIf)
55+
}
56+
57+
function Get-NovaPackageValidationStatus {
58+
[CmdletBinding()]
59+
param(
60+
[Parameter(Mandatory)][pscustomobject]$WorkflowContext
61+
)
62+
63+
if ($WorkflowContext.SkipTestsRequested) {
64+
return 'Building package input with tests skipped'
1265
}
1366

14-
return Invoke-NovaPackageArtifactCreation -WorkflowContext $WorkflowContext
67+
return 'Building and testing package input'
68+
}
69+
70+
function Write-NovaPackageWorkflowResult {
71+
[CmdletBinding()]
72+
param(
73+
[Parameter(Mandatory)][pscustomobject]$WorkflowContext,
74+
[AllowNull()][AllowEmptyCollection()][object[]]$Artifacts = @(),
75+
[switch]$WhatIfEnabled
76+
)
77+
78+
$resolvedArtifacts = @($Artifacts)
79+
$statusMessage = Get-NovaPackageWorkflowStatusMessage -WorkflowContext $WorkflowContext -ArtifactCount $resolvedArtifacts.Count -WhatIfEnabled:$WhatIfEnabled
80+
Write-Message $statusMessage -color Green
81+
Write-Message "Package target: $( Get-NovaPackageWorkflowResultTarget -WorkflowContext $WorkflowContext -Artifacts $resolvedArtifacts -WhatIfEnabled:$WhatIfEnabled )"
82+
83+
foreach ($line in (Get-NovaPackageWorkflowNextStepLine -WhatIfEnabled:$WhatIfEnabled)) {
84+
Write-Message $line
85+
}
86+
}
87+
88+
function Get-NovaPackageWorkflowStatusMessage {
89+
[CmdletBinding()]
90+
param(
91+
[Parameter(Mandatory)][pscustomobject]$WorkflowContext,
92+
[Parameter(Mandatory)][int]$ArtifactCount,
93+
[switch]$WhatIfEnabled
94+
)
95+
96+
if ($WhatIfEnabled) {
97+
return "Package plan ready for $( $WorkflowContext.ProjectInfo.ProjectName )"
98+
}
99+
100+
if ($ArtifactCount -eq 1) {
101+
return "Created 1 package artifact for $( $WorkflowContext.ProjectInfo.ProjectName )"
102+
}
103+
104+
return "Created $ArtifactCount package artifacts for $( $WorkflowContext.ProjectInfo.ProjectName )"
105+
}
106+
107+
function Get-NovaPackageWorkflowResultTarget {
108+
[CmdletBinding()]
109+
param(
110+
[Parameter(Mandatory)][pscustomobject]$WorkflowContext,
111+
[Parameter(Mandatory)][AllowEmptyCollection()][object[]]$Artifacts,
112+
[switch]$WhatIfEnabled
113+
)
114+
115+
if ($WhatIfEnabled) {
116+
return $WorkflowContext.Target
117+
}
118+
119+
$resolvedOutputDirectories = @($Artifacts | ForEach-Object OutputDirectory | Sort-Object -Unique)
120+
if ($resolvedOutputDirectories.Count -eq 0) {
121+
return $WorkflowContext.Target
122+
}
123+
124+
return ($resolvedOutputDirectories -join ', ')
125+
}
126+
127+
function Get-NovaPackageWorkflowNextStepLine {
128+
[CmdletBinding()]
129+
param(
130+
[switch]$WhatIfEnabled
131+
)
132+
133+
if ($WhatIfEnabled) {
134+
return @(
135+
'Next step:'
136+
'Run New-NovaModulePackage without -WhatIf when you are ready to create the package artifacts.'
137+
)
138+
}
139+
140+
return @(
141+
'Next step:'
142+
'Deploy-NovaPackage'
143+
)
15144
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
function Invoke-NovaBuildValidation {
2+
param($WorkflowContext)
3+
4+
$script:validated = $true
5+
}
6+
7+
function Invoke-NovaPackageArtifactCreation {
8+
param($WorkflowContext)
9+
10+
return @([pscustomobject]@{PackagePath = '/p'})
11+
}
12+
13+
function Write-Message {
14+
param(
15+
[string]$Text,
16+
[string]$color
17+
)
18+
}
Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,67 @@
11
BeforeAll {
22
$projectRoot = Split-Path -Parent (Split-Path -Parent (Split-Path -Parent $PSScriptRoot))
33
. (Join-Path $projectRoot 'src/private/package/InvokeNovaPackageWorkflow.ps1')
4-
5-
function Invoke-NovaBuildValidation {param($WorkflowContext) $script:validated = $true}
6-
function Invoke-NovaPackageArtifactCreation {param($WorkflowContext) return @([pscustomobject]@{PackagePath='/p'})}
4+
. (Join-Path $PSScriptRoot 'InvokeNovaPackageWorkflow.TestSupport.ps1')
75
}
86

97
Describe 'Invoke-NovaPackageWorkflow' {
108
BeforeEach {
119
$script:validated = $false
10+
Mock Write-Message {}
11+
Mock Write-Progress {}
1212
}
1313

1414
It 'validates the build and returns without creating artifacts when ShouldRun is false' {
1515
Mock Invoke-NovaPackageArtifactCreation {}
16-
$result = Invoke-NovaPackageWorkflow -WorkflowContext ([pscustomobject]@{})
16+
$result = Invoke-NovaPackageWorkflow -WorkflowContext ([pscustomobject]@{
17+
WorkflowParams = @{}
18+
SkipTestsRequested = $false
19+
ProjectInfo = [pscustomobject]@{ProjectName = 'Demo'}
20+
Target = '/p/Demo.1.0.0.nupkg'
21+
})
1722
$script:validated | Should -BeTrue
1823
Should -Invoke Invoke-NovaPackageArtifactCreation -Times 0
24+
Assert-MockCalled Write-Progress -Times 2
1925
$result | Should -BeNullOrEmpty
2026
}
2127

22-
It 'creates artifacts when ShouldRun is set' {
23-
$artifacts = @([pscustomobject]@{PackagePath='/p'})
28+
It 'creates artifacts, reports progress, and prints the next suggested step when ShouldRun is set' {
29+
$artifacts = @([pscustomobject]@{PackagePath='/p/Demo.1.0.0.nupkg'; OutputDirectory='/p'})
2430
Mock Invoke-NovaPackageArtifactCreation {return $artifacts}
25-
$result = Invoke-NovaPackageWorkflow -WorkflowContext ([pscustomobject]@{}) -ShouldRun
31+
$result = Invoke-NovaPackageWorkflow -WorkflowContext ([pscustomobject]@{
32+
WorkflowParams = @{}
33+
SkipTestsRequested = $false
34+
ProjectInfo = [pscustomobject]@{ProjectName = 'Demo'}
35+
Target = '/p/Demo.1.0.0.nupkg'
36+
}) -ShouldRun
2637
Should -Invoke Invoke-NovaPackageArtifactCreation -Times 1
38+
Assert-MockCalled Write-Progress -Times 3
39+
Assert-MockCalled Write-Message -Times 3
40+
Assert-MockCalled Write-Message -Times 1 -ParameterFilter {
41+
$Text -eq 'Created 1 package artifact for Demo' -and $color -eq 'Green'
42+
}
43+
Assert-MockCalled Write-Message -Times 1 -ParameterFilter {
44+
$Text -eq 'Deploy-NovaPackage'
45+
}
2746
@($result).Count | Should -Be 1
2847
}
48+
49+
It 'writes a package plan summary in WhatIf mode' {
50+
$result = Invoke-NovaPackageWorkflow -WorkflowContext ([pscustomobject]@{
51+
WorkflowParams = @{WhatIf = $true}
52+
SkipTestsRequested = $true
53+
ProjectInfo = [pscustomobject]@{ProjectName = 'Demo'}
54+
Target = '/p/Demo.1.0.0.nupkg'
55+
})
56+
57+
$script:validated | Should -BeTrue
58+
Assert-MockCalled Write-Message -Times 3
59+
Assert-MockCalled Write-Message -Times 1 -ParameterFilter {
60+
$Text -eq 'Package plan ready for Demo' -and $color -eq 'Green'
61+
}
62+
Assert-MockCalled Write-Message -Times 1 -ParameterFilter {
63+
$Text -eq 'Run New-NovaModulePackage without -WhatIf when you are ready to create the package artifacts.'
64+
}
65+
$result | Should -BeNullOrEmpty
66+
}
2967
}

0 commit comments

Comments
 (0)