From 5df76d2f5fdea8b756a8bcf93c38c525b2040d6d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 19 Nov 2025 19:24:44 +0000 Subject: [PATCH 1/6] Initial plan From 9a7298c1dcfe1a299d85d77d7d58b1f661bfc710 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 19 Nov 2025 19:29:44 +0000 Subject: [PATCH 2/6] Initial analysis of TrustRepository issue in RequiredResource Co-authored-by: adityapatwardhan <12820925+adityapatwardhan@users.noreply.github.com> --- nuget.config | 1 + 1 file changed, 1 insertion(+) diff --git a/nuget.config b/nuget.config index 5c704bf46..759e2aac1 100644 --- a/nuget.config +++ b/nuget.config @@ -2,6 +2,7 @@ + From 744776f7ea94c5836047959794ddb03928570dcf Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 19 Nov 2025 19:32:35 +0000 Subject: [PATCH 3/6] Fix TrustRepository not being respected in RequiredResource and add tests Co-authored-by: adityapatwardhan <12820925+adityapatwardhan@users.noreply.github.com> --- src/code/InstallPSResource.cs | 24 +++++++++++++------ .../InstallPSResourceV2Server.Tests.ps1 | 13 ++++++++++ .../InstallPSResourceV3Server.Tests.ps1 | 13 ++++++++++ 3 files changed, 43 insertions(+), 7 deletions(-) diff --git a/src/code/InstallPSResource.cs b/src/code/InstallPSResource.cs index 83943eef9..1ddd67412 100644 --- a/src/code/InstallPSResource.cs +++ b/src/code/InstallPSResource.cs @@ -565,6 +565,16 @@ private void ProcessInstallHelper(string[] pkgNames, string pkgVersion, bool pkg this)); } + // When reqResourceParams is provided (via -RequiredResource), use its properties + // instead of the cmdlet-level parameters + bool acceptLicense = reqResourceParams != null ? reqResourceParams.AcceptLicense : AcceptLicense; + bool quiet = reqResourceParams != null ? reqResourceParams.Quiet : Quiet; + bool reinstall = reqResourceParams != null ? reqResourceParams.Reinstall : Reinstall; + bool trustRepository = reqResourceParams != null ? reqResourceParams.TrustRepository : TrustRepository; + bool noClobber = reqResourceParams != null ? reqResourceParams.NoClobber : NoClobber; + bool skipDependencyCheck = reqResourceParams != null ? reqResourceParams.SkipDependencyCheck : SkipDependencyCheck; + ScopeType scope = reqResourceParams != null && reqResourceParams.Scope != ScopeType.CurrentUser ? reqResourceParams.Scope : Scope; + IEnumerable installedPkgs = _installHelper.BeginInstallPackages( names: pkgNames, versionRange: versionRange, @@ -573,19 +583,19 @@ private void ProcessInstallHelper(string[] pkgNames, string pkgVersion, bool pkg versionString: Version, prerelease: pkgPrerelease, repository: pkgRepository, - acceptLicense: AcceptLicense, - quiet: Quiet, - reinstall: Reinstall, + acceptLicense: acceptLicense, + quiet: quiet, + reinstall: reinstall, force: false, - trustRepository: TrustRepository, - noClobber: NoClobber, + trustRepository: trustRepository, + noClobber: noClobber, asNupkg: false, includeXml: true, - skipDependencyCheck: SkipDependencyCheck, + skipDependencyCheck: skipDependencyCheck, authenticodeCheck: AuthenticodeCheck, savePkg: false, pathsToInstallPkg: _pathsToInstallPkg, - scope: Scope, + scope: scope, tmpPath: _tmpPath, pkgsInstalled: _packagesOnMachine); diff --git a/test/InstallPSResourceTests/InstallPSResourceV2Server.Tests.ps1 b/test/InstallPSResourceTests/InstallPSResourceV2Server.Tests.ps1 index 4285e0479..e269b2628 100644 --- a/test/InstallPSResourceTests/InstallPSResourceV2Server.Tests.ps1 +++ b/test/InstallPSResourceTests/InstallPSResourceV2Server.Tests.ps1 @@ -429,6 +429,19 @@ Describe 'Test Install-PSResource for V2 Server scenarios' -tags 'CI' { (Get-InstalledPSResource -Name 'TestModule99').'Prerelease' | Should -Be 'beta2' } + It "Install module using -RequiredResource with TrustRepository in hashtable" { + # This test verifies that TrustRepository specified in -RequiredResource hashtable is respected + Install-PSResource -RequiredResource @{ + 'TestModule99' = @{ + 'repository' = 'PSGallery' + 'trustrepository' = 'true' + } + } + $res = Get-InstalledPSResource -Name 'TestModule99' + $res.Name | Should -Be 'TestModule99' + $res.Version | Should -Be '0.0.93' + } + It "Install modules using -RequiredResource with JSON string" { $rrJSON = "{ 'test_module': { diff --git a/test/InstallPSResourceTests/InstallPSResourceV3Server.Tests.ps1 b/test/InstallPSResourceTests/InstallPSResourceV3Server.Tests.ps1 index e18b9272d..835e0c0c6 100644 --- a/test/InstallPSResourceTests/InstallPSResourceV3Server.Tests.ps1 +++ b/test/InstallPSResourceTests/InstallPSResourceV3Server.Tests.ps1 @@ -310,6 +310,19 @@ Describe 'Test Install-PSResource for V3Server scenarios' -tags 'CI' { $res3.Version | Should -Be '0.0.93' } + It 'Install module using -RequiredResource with TrustRepository in hashtable' { + # This test verifies that TrustRepository specified in -RequiredResource hashtable is respected + Install-PSResource -RequiredResource @{ + 'TestModule99' = @{ + 'repository' = $NuGetGalleryName + 'trustrepository' = 'true' + } + } + $res = Get-InstalledPSResource -Name 'TestModule99' + $res.Name | Should -Be 'TestModule99' + $res.Version | Should -Be '0.0.93' + } + It 'Install modules using -RequiredResource with JSON string' { $rrJSON = "{ 'test_module': { From 55d38122aae0dc7251d3527f863ba76d307228ff Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 19 Nov 2025 19:34:32 +0000 Subject: [PATCH 4/6] Simplify Scope parameter logic in ProcessInstallHelper Co-authored-by: adityapatwardhan <12820925+adityapatwardhan@users.noreply.github.com> --- src/code/InstallPSResource.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code/InstallPSResource.cs b/src/code/InstallPSResource.cs index 1ddd67412..e2fad301d 100644 --- a/src/code/InstallPSResource.cs +++ b/src/code/InstallPSResource.cs @@ -573,7 +573,7 @@ private void ProcessInstallHelper(string[] pkgNames, string pkgVersion, bool pkg bool trustRepository = reqResourceParams != null ? reqResourceParams.TrustRepository : TrustRepository; bool noClobber = reqResourceParams != null ? reqResourceParams.NoClobber : NoClobber; bool skipDependencyCheck = reqResourceParams != null ? reqResourceParams.SkipDependencyCheck : SkipDependencyCheck; - ScopeType scope = reqResourceParams != null && reqResourceParams.Scope != ScopeType.CurrentUser ? reqResourceParams.Scope : Scope; + ScopeType scope = reqResourceParams != null ? reqResourceParams.Scope : Scope; IEnumerable installedPkgs = _installHelper.BeginInstallPackages( names: pkgNames, From 449530a31fac2dac3f6f153abff2fa041ebc1ca6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 19 Nov 2025 19:38:35 +0000 Subject: [PATCH 5/6] Remove unintended nuget.config changes Co-authored-by: adityapatwardhan <12820925+adityapatwardhan@users.noreply.github.com> --- nuget.config | 1 - 1 file changed, 1 deletion(-) diff --git a/nuget.config b/nuget.config index 759e2aac1..5c704bf46 100644 --- a/nuget.config +++ b/nuget.config @@ -2,7 +2,6 @@ - From 077dc301f3239685faf9726151e40be4be845292 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 20 Nov 2025 20:36:13 +0000 Subject: [PATCH 6/6] Make InstallPkgParams properties nullable to distinguish unset from false This addresses the feedback to check if reqResourceParams properties are null. Now the code can distinguish between: - User didn't specify the property (null) -> use cmdlet-level parameter - User explicitly set the property to true/false -> use that value Changed properties to nullable (bool?, ScopeType?) and updated logic to only set them when explicitly provided in the RequiredResource hashtable. Co-authored-by: alerickson <25858831+alerickson@users.noreply.github.com> --- src/code/InstallPSResource.cs | 20 +++++++------- src/code/InstallPkgParams.cs | 50 ++++++++++++++++++++++------------- 2 files changed, 41 insertions(+), 29 deletions(-) diff --git a/src/code/InstallPSResource.cs b/src/code/InstallPSResource.cs index e2fad301d..feca62d50 100644 --- a/src/code/InstallPSResource.cs +++ b/src/code/InstallPSResource.cs @@ -487,9 +487,9 @@ private void RequiredResourceHelper(Hashtable reqResourceHash) } } - if (pkgParams.Scope == ScopeType.AllUsers) + if (pkgParams.Scope.HasValue && pkgParams.Scope.Value == ScopeType.AllUsers) { - _pathsToInstallPkg = Utils.GetAllInstallationPaths(this, pkgParams.Scope); + _pathsToInstallPkg = Utils.GetAllInstallationPaths(this, pkgParams.Scope.Value); } pkgVersion = pkgInstallInfo["version"] == null ? String.Empty : pkgInstallInfo["version"].ToString(); @@ -566,14 +566,14 @@ private void ProcessInstallHelper(string[] pkgNames, string pkgVersion, bool pkg } // When reqResourceParams is provided (via -RequiredResource), use its properties - // instead of the cmdlet-level parameters - bool acceptLicense = reqResourceParams != null ? reqResourceParams.AcceptLicense : AcceptLicense; - bool quiet = reqResourceParams != null ? reqResourceParams.Quiet : Quiet; - bool reinstall = reqResourceParams != null ? reqResourceParams.Reinstall : Reinstall; - bool trustRepository = reqResourceParams != null ? reqResourceParams.TrustRepository : TrustRepository; - bool noClobber = reqResourceParams != null ? reqResourceParams.NoClobber : NoClobber; - bool skipDependencyCheck = reqResourceParams != null ? reqResourceParams.SkipDependencyCheck : SkipDependencyCheck; - ScopeType scope = reqResourceParams != null ? reqResourceParams.Scope : Scope; + // instead of the cmdlet-level parameters. Only use the property if it was explicitly set (not null). + bool acceptLicense = reqResourceParams?.AcceptLicense ?? AcceptLicense; + bool quiet = reqResourceParams?.Quiet ?? Quiet; + bool reinstall = reqResourceParams?.Reinstall ?? Reinstall; + bool trustRepository = reqResourceParams?.TrustRepository ?? TrustRepository; + bool noClobber = reqResourceParams?.NoClobber ?? NoClobber; + bool skipDependencyCheck = reqResourceParams?.SkipDependencyCheck ?? SkipDependencyCheck; + ScopeType scope = reqResourceParams?.Scope ?? Scope; IEnumerable installedPkgs = _installHelper.BeginInstallPackages( names: pkgNames, diff --git a/src/code/InstallPkgParams.cs b/src/code/InstallPkgParams.cs index 7a1b8e986..19cdd076b 100644 --- a/src/code/InstallPkgParams.cs +++ b/src/code/InstallPkgParams.cs @@ -11,15 +11,15 @@ public class InstallPkgParams public string Name { get; set; } public VersionRange Version { get; set; } public string Repository { get; set; } - public bool AcceptLicense { get; set; } + public bool? AcceptLicense { get; set; } public bool Prerelease { get; set; } - public ScopeType Scope { get; set; } - public bool Quiet { get; set; } - public bool Reinstall { get; set; } + public ScopeType? Scope { get; set; } + public bool? Quiet { get; set; } + public bool? Reinstall { get; set; } public bool Force { get; set; } - public bool TrustRepository { get; set; } - public bool NoClobber { get; set; } - public bool SkipDependencyCheck { get; set; } + public bool? TrustRepository { get; set; } + public bool? NoClobber { get; set; } + public bool? SkipDependencyCheck { get; set; } @@ -67,8 +67,10 @@ public void SetProperty(string propertyName, string propertyValue, out ErrorReco break; case "acceptlicense": - bool.TryParse(propertyValue, out bool acceptLicenseTmp); - AcceptLicense = acceptLicenseTmp; + if (!string.IsNullOrWhiteSpace(propertyValue) && bool.TryParse(propertyValue, out bool acceptLicenseTmp)) + { + AcceptLicense = acceptLicenseTmp; + } break; case "prerelease": @@ -82,28 +84,38 @@ public void SetProperty(string propertyName, string propertyValue, out ErrorReco break; case "quiet": - bool.TryParse(propertyValue, out bool quietTmp); - Quiet = quietTmp; + if (!string.IsNullOrWhiteSpace(propertyValue) && bool.TryParse(propertyValue, out bool quietTmp)) + { + Quiet = quietTmp; + } break; case "reinstall": - bool.TryParse(propertyValue, out bool reinstallTmp); - Reinstall = reinstallTmp; + if (!string.IsNullOrWhiteSpace(propertyValue) && bool.TryParse(propertyValue, out bool reinstallTmp)) + { + Reinstall = reinstallTmp; + } break; case "trustrepository": - bool.TryParse(propertyValue, out bool trustRepositoryTmp); - TrustRepository = trustRepositoryTmp; + if (!string.IsNullOrWhiteSpace(propertyValue) && bool.TryParse(propertyValue, out bool trustRepositoryTmp)) + { + TrustRepository = trustRepositoryTmp; + } break; case "noclobber": - bool.TryParse(propertyValue, out bool noClobberTmp); - NoClobber = noClobberTmp; + if (!string.IsNullOrWhiteSpace(propertyValue) && bool.TryParse(propertyValue, out bool noClobberTmp)) + { + NoClobber = noClobberTmp; + } break; case "skipdependencycheck": - bool.TryParse(propertyValue, out bool skipDependencyCheckTmp); - SkipDependencyCheck = skipDependencyCheckTmp; + if (!string.IsNullOrWhiteSpace(propertyValue) && bool.TryParse(propertyValue, out bool skipDependencyCheckTmp)) + { + SkipDependencyCheck = skipDependencyCheckTmp; + } break; default: