From 3856422beb851a99cf19c45e93a188faf74163d9 Mon Sep 17 00:00:00 2001 From: Gilbert Sanchez Date: Fri, 15 May 2026 21:56:23 -0700 Subject: [PATCH 1/2] fix: bootstrap NuGet lazily only when a Nuget/PSGalleryNuget dep is used Fixes #117. PSDepend was unconditionally downloading nuget.exe at module load time, even when no NuGet dependencies were declared. Move the BootStrap-Nuget call out of PSDepend.psm1 and into Nuget.ps1 and PSGalleryNuget.ps1 so it only runs on demand. Also add a missing `return` after the nuget-unavailable Write-Error in both scripts. Co-Authored-By: Claude Sonnet 4.6 --- PSDepend/PSDepend.psm1 | 5 +-- PSDepend/PSDependScripts/Nuget.ps1 | 10 +++++- PSDepend/PSDependScripts/PSGalleryNuget.ps1 | 10 +++++- Tests/Nuget.Type.Tests.ps1 | 40 +++++++++++++++++++++ Tests/PSGalleryNuget.Type.Tests.ps1 | 40 +++++++++++++++++++++ 5 files changed, 99 insertions(+), 6 deletions(-) diff --git a/PSDepend/PSDepend.psm1 b/PSDepend/PSDepend.psm1 index aa0a743..998f305 100644 --- a/PSDepend/PSDepend.psm1 +++ b/PSDepend/PSDepend.psm1 @@ -16,7 +16,7 @@ } } -#Get nuget dependecy file if we don't have it +#Read PSDepend.Config path variables Get-Content $ModuleRoot\PSDepend.Config | Where-Object {$_ -and $_ -notmatch "^\s*#"} | Foreach-Object { @@ -27,8 +27,5 @@ $Value = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Value) Set-Variable -Name $Name -Value $Value } - if(Test-PlatformSupport -Support 'windows','core') { - BootStrap-Nuget -NugetPath $NuGetPath - } Export-ModuleMember -Function $Public.Basename diff --git a/PSDepend/PSDependScripts/Nuget.ps1 b/PSDepend/PSDependScripts/Nuget.ps1 index 68aff50..88cd689 100644 --- a/PSDepend/PSDependScripts/Nuget.ps1 +++ b/PSDepend/PSDependScripts/Nuget.ps1 @@ -109,7 +109,15 @@ param( if(-not (Get-Command Nuget -ErrorAction SilentlyContinue)) { - Write-Error "Nuget requires Nuget.exe. Ensure this is in your path, or explicitly specified in $ModuleRoot\PSDepend.Config's NugetPath. Skipping [$DependencyName]" + if(Test-PlatformSupport -Support 'windows','core') + { + BootStrap-Nuget -NugetPath $NuGetPath + } + if(-not (Get-Command Nuget -ErrorAction SilentlyContinue)) + { + Write-Error "Nuget requires Nuget.exe. Ensure this is in your path, or explicitly specified in $ModuleRoot\PSDepend.Config's NugetPath. Skipping [$DependencyName]" + return + } } Write-Verbose -Message "Getting dependency [$DependencyName] from Nuget source [$Source]" diff --git a/PSDepend/PSDependScripts/PSGalleryNuget.ps1 b/PSDepend/PSDependScripts/PSGalleryNuget.ps1 index 0d94777..2fe512a 100644 --- a/PSDepend/PSDependScripts/PSGalleryNuget.ps1 +++ b/PSDepend/PSDependScripts/PSGalleryNuget.ps1 @@ -97,7 +97,15 @@ param( if(-not (Get-Command Nuget -ErrorAction SilentlyContinue)) { - Write-Error "PSGalleryNuget requires Nuget.exe. Ensure this is in your path, or explicitly specified in $ModuleRoot\PSDepend.Config's NugetPath. Skipping [$DependencyName]" + if(Test-PlatformSupport -Support 'windows','core') + { + BootStrap-Nuget -NugetPath $NuGetPath + } + if(-not (Get-Command Nuget -ErrorAction SilentlyContinue)) + { + Write-Error "PSGalleryNuget requires Nuget.exe. Ensure this is in your path, or explicitly specified in $ModuleRoot\PSDepend.Config's NugetPath. Skipping [$DependencyName]" + return + } } Write-Verbose -Message "Getting dependency [$name] from Nuget source [$Source]" diff --git a/Tests/Nuget.Type.Tests.ps1 b/Tests/Nuget.Type.Tests.ps1 index f797bd1..3aefbe8 100644 --- a/Tests/Nuget.Type.Tests.ps1 +++ b/Tests/Nuget.Type.Tests.ps1 @@ -52,4 +52,44 @@ Describe 'Nuget script' { $Arguments -contains '-version' -and $Arguments -contains '12.0.2' } } + + Context 'NuGet bootstrap' { + BeforeAll { + InModuleScope PSDepend { + Mock Get-Command { $null } -ParameterFilter { $Name -eq 'Nuget' } + Mock BootStrap-Nuget { } + Mock Test-PlatformSupport { $true } + } + } + + It 'Calls BootStrap-Nuget when nuget.exe is missing on a supported platform' { + $targetDir = (New-Item 'TestDrive:/nuget-bootstrap' -ItemType Directory -Force).FullName + $dep = New-PSDependFixture -DependencyName 'Newtonsoft.Json' -DependencyType 'Nuget' -Target $targetDir + InModuleScope PSDepend -Parameters @{ Dep = $dep; ScriptPath = $script:ScriptPath } { + & $ScriptPath -Dependency $Dep -ErrorAction SilentlyContinue + } + Should -Invoke -CommandName BootStrap-Nuget -ModuleName PSDepend -Times 1 + } + + It 'Does not invoke nuget install when nuget.exe is still missing after bootstrap' { + $targetDir = (New-Item 'TestDrive:/nuget-bootstrap-fail' -ItemType Directory -Force).FullName + $dep = New-PSDependFixture -DependencyName 'Newtonsoft.Json' -DependencyType 'Nuget' -Target $targetDir + InModuleScope PSDepend -Parameters @{ Dep = $dep; ScriptPath = $script:ScriptPath } { + & $ScriptPath -Dependency $Dep -ErrorAction SilentlyContinue + } + Should -Invoke -CommandName Invoke-ExternalCommand -ModuleName PSDepend -Times 0 + } + + It 'Does not call BootStrap-Nuget on an unsupported platform' { + InModuleScope PSDepend { + Mock Test-PlatformSupport { $false } + } + $targetDir = (New-Item 'TestDrive:/nuget-bootstrap-noplatform' -ItemType Directory -Force).FullName + $dep = New-PSDependFixture -DependencyName 'Newtonsoft.Json' -DependencyType 'Nuget' -Target $targetDir + InModuleScope PSDepend -Parameters @{ Dep = $dep; ScriptPath = $script:ScriptPath } { + & $ScriptPath -Dependency $Dep -ErrorAction SilentlyContinue + } + Should -Invoke -CommandName BootStrap-Nuget -ModuleName PSDepend -Times 0 + } + } } diff --git a/Tests/PSGalleryNuget.Type.Tests.ps1 b/Tests/PSGalleryNuget.Type.Tests.ps1 index c53c323..764cf37 100644 --- a/Tests/PSGalleryNuget.Type.Tests.ps1 +++ b/Tests/PSGalleryNuget.Type.Tests.ps1 @@ -51,4 +51,44 @@ Describe 'PSGalleryNuget script' { } Should -Invoke -CommandName Import-PSDependModule -ModuleName PSDepend -Times 1 } + + Context 'NuGet bootstrap' { + BeforeAll { + InModuleScope PSDepend { + Mock Get-Command { $null } -ParameterFilter { $Name -eq 'Nuget' } + Mock BootStrap-Nuget { } + Mock Test-PlatformSupport { $true } + } + } + + It 'Calls BootStrap-Nuget when nuget.exe is missing on a supported platform' { + $targetDir = (New-Item 'TestDrive:/psgnuget-bootstrap' -ItemType Directory -Force).FullName + $dep = New-PSDependFixture -DependencyName 'PSDeploy' -DependencyType 'PSGalleryNuget' -Target $targetDir + InModuleScope PSDepend -Parameters @{ Dep = $dep; ScriptPath = $script:ScriptPath } { + & $ScriptPath -Dependency $Dep -ErrorAction SilentlyContinue + } + Should -Invoke -CommandName BootStrap-Nuget -ModuleName PSDepend -Times 1 + } + + It 'Does not invoke nuget install when nuget.exe is still missing after bootstrap' { + $targetDir = (New-Item 'TestDrive:/psgnuget-bootstrap-fail' -ItemType Directory -Force).FullName + $dep = New-PSDependFixture -DependencyName 'PSDeploy' -DependencyType 'PSGalleryNuget' -Target $targetDir + InModuleScope PSDepend -Parameters @{ Dep = $dep; ScriptPath = $script:ScriptPath } { + & $ScriptPath -Dependency $Dep -ErrorAction SilentlyContinue + } + Should -Invoke -CommandName Invoke-ExternalCommand -ModuleName PSDepend -Times 0 + } + + It 'Does not call BootStrap-Nuget on an unsupported platform' { + InModuleScope PSDepend { + Mock Test-PlatformSupport { $false } + } + $targetDir = (New-Item 'TestDrive:/psgnuget-bootstrap-noplatform' -ItemType Directory -Force).FullName + $dep = New-PSDependFixture -DependencyName 'PSDeploy' -DependencyType 'PSGalleryNuget' -Target $targetDir + InModuleScope PSDepend -Parameters @{ Dep = $dep; ScriptPath = $script:ScriptPath } { + & $ScriptPath -Dependency $Dep -ErrorAction SilentlyContinue + } + Should -Invoke -CommandName BootStrap-Nuget -ModuleName PSDepend -Times 0 + } + } } From 084652ade294ccd60a2e15497fed2b80290a8d69 Mon Sep 17 00:00:00 2001 From: Gilbert Sanchez Date: Fri, 15 May 2026 22:03:09 -0700 Subject: [PATCH 2/2] Apply suggestions from code review Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Signed-off-by: Gilbert Sanchez --- PSDepend/PSDependScripts/Nuget.ps1 | 2 +- PSDepend/PSDependScripts/PSGalleryNuget.ps1 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/PSDepend/PSDependScripts/Nuget.ps1 b/PSDepend/PSDependScripts/Nuget.ps1 index 88cd689..a8c22b6 100644 --- a/PSDepend/PSDependScripts/Nuget.ps1 +++ b/PSDepend/PSDependScripts/Nuget.ps1 @@ -109,7 +109,7 @@ param( if(-not (Get-Command Nuget -ErrorAction SilentlyContinue)) { - if(Test-PlatformSupport -Support 'windows','core') + if(Test-PlatformSupport -Type 'Nuget' -Support 'windows','core') { BootStrap-Nuget -NugetPath $NuGetPath } diff --git a/PSDepend/PSDependScripts/PSGalleryNuget.ps1 b/PSDepend/PSDependScripts/PSGalleryNuget.ps1 index 2fe512a..c67e7fa 100644 --- a/PSDepend/PSDependScripts/PSGalleryNuget.ps1 +++ b/PSDepend/PSDependScripts/PSGalleryNuget.ps1 @@ -97,7 +97,7 @@ param( if(-not (Get-Command Nuget -ErrorAction SilentlyContinue)) { - if(Test-PlatformSupport -Support 'windows','core') + if(Test-PlatformSupport -Type 'PSGalleryNuget' -Support 'windows','core') { BootStrap-Nuget -NugetPath $NuGetPath }