Skip to content

Commit 33f9573

Browse files
HeyItsGilbertclaudeCopilot
authored
fix: bootstrap NuGet lazily only when a Nuget/PSGalleryNuget dep is used (#175)
## Summary Fixes #117. PSDepend was unconditionally downloading `nuget.exe` at module load time via `BootStrap-Nuget` in `PSDepend.psm1`, even when no `Nuget` or `PSGalleryNuget` dependencies were declared. Users relying purely on `PSGalleryModule` (or any other type) had no way to suppress this network call. - Remove the eager `BootStrap-Nuget` call from `PSDepend.psm1` - Move it into `Nuget.ps1` and `PSGalleryNuget.ps1` so it only runs when one of those dependency types is actually invoked - Wrap the call in `Test-PlatformSupport` (matching the original guard) so bootstrap is skipped on platforms where `nuget.exe` isn't applicable - Add a missing `return` after `Write-Error` in both scripts — previously execution would continue into the `nuget install` invocation even after the error ## Test plan - [x] `Nuget.Type.Tests.ps1` — new `NuGet bootstrap` context: verifies `BootStrap-Nuget` is called when `nuget.exe` is missing on a supported platform, not called on unsupported platforms, and that `Invoke-ExternalCommand` is never reached when nuget remains unavailable after bootstrap - [x] `PSGalleryNuget.Type.Tests.ps1` — same three cases for the `PSGalleryNuget` script - [x] All 12 tests pass (`Passed: 12 | Failed: 0`) 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Signed-off-by: Gilbert Sanchez <me@gilbertsanchez.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
1 parent 06f785d commit 33f9573

5 files changed

Lines changed: 99 additions & 6 deletions

File tree

PSDepend/PSDepend.psm1

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
}
1717
}
1818

19-
#Get nuget dependecy file if we don't have it
19+
#Read PSDepend.Config path variables
2020
Get-Content $ModuleRoot\PSDepend.Config |
2121
Where-Object {$_ -and $_ -notmatch "^\s*#"} |
2222
Foreach-Object {
@@ -27,8 +27,5 @@
2727
$Value = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Value)
2828
Set-Variable -Name $Name -Value $Value
2929
}
30-
if(Test-PlatformSupport -Support 'windows','core') {
31-
BootStrap-Nuget -NugetPath $NuGetPath
32-
}
3330

3431
Export-ModuleMember -Function $Public.Basename

PSDepend/PSDependScripts/Nuget.ps1

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,15 @@ param(
109109

110110
if(-not (Get-Command Nuget -ErrorAction SilentlyContinue))
111111
{
112-
Write-Error "Nuget requires Nuget.exe. Ensure this is in your path, or explicitly specified in $ModuleRoot\PSDepend.Config's NugetPath. Skipping [$DependencyName]"
112+
if(Test-PlatformSupport -Type 'Nuget' -Support 'windows','core')
113+
{
114+
BootStrap-Nuget -NugetPath $NuGetPath
115+
}
116+
if(-not (Get-Command Nuget -ErrorAction SilentlyContinue))
117+
{
118+
Write-Error "Nuget requires Nuget.exe. Ensure this is in your path, or explicitly specified in $ModuleRoot\PSDepend.Config's NugetPath. Skipping [$DependencyName]"
119+
return
120+
}
113121
}
114122

115123
Write-Verbose -Message "Getting dependency [$DependencyName] from Nuget source [$Source]"

PSDepend/PSDependScripts/PSGalleryNuget.ps1

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,15 @@ param(
9797

9898
if(-not (Get-Command Nuget -ErrorAction SilentlyContinue))
9999
{
100-
Write-Error "PSGalleryNuget requires Nuget.exe. Ensure this is in your path, or explicitly specified in $ModuleRoot\PSDepend.Config's NugetPath. Skipping [$DependencyName]"
100+
if(Test-PlatformSupport -Type 'PSGalleryNuget' -Support 'windows','core')
101+
{
102+
BootStrap-Nuget -NugetPath $NuGetPath
103+
}
104+
if(-not (Get-Command Nuget -ErrorAction SilentlyContinue))
105+
{
106+
Write-Error "PSGalleryNuget requires Nuget.exe. Ensure this is in your path, or explicitly specified in $ModuleRoot\PSDepend.Config's NugetPath. Skipping [$DependencyName]"
107+
return
108+
}
101109
}
102110

103111
Write-Verbose -Message "Getting dependency [$name] from Nuget source [$Source]"

Tests/Nuget.Type.Tests.ps1

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,44 @@ Describe 'Nuget script' {
5252
$Arguments -contains '-version' -and $Arguments -contains '12.0.2'
5353
}
5454
}
55+
56+
Context 'NuGet bootstrap' {
57+
BeforeAll {
58+
InModuleScope PSDepend {
59+
Mock Get-Command { $null } -ParameterFilter { $Name -eq 'Nuget' }
60+
Mock BootStrap-Nuget { }
61+
Mock Test-PlatformSupport { $true }
62+
}
63+
}
64+
65+
It 'Calls BootStrap-Nuget when nuget.exe is missing on a supported platform' {
66+
$targetDir = (New-Item 'TestDrive:/nuget-bootstrap' -ItemType Directory -Force).FullName
67+
$dep = New-PSDependFixture -DependencyName 'Newtonsoft.Json' -DependencyType 'Nuget' -Target $targetDir
68+
InModuleScope PSDepend -Parameters @{ Dep = $dep; ScriptPath = $script:ScriptPath } {
69+
& $ScriptPath -Dependency $Dep -ErrorAction SilentlyContinue
70+
}
71+
Should -Invoke -CommandName BootStrap-Nuget -ModuleName PSDepend -Times 1
72+
}
73+
74+
It 'Does not invoke nuget install when nuget.exe is still missing after bootstrap' {
75+
$targetDir = (New-Item 'TestDrive:/nuget-bootstrap-fail' -ItemType Directory -Force).FullName
76+
$dep = New-PSDependFixture -DependencyName 'Newtonsoft.Json' -DependencyType 'Nuget' -Target $targetDir
77+
InModuleScope PSDepend -Parameters @{ Dep = $dep; ScriptPath = $script:ScriptPath } {
78+
& $ScriptPath -Dependency $Dep -ErrorAction SilentlyContinue
79+
}
80+
Should -Invoke -CommandName Invoke-ExternalCommand -ModuleName PSDepend -Times 0
81+
}
82+
83+
It 'Does not call BootStrap-Nuget on an unsupported platform' {
84+
InModuleScope PSDepend {
85+
Mock Test-PlatformSupport { $false }
86+
}
87+
$targetDir = (New-Item 'TestDrive:/nuget-bootstrap-noplatform' -ItemType Directory -Force).FullName
88+
$dep = New-PSDependFixture -DependencyName 'Newtonsoft.Json' -DependencyType 'Nuget' -Target $targetDir
89+
InModuleScope PSDepend -Parameters @{ Dep = $dep; ScriptPath = $script:ScriptPath } {
90+
& $ScriptPath -Dependency $Dep -ErrorAction SilentlyContinue
91+
}
92+
Should -Invoke -CommandName BootStrap-Nuget -ModuleName PSDepend -Times 0
93+
}
94+
}
5595
}

Tests/PSGalleryNuget.Type.Tests.ps1

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,44 @@ Describe 'PSGalleryNuget script' {
5151
}
5252
Should -Invoke -CommandName Import-PSDependModule -ModuleName PSDepend -Times 1
5353
}
54+
55+
Context 'NuGet bootstrap' {
56+
BeforeAll {
57+
InModuleScope PSDepend {
58+
Mock Get-Command { $null } -ParameterFilter { $Name -eq 'Nuget' }
59+
Mock BootStrap-Nuget { }
60+
Mock Test-PlatformSupport { $true }
61+
}
62+
}
63+
64+
It 'Calls BootStrap-Nuget when nuget.exe is missing on a supported platform' {
65+
$targetDir = (New-Item 'TestDrive:/psgnuget-bootstrap' -ItemType Directory -Force).FullName
66+
$dep = New-PSDependFixture -DependencyName 'PSDeploy' -DependencyType 'PSGalleryNuget' -Target $targetDir
67+
InModuleScope PSDepend -Parameters @{ Dep = $dep; ScriptPath = $script:ScriptPath } {
68+
& $ScriptPath -Dependency $Dep -ErrorAction SilentlyContinue
69+
}
70+
Should -Invoke -CommandName BootStrap-Nuget -ModuleName PSDepend -Times 1
71+
}
72+
73+
It 'Does not invoke nuget install when nuget.exe is still missing after bootstrap' {
74+
$targetDir = (New-Item 'TestDrive:/psgnuget-bootstrap-fail' -ItemType Directory -Force).FullName
75+
$dep = New-PSDependFixture -DependencyName 'PSDeploy' -DependencyType 'PSGalleryNuget' -Target $targetDir
76+
InModuleScope PSDepend -Parameters @{ Dep = $dep; ScriptPath = $script:ScriptPath } {
77+
& $ScriptPath -Dependency $Dep -ErrorAction SilentlyContinue
78+
}
79+
Should -Invoke -CommandName Invoke-ExternalCommand -ModuleName PSDepend -Times 0
80+
}
81+
82+
It 'Does not call BootStrap-Nuget on an unsupported platform' {
83+
InModuleScope PSDepend {
84+
Mock Test-PlatformSupport { $false }
85+
}
86+
$targetDir = (New-Item 'TestDrive:/psgnuget-bootstrap-noplatform' -ItemType Directory -Force).FullName
87+
$dep = New-PSDependFixture -DependencyName 'PSDeploy' -DependencyType 'PSGalleryNuget' -Target $targetDir
88+
InModuleScope PSDepend -Parameters @{ Dep = $dep; ScriptPath = $script:ScriptPath } {
89+
& $ScriptPath -Dependency $Dep -ErrorAction SilentlyContinue
90+
}
91+
Should -Invoke -CommandName BootStrap-Nuget -ModuleName PSDepend -Times 0
92+
}
93+
}
5494
}

0 commit comments

Comments
 (0)