Skip to content

Commit 538edd1

Browse files
committed
fix(#138): resolve information source mismatch in update reporting
- Update `% nova update` to accurately report the current `PSGallery` lookup candidate. - Modify self-update plan functions to preserve lookup candidate and repository information. - Enhance no-update output to reflect the latest update candidate instead of falsely claiming the installed version is the newest.
1 parent f1c881f commit 538edd1

8 files changed

Lines changed: 156 additions & 12 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3434
usage.
3535
- Uses the stored prerelease update preference to decide whether prerelease self-updates are eligible.
3636
- Requires explicit confirmation before a prerelease self-update proceeds.
37+
- `% nova update` now reports the current `PSGallery` lookup candidate in no-update output instead of claiming the
38+
installed version is universally the newest available.
3739
- Add `% nova version --installed` / `% nova version -i` so users can compare the locally installed version of the
3840
current project/module with the current project version from `project.json`, while keeping `% nova --version` /
3941
`% nova -v` dedicated to the installed NovaModuleTools version.

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,10 @@ preference to decide whether prerelease self-updates are eligible. When prerelea
107107
self-update stays on stable releases. When they are enabled, self-update may target a prerelease, but it asks for
108108
explicit confirmation before proceeding.
109109

110+
`% nova update` checks PowerShell Gallery (`PSGallery`) for its current update candidate. When no update is applied,
111+
the CLI reports the installed version together with the candidate returned from that lookup instead of claiming the
112+
installed version is universally the newest available.
113+
110114
Successful `Update-NovaModuleTool`, CLI:`% nova update`, and `Install-NovaCli` runs print the release notes link from
111115
the
112116
installed module manifest. When `Invoke-NovaBuild` detects a newer `NovaModuleTools` version after a build, the update

scripts/build/ci/Install-CiPowerShellModules.ps1

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ function Install-CiModule {
1111
[Parameter(Mandatory)][string]$Name
1212
)
1313

14+
$repositoryName = 'PSGallery'
1415
Write-Host "Installing PowerShell module '$Name'..."
15-
Install-Module -Name $Name -AllowPrerelease -Scope CurrentUser -Force -ErrorAction Stop | Out-Null
16+
Install-Module -Name $Name -Repository $repositoryName -AllowPrerelease -Scope CurrentUser -Force -ErrorAction Stop | Out-Null
1617

1718
$installedModule = Get-InstalledModule -Name $Name -ErrorAction Stop |
1819
Sort-Object Version -Descending |

src/private/cli/FormatNovaCliCommandResult.ps1

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,21 @@ function Format-NovaCliVersionUpdateResult {
5050
return "$summaryPrefix $( $Result.PreviousVersion ) -> $( $Result.NewVersion ) | Label: $( $Result.Label ) | Commits: $( $Result.CommitCount )"
5151
}
5252

53+
function Get-NovaCliNoUpdateDetail {
54+
[CmdletBinding()]
55+
param([Parameter(Mandatory)][object]$Result)
56+
57+
if (-not [string]::IsNullOrWhiteSpace($Result.LookupCandidateVersion) -and -not [string]::IsNullOrWhiteSpace($Result.LookupRepository)) {
58+
return "Installed: $( $Result.ModuleName ) $( $Result.CurrentVersion ). $( $Result.LookupRepository ) currently reports $( $Result.LookupCandidateVersion ) as the latest update candidate checked."
59+
}
60+
61+
if (-not [string]::IsNullOrWhiteSpace($Result.LookupCandidateVersion)) {
62+
return "Installed: $( $Result.ModuleName ) $( $Result.CurrentVersion ). The current update lookup reports $( $Result.LookupCandidateVersion ) as the latest candidate checked."
63+
}
64+
65+
return "Installed: $( $Result.ModuleName ) $( $Result.CurrentVersion ). No update candidate is currently available from the configured update source."
66+
}
67+
5368
function Format-NovaCliCommandResult {
5469
[CmdletBinding()]
5570
param(
@@ -59,8 +74,8 @@ function Format-NovaCliCommandResult {
5974

6075
if (Test-NovaCliNoUpdateResult -Command $Command -Result $Result) {
6176
return @(
62-
"You're up to date!"
63-
"$( $Result.ModuleName ) $( $Result.CurrentVersion ) is currently the newest version available."
77+
'No update was applied.'
78+
(Get-NovaCliNoUpdateDetail -Result $Result)
6479
)
6580
}
6681

src/private/update/ConvertToNovaModuleSelfUpdatePlan.ps1

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,77 @@
1+
function Get-NovaModuleSelfUpdateLookupCandidate {
2+
[CmdletBinding()]
3+
param(
4+
[pscustomobject]$LookupResult,
5+
[Parameter(Mandatory)][bool]$PrereleaseNotificationsEnabled
6+
)
7+
8+
if ($null -eq $LookupResult) {
9+
return $null
10+
}
11+
12+
if ($PrereleaseNotificationsEnabled -and $null -ne $LookupResult.Prerelease) {
13+
return $LookupResult.Prerelease
14+
}
15+
16+
if ($null -ne $LookupResult.Stable) {
17+
return $LookupResult.Stable
18+
}
19+
20+
return $LookupResult.Prerelease
21+
}
22+
23+
function Get-NovaModuleSelfUpdateLookupRepository {
24+
[CmdletBinding()]
25+
param(
26+
[pscustomobject]$LookupResult,
27+
[object]$LookupCandidate
28+
)
29+
30+
if ($null -ne $LookupCandidate -and $LookupCandidate.PSObject.Properties.Name -contains 'Repository') {
31+
return $LookupCandidate.Repository
32+
}
33+
34+
if ($null -ne $LookupResult -and $LookupResult.PSObject.Properties.Name -contains 'SourceRepository') {
35+
return $LookupResult.SourceRepository
36+
}
37+
38+
return $null
39+
}
40+
41+
function Get-NovaModuleSelfUpdatePlanContext {
42+
[CmdletBinding()]
43+
param(
44+
[pscustomobject]$LookupResult,
45+
[Parameter(Mandatory)][bool]$PrereleaseNotificationsEnabled
46+
)
47+
48+
$lookupCandidate = Get-NovaModuleSelfUpdateLookupCandidate -LookupResult $LookupResult -PrereleaseNotificationsEnabled:$PrereleaseNotificationsEnabled
49+
$lookupCandidateVersion = if ($null -ne $lookupCandidate -and $lookupCandidate.PSObject.Properties.Name -contains 'Version') {
50+
$lookupCandidate.Version
51+
}
52+
else {
53+
$null
54+
}
55+
$lookupCandidateChannel = if ($null -ne $lookupCandidate -and $lookupCandidate.PSObject.Properties.Name -contains 'Channel') {
56+
$lookupCandidate.Channel
57+
}
58+
else {
59+
$null
60+
}
61+
62+
return [pscustomobject]@{
63+
LookupCandidateVersion = $lookupCandidateVersion
64+
LookupCandidateChannel = $lookupCandidateChannel
65+
LookupRepository = Get-NovaModuleSelfUpdateLookupRepository -LookupResult $LookupResult -LookupCandidate $lookupCandidate
66+
PrereleaseNotificationsEnabled = $PrereleaseNotificationsEnabled
67+
}
68+
}
69+
170
function ConvertTo-NovaModuleSelfUpdatePlan {
271
[CmdletBinding()]
372
param(
473
[Parameter(Mandatory)][pscustomobject]$InstalledModule,
5-
[Parameter(Mandatory)][bool]$PrereleaseNotificationsEnabled,
74+
[Parameter(Mandatory)][pscustomobject]$PlanContext,
675
[string]$TargetVersion,
776
[switch]$PrereleaseTarget
877
)
@@ -11,7 +80,10 @@ function ConvertTo-NovaModuleSelfUpdatePlan {
1180
ModuleName = $InstalledModule.ModuleName
1281
CurrentVersion = $InstalledModule.Version
1382
TargetVersion = $TargetVersion
14-
PrereleaseNotificationsEnabled = $PrereleaseNotificationsEnabled
83+
LookupCandidateVersion = $PlanContext.LookupCandidateVersion
84+
LookupCandidateChannel = $PlanContext.LookupCandidateChannel
85+
LookupRepository = $PlanContext.LookupRepository
86+
PrereleaseNotificationsEnabled = $PlanContext.PrereleaseNotificationsEnabled
1587
UpdateAvailable = -not [string]::IsNullOrWhiteSpace($TargetVersion)
1688
Updated = $false
1789
Cancelled = $false

src/private/update/GetNovaModuleSelfUpdatePlan.ps1

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@ function Get-NovaModuleSelfUpdatePlan {
66
[Parameter(Mandatory)][bool]$PrereleaseNotificationsEnabled
77
)
88

9+
$planContext = Get-NovaModuleSelfUpdatePlanContext -LookupResult $LookupResult -PrereleaseNotificationsEnabled:$PrereleaseNotificationsEnabled
910
$stableVersion = Get-NovaAvailableSemanticVersion -VersionInfo $LookupResult.Stable
1011
if (Test-NovaPrereleaseUpdateAvailable -LookupResult $LookupResult -InstalledVersion $InstalledModule.SemanticVersion -StableVersion $stableVersion -PrereleaseNotificationsEnabled $PrereleaseNotificationsEnabled) {
11-
return ConvertTo-NovaModuleSelfUpdatePlan -InstalledModule $InstalledModule -PrereleaseNotificationsEnabled:$PrereleaseNotificationsEnabled -TargetVersion $LookupResult.Prerelease.Version -PrereleaseTarget
12+
return ConvertTo-NovaModuleSelfUpdatePlan -InstalledModule $InstalledModule -PlanContext $planContext -TargetVersion $LookupResult.Prerelease.Version -PrereleaseTarget
1213
}
1314

1415
if (Test-NovaStableUpdateAvailable -StableVersion $stableVersion -InstalledVersion $InstalledModule.SemanticVersion) {
15-
return ConvertTo-NovaModuleSelfUpdatePlan -InstalledModule $InstalledModule -PrereleaseNotificationsEnabled:$PrereleaseNotificationsEnabled -TargetVersion $LookupResult.Stable.Version
16+
return ConvertTo-NovaModuleSelfUpdatePlan -InstalledModule $InstalledModule -PlanContext $planContext -TargetVersion $LookupResult.Stable.Version
1617
}
1718

18-
return ConvertTo-NovaModuleSelfUpdatePlan -InstalledModule $InstalledModule -PrereleaseNotificationsEnabled:$PrereleaseNotificationsEnabled
19+
return ConvertTo-NovaModuleSelfUpdatePlan -InstalledModule $InstalledModule -PlanContext $planContext
1920
}

src/resources/update/ModuleUpdateLookup.ps1.txt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ $WarningPreference = 'SilentlyContinue'
44
$InformationPreference = 'SilentlyContinue'
55
$VerbosePreference = 'SilentlyContinue'
66
$ErrorActionPreference = 'Stop'
7+
$repositoryName = 'PSGallery'
78

89
function Get-PrereleaseLabel {
910
param([object]$Item)
@@ -47,19 +48,21 @@ function ConvertTo-VersionInfo {
4748
return [pscustomobject]@{
4849
ModuleName = $ResolvedModuleName
4950
Channel = $Channel
51+
Repository = $repositoryName
5052
Version = $versionText
5153
}
5254
}
5355

54-
$stableItem = Find-Module $ResolvedModuleName -ErrorAction Stop -WarningAction SilentlyContinue
56+
$stableItem = Find-Module $ResolvedModuleName -Repository $repositoryName -ErrorAction Stop -WarningAction SilentlyContinue
5557
$prereleaseItem = if ($IncludePrerelease) {
56-
Find-Module $ResolvedModuleName -AllowPrerelease -ErrorAction Stop -WarningAction SilentlyContinue
58+
Find-Module $ResolvedModuleName -Repository $repositoryName -AllowPrerelease -ErrorAction Stop -WarningAction SilentlyContinue
5759
}
5860
else {
5961
$null
6062
}
6163

6264
[pscustomobject]@{
65+
SourceRepository = $repositoryName
6366
Stable = ConvertTo-VersionInfo -Item $stableItem -Channel 'Stable'
6467
Prerelease = ConvertTo-VersionInfo -Item $prereleaseItem -Channel 'Prerelease'
6568
}

tests/UpdateNotification.Tests.ps1

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,38 @@ Describe 'Update notification behavior' {
243243
}
244244
}
245245

246+
It 'Get-NovaModuleSelfUpdatePlan preserves the lookup candidate and repository for no-update results' {
247+
InModuleScope $script:moduleName {
248+
$installedModule = [pscustomobject]@{
249+
ModuleName = 'NovaModuleTools'
250+
Version = '2.0.0-preview9920'
251+
SemanticVersion = [semver]'2.0.0-preview9920'
252+
IsPrerelease = $true
253+
}
254+
$lookupResult = [pscustomobject]@{
255+
SourceRepository = 'PSGallery'
256+
Stable = [pscustomobject]@{
257+
Version = '1.9.1'
258+
Channel = 'Stable'
259+
Repository = 'PSGallery'
260+
}
261+
Prerelease = [pscustomobject]@{
262+
Version = '2.0.0-beta'
263+
Channel = 'Prerelease'
264+
Repository = 'PSGallery'
265+
}
266+
}
267+
268+
$result = Get-NovaModuleSelfUpdatePlan -InstalledModule $installedModule -LookupResult $lookupResult -PrereleaseNotificationsEnabled:$true
269+
270+
$result.UpdateAvailable | Should -BeFalse
271+
$result.TargetVersion | Should -BeNullOrEmpty
272+
$result.LookupCandidateVersion | Should -Be '2.0.0-beta'
273+
$result.LookupCandidateChannel | Should -Be 'Prerelease'
274+
$result.LookupRepository | Should -Be 'PSGallery'
275+
}
276+
}
277+
246278
It 'Get-NovaModuleSelfUpdateWorkflowContext throws when update lookup cannot resolve a candidate' {
247279
InModuleScope $script:moduleName {
248280
Mock Read-NovaUpdateNotificationPreference {[pscustomobject]@{PrereleaseNotificationsEnabled = $true}}
@@ -549,6 +581,9 @@ Describe 'Update notification behavior' {
549581
ModuleName = 'NovaModuleTools'
550582
CurrentVersion = '2.0.0-prerelease3'
551583
TargetVersion = $null
584+
LookupCandidateVersion = '2.0.0-beta'
585+
LookupCandidateChannel = 'Prerelease'
586+
LookupRepository = 'PSGallery'
552587
PrereleaseNotificationsEnabled = $true
553588
UpdateAvailable = $false
554589
Updated = $false
@@ -561,12 +596,23 @@ Describe 'Update notification behavior' {
561596
$result = @(Invoke-NovaCli update)
562597

563598
$result | Should -HaveCount 2
564-
$result[0] | Should -Be "You're up to date!"
565-
$result[1] | Should -Be 'NovaModuleTools 2.0.0-prerelease3 is currently the newest version available.'
599+
$result[0] | Should -Be 'No update was applied.'
600+
$result[1] | Should -Be 'Installed: NovaModuleTools 2.0.0-prerelease3. PSGallery currently reports 2.0.0-beta as the latest update candidate checked.'
566601
Assert-MockCalled Update-NovaModuleTool -Times 1
567602
}
568603
}
569604

605+
It 'Get-NovaModuleUpdateLookupScript pins lookups to PSGallery and returns repository metadata' {
606+
InModuleScope $script:moduleName {
607+
$scriptText = Get-NovaModuleUpdateLookupScript
608+
609+
$scriptText | Should -Match 'Find-Module \$ResolvedModuleName -Repository \$repositoryName'
610+
$scriptText | Should -Match 'Find-Module \$ResolvedModuleName -Repository \$repositoryName -AllowPrerelease'
611+
$scriptText | Should -Match 'SourceRepository = \$repositoryName'
612+
$scriptText | Should -Match 'Repository = \$repositoryName'
613+
}
614+
}
615+
570616
It 'ConvertFrom-NovaUpdateCliArgument allows no arguments and rejects unsupported usage' {
571617
InModuleScope $script:moduleName {
572618
(ConvertFrom-NovaUpdateCliArgument).Count | Should -Be 0

0 commit comments

Comments
 (0)