From b0bcb3be52ec866298b8afc388508f15517dca84 Mon Sep 17 00:00:00 2001 From: alerickson <25858831+alerickson@users.noreply.github.com> Date: Tue, 1 Aug 2023 13:48:17 -0700 Subject: [PATCH 1/9] Bug fix for parsing required modules when publishing --- src/code/PublishPSResource.cs | 36 +++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/src/code/PublishPSResource.cs b/src/code/PublishPSResource.cs index 36530b07c..aba924af2 100644 --- a/src/code/PublishPSResource.cs +++ b/src/code/PublishPSResource.cs @@ -780,8 +780,8 @@ private Hashtable ParseRequiredModules(Hashtable parsedMetadataHash) if (!parsedMetadataHash.ContainsKey("requiredmodules")) { return null; - } - var requiredModules = parsedMetadataHash["requiredmodules"]; + } + LanguagePrimitives.TryConvertTo(parsedMetadataHash["requiredmodules"], out object[] requiredModules); // Required modules can be: // a. An array of hash tables of module name and version @@ -790,23 +790,27 @@ private Hashtable ParseRequiredModules(Hashtable parsedMetadataHash) // d. A single string module name var dependenciesHash = new Hashtable(); - if (LanguagePrimitives.TryConvertTo(requiredModules, out Hashtable[] moduleList)) + foreach (var reqModule in requiredModules) { - // instead of returning an array of hashtables, - // loop through the array and add each element of - foreach (Hashtable hash in moduleList) + if (LanguagePrimitives.TryConvertTo(reqModule, out Hashtable moduleHash)) { - dependenciesHash.Add(hash["ModuleName"], hash["ModuleVersion"]); + if (moduleHash.ContainsKey("ModuleVersion")) + { + dependenciesHash.Add(moduleHash["ModuleName"], moduleHash["ModuleVersion"]); + } + else if (moduleHash.ContainsKey("RequiredVersion")) + { + dependenciesHash.Add(moduleHash["ModuleName"], moduleHash["RequiredVersion"]); + } + else { + dependenciesHash.Add(moduleHash["ModuleName"], string.Empty); + } } - } - else if (LanguagePrimitives.TryConvertTo(requiredModules, out string[] moduleNames)) - { - foreach (var modName in moduleNames) + else if (LanguagePrimitives.TryConvertTo(reqModule, out string moduleName)) { - dependenciesHash.Add(modName, string.Empty); + dependenciesHash.Add(moduleName, string.Empty); } } - var externalModuleDeps = parsedMetadataHash.ContainsKey("ExternalModuleDependencies") ? parsedMetadataHash["ExternalModuleDependencies"] : null; @@ -832,7 +836,7 @@ private bool CheckDependenciesExist(Hashtable dependencies, string repositoryNam foreach (var dependency in dependencies.Keys) { // Need to make individual calls since we're look for exact version numbers or ranges. - var depName = new[] { (string)dependency }; + var depName = dependency as string; // test version string depVersion = dependencies[dependency] as string; depVersion = string.IsNullOrWhiteSpace(depVersion) ? "*" : depVersion; @@ -857,11 +861,11 @@ private bool CheckDependenciesExist(Hashtable dependencies, string repositoryNam var repository = new[] { repositoryName }; // Note: we set prerelease argument for FindByResourceName() to true because if no version is specified we want latest version (including prerelease). // If version is specified it will get that one. There is also no way to specify a prerelease flag with RequiredModules hashtable of dependency so always try to get latest version. - var dependencyFound = findHelper.FindByResourceName(depName, ResourceType.Module, versionRange, nugetVersion, versionType, depVersion, prerelease: true, tag: null, repository, includeDependencies: false); + var dependencyFound = findHelper.FindByResourceName(new string[] { depName }, ResourceType.Module, versionRange, nugetVersion, versionType, depVersion, prerelease: true, tag: null, repository, includeDependencies: false); if (dependencyFound == null || !dependencyFound.Any()) { WriteError(new ErrorRecord( - new ArgumentException($"Dependency '{depName.First()}' was not found in repository '{repositoryName}'. Make sure the dependency is published to the repository before publishing this module."), + new ArgumentException($"Dependency '{depName}' was not found in repository '{repositoryName}'. Make sure the dependency is published to the repository before publishing this module."), "DependencyNotFound", ErrorCategory.ObjectNotFound, this)); From 46f51e1b289e60d0166c8c1595081e800a3ef2c9 Mon Sep 17 00:00:00 2001 From: alerickson <25858831+alerickson@users.noreply.github.com> Date: Tue, 1 Aug 2023 14:12:31 -0700 Subject: [PATCH 2/9] add test --- .../PublishPSResource.Tests.ps1 | 32 +++++++++++++++++-- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/test/PublishPSResourceTests/PublishPSResource.Tests.ps1 b/test/PublishPSResourceTests/PublishPSResource.Tests.ps1 index 904dd868f..3d6e4eb23 100644 --- a/test/PublishPSResourceTests/PublishPSResource.Tests.ps1 +++ b/test/PublishPSResourceTests/PublishPSResource.Tests.ps1 @@ -4,8 +4,6 @@ $modPath = "$psscriptroot/../PSGetTestUtils.psm1" Import-Module $modPath -Force -Verbose -$testDir = (get-item $psscriptroot).parent.FullName - function CreateTestModule { param ( @@ -543,7 +541,7 @@ Describe "Test Publish-PSResource" -tags 'CI' { (Get-ChildItem $script:repositoryPath).FullName | Should -Be $expectedPath } - It "should publish a script with sExternalModuleDependencies that are not published" { + It "should publish a script with ExternalModuleDependencies that are not published" { $scriptName = "test" $scriptVersion = "1.0.0" $scriptPath = Join-Path -Path $script:testScriptsFolderPath -ChildPath "$scriptName.ps1" @@ -671,4 +669,32 @@ Describe "Test Publish-PSResource" -tags 'CI' { $expectedPath = Join-Path -Path $script:repositoryPath2 -ChildPath "$ParentModuleName.$ParentVersion.nupkg" (Get-ChildItem $script:repositoryPath2).FullName | Should -Contain $expectedPath } + + It "Publish a module with required modules (both in string format and hashtable format)" { + # look at functions in test utils for creating a module with prerelease + $ModuleName = "ParentModule" + $ModuleVersion = "1.0.0" + $ModuleRoot = Join-Path -Path $script:PublishModuleBase -ChildPath $ModuleName + $ModuleManifestPath = Join-Path -Path $ModuleRoot -ChildPath "$ModuleName.psd1" + + $ReqModule1Name = "ReqModule1" + $ReqModule1Version = "3.0.0" + $ReqModule1Root = Join-Path -Path $script:PublishModuleBase -ChildPath $ReqModule1Name + $ReqModule1ManifestPath = Join-Path -Path $ReqModule1Root -ChildPath "$ReqModule1Name.psd1" + + $ReqModule2Name = "ReqModule2" + $ReqModule2Root = Join-Path -Path $script:PublishModuleBase -ChildPath $ReqModule2Name + $ReqModule2ManifestPath = Join-Path -Path $reqModule2Root -ChildPath "$ReqModule2Name.psd1" + + New-ModuleManifest -Path $ModuleManifestPath -ModuleVersion $ModuleVersion -Description "$ModuleName module" -RequiredModules @( @{"ModuleName" = $ReqModule1Name; "ModuleVersion" = $ReqModule1Version}, $ReqModule2Name ) + New-ModuleManifest -Path $ReqModule1ManifestPath -ModuleVersion $ModuleVersion -Description "$ModuleName module" -RequiredModules @( @{"ModuleName" = $ReqModule1Name; "ModuleVersion" = $ReqModule1Version}, $ReqModule2Name ) + New-ModuleManifest -Path $ReqModule2ManifestPath -ModuleVersion $ModuleVersion -Description "$ModuleName module" -RequiredModules @( @{"ModuleName" = $ReqModule1Name; "ModuleVersion" = $ReqModule1Version}, $ReqModule2Name ) + + Publish-PSResource -Path $ReqModule1ManifestPath -Repository $testRepository2 + Publish-PSResource -Path $ReqModule2ManifestPath -Repository $testRepository2 + Publish-PSResource -Path $ModuleManifestPath -Repository $testRepository2 + + $expectedPath = Join-Path -Path $script:repositoryPath2 -ChildPath "$ModuleName.$ModuleVersion.nupkg" + (Get-ChildItem $script:repositoryPath2).FullName | Should -Contain $expectedPath + } } From 359d845d6ed608a2f37530308ae86a8a1e7b7d91 Mon Sep 17 00:00:00 2001 From: alerickson <25858831+alerickson@users.noreply.github.com> Date: Tue, 1 Aug 2023 14:44:28 -0700 Subject: [PATCH 3/9] add test drive that was accidentally deleted --- test/PublishPSResourceTests/PublishPSResource.Tests.ps1 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/PublishPSResourceTests/PublishPSResource.Tests.ps1 b/test/PublishPSResourceTests/PublishPSResource.Tests.ps1 index 3d6e4eb23..b9d64647e 100644 --- a/test/PublishPSResourceTests/PublishPSResource.Tests.ps1 +++ b/test/PublishPSResourceTests/PublishPSResource.Tests.ps1 @@ -4,6 +4,8 @@ $modPath = "$psscriptroot/../PSGetTestUtils.psm1" Import-Module $modPath -Force -Verbose +$testDir = (get-item $psscriptroot).parent.FullName + function CreateTestModule { param ( From 7a5d38e1a923a4aee77cb6cd399f5f02f04e1f7f Mon Sep 17 00:00:00 2001 From: alerickson <25858831+alerickson@users.noreply.github.com> Date: Tue, 1 Aug 2023 15:06:14 -0700 Subject: [PATCH 4/9] Fix test --- test/PublishPSResourceTests/PublishPSResource.Tests.ps1 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/PublishPSResourceTests/PublishPSResource.Tests.ps1 b/test/PublishPSResourceTests/PublishPSResource.Tests.ps1 index b9d64647e..80c83b259 100644 --- a/test/PublishPSResourceTests/PublishPSResource.Tests.ps1 +++ b/test/PublishPSResourceTests/PublishPSResource.Tests.ps1 @@ -677,15 +677,18 @@ Describe "Test Publish-PSResource" -tags 'CI' { $ModuleName = "ParentModule" $ModuleVersion = "1.0.0" $ModuleRoot = Join-Path -Path $script:PublishModuleBase -ChildPath $ModuleName + New-Item $ModuleRoot -ItemType Directory $ModuleManifestPath = Join-Path -Path $ModuleRoot -ChildPath "$ModuleName.psd1" $ReqModule1Name = "ReqModule1" $ReqModule1Version = "3.0.0" $ReqModule1Root = Join-Path -Path $script:PublishModuleBase -ChildPath $ReqModule1Name + New-Item $ReqModule1Root -ItemType Directory $ReqModule1ManifestPath = Join-Path -Path $ReqModule1Root -ChildPath "$ReqModule1Name.psd1" $ReqModule2Name = "ReqModule2" $ReqModule2Root = Join-Path -Path $script:PublishModuleBase -ChildPath $ReqModule2Name + New-Item $ReqModule2Root -ItemType Directory $ReqModule2ManifestPath = Join-Path -Path $reqModule2Root -ChildPath "$ReqModule2Name.psd1" New-ModuleManifest -Path $ModuleManifestPath -ModuleVersion $ModuleVersion -Description "$ModuleName module" -RequiredModules @( @{"ModuleName" = $ReqModule1Name; "ModuleVersion" = $ReqModule1Version}, $ReqModule2Name ) From 50ed9c2c325af3721a17298990d43615811619ad Mon Sep 17 00:00:00 2001 From: alerickson <25858831+alerickson@users.noreply.github.com> Date: Tue, 1 Aug 2023 15:34:34 -0700 Subject: [PATCH 5/9] update test --- test/PublishPSResourceTests/PublishPSResource.Tests.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/PublishPSResourceTests/PublishPSResource.Tests.ps1 b/test/PublishPSResourceTests/PublishPSResource.Tests.ps1 index 80c83b259..804c54459 100644 --- a/test/PublishPSResourceTests/PublishPSResource.Tests.ps1 +++ b/test/PublishPSResourceTests/PublishPSResource.Tests.ps1 @@ -692,8 +692,8 @@ Describe "Test Publish-PSResource" -tags 'CI' { $ReqModule2ManifestPath = Join-Path -Path $reqModule2Root -ChildPath "$ReqModule2Name.psd1" New-ModuleManifest -Path $ModuleManifestPath -ModuleVersion $ModuleVersion -Description "$ModuleName module" -RequiredModules @( @{"ModuleName" = $ReqModule1Name; "ModuleVersion" = $ReqModule1Version}, $ReqModule2Name ) - New-ModuleManifest -Path $ReqModule1ManifestPath -ModuleVersion $ModuleVersion -Description "$ModuleName module" -RequiredModules @( @{"ModuleName" = $ReqModule1Name; "ModuleVersion" = $ReqModule1Version}, $ReqModule2Name ) - New-ModuleManifest -Path $ReqModule2ManifestPath -ModuleVersion $ModuleVersion -Description "$ModuleName module" -RequiredModules @( @{"ModuleName" = $ReqModule1Name; "ModuleVersion" = $ReqModule1Version}, $ReqModule2Name ) + New-ModuleManifest -Path $ReqModule1ManifestPath -ModuleVersion $ReqModule1Version -Description "$ReqModule1Name module" + New-ModuleManifest -Path $ReqModule2ManifestPath -Description "$ReqModule1Name module" Publish-PSResource -Path $ReqModule1ManifestPath -Repository $testRepository2 Publish-PSResource -Path $ReqModule2ManifestPath -Repository $testRepository2 From 2e2bd41d36edb80a1ca51bb02d41c87b745de4fc Mon Sep 17 00:00:00 2001 From: alerickson <25858831+alerickson@users.noreply.github.com> Date: Tue, 1 Aug 2023 16:50:23 -0700 Subject: [PATCH 6/9] Update test --- .../PublishPSResource.Tests.ps1 | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/test/PublishPSResourceTests/PublishPSResource.Tests.ps1 b/test/PublishPSResourceTests/PublishPSResource.Tests.ps1 index 804c54459..2e25b1429 100644 --- a/test/PublishPSResourceTests/PublishPSResource.Tests.ps1 +++ b/test/PublishPSResourceTests/PublishPSResource.Tests.ps1 @@ -89,6 +89,8 @@ Describe "Test Publish-PSResource" -tags 'CI' { } # Path to folder, within our test folder, where we store invalid module and script files used for testing + $testDir = (get-item $psscriptroot).parent.FullName + $script:testFilesFolderPath = Join-Path $testDir -ChildPath "testFiles" # Path to specifically to that invalid test modules folder @@ -98,7 +100,7 @@ Describe "Test Publish-PSResource" -tags 'CI' { $script:testScriptsFolderPath = Join-Path $script:testFilesFolderPath -ChildPath "testScripts" # Create test module with missing required module - CreateTestModule -Path $TestDrive -ModuleName 'ModuleWithMissingRequiredModule' + #CreateTestModule -Path $TestDrive -ModuleName 'ModuleWithMissingRequiredModule' } AfterAll { Get-RevertPSResourceRepositoryFile @@ -691,12 +693,16 @@ Describe "Test Publish-PSResource" -tags 'CI' { New-Item $ReqModule2Root -ItemType Directory $ReqModule2ManifestPath = Join-Path -Path $reqModule2Root -ChildPath "$ReqModule2Name.psd1" - New-ModuleManifest -Path $ModuleManifestPath -ModuleVersion $ModuleVersion -Description "$ModuleName module" -RequiredModules @( @{"ModuleName" = $ReqModule1Name; "ModuleVersion" = $ReqModule1Version}, $ReqModule2Name ) + New-ModuleManifest -Path $ModuleManifestPath -ModuleVersion $ModuleVersion -Description "$ModuleName module" -RequiredModules @( @{ "ModuleName" = $ReqModule1Name; "ModuleVersion" = $ReqModule1Version }, $ReqModule2Name ) New-ModuleManifest -Path $ReqModule1ManifestPath -ModuleVersion $ReqModule1Version -Description "$ReqModule1Name module" New-ModuleManifest -Path $ReqModule2ManifestPath -Description "$ReqModule1Name module" - + Publish-PSResource -Path $ReqModule1ManifestPath -Repository $testRepository2 Publish-PSResource -Path $ReqModule2ManifestPath -Repository $testRepository2 + + Install-PSResource $ReqModule1Name -Repository $testRepository2 -TrustRepository + Install-PSResource $ReqModule2Name -Repository $testRepository2 -TrustRepository + Publish-PSResource -Path $ModuleManifestPath -Repository $testRepository2 $expectedPath = Join-Path -Path $script:repositoryPath2 -ChildPath "$ModuleName.$ModuleVersion.nupkg" From cd0695051fde160113f0f8c062e6d41215deb68c Mon Sep 17 00:00:00 2001 From: alerickson <25858831+alerickson@users.noreply.github.com> Date: Tue, 1 Aug 2023 17:09:12 -0700 Subject: [PATCH 7/9] Update test --- test/PublishPSResourceTests/PublishPSResource.Tests.ps1 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/PublishPSResourceTests/PublishPSResource.Tests.ps1 b/test/PublishPSResourceTests/PublishPSResource.Tests.ps1 index 2e25b1429..a6791e539 100644 --- a/test/PublishPSResourceTests/PublishPSResource.Tests.ps1 +++ b/test/PublishPSResourceTests/PublishPSResource.Tests.ps1 @@ -89,8 +89,6 @@ Describe "Test Publish-PSResource" -tags 'CI' { } # Path to folder, within our test folder, where we store invalid module and script files used for testing - $testDir = (get-item $psscriptroot).parent.FullName - $script:testFilesFolderPath = Join-Path $testDir -ChildPath "testFiles" # Path to specifically to that invalid test modules folder @@ -100,7 +98,7 @@ Describe "Test Publish-PSResource" -tags 'CI' { $script:testScriptsFolderPath = Join-Path $script:testFilesFolderPath -ChildPath "testScripts" # Create test module with missing required module - #CreateTestModule -Path $TestDrive -ModuleName 'ModuleWithMissingRequiredModule' + CreateTestModule -Path $TestDrive -ModuleName 'ModuleWithMissingRequiredModule' } AfterAll { Get-RevertPSResourceRepositoryFile From 94c8ad9212103fd5b1bbff84573b227dabb56d23 Mon Sep 17 00:00:00 2001 From: alerickson <25858831+alerickson@users.noreply.github.com> Date: Thu, 3 Aug 2023 12:23:17 -0700 Subject: [PATCH 8/9] Iterate through hashtable instead of hashtable keys --- src/code/PublishPSResource.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/code/PublishPSResource.cs b/src/code/PublishPSResource.cs index aba924af2..f3508cc96 100644 --- a/src/code/PublishPSResource.cs +++ b/src/code/PublishPSResource.cs @@ -833,10 +833,10 @@ private bool CheckDependenciesExist(Hashtable dependencies, string repositoryNam // Check to see that all dependencies are in the repository // Searches for each dependency in the repository the pkg is being pushed to, // If the dependency is not there, error - foreach (var dependency in dependencies.Keys) + foreach (DictionaryEntry dependency in dependencies) { // Need to make individual calls since we're look for exact version numbers or ranges. - var depName = dependency as string; + var depName = dependency.Key as string; // test version string depVersion = dependencies[dependency] as string; depVersion = string.IsNullOrWhiteSpace(depVersion) ? "*" : depVersion; From 2dfa1c75437554722f6181e7a2e3330460ee67c3 Mon Sep 17 00:00:00 2001 From: alerickson <25858831+alerickson@users.noreply.github.com> Date: Thu, 3 Aug 2023 12:48:53 -0700 Subject: [PATCH 9/9] Update variable name --- src/code/PublishPSResource.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/code/PublishPSResource.cs b/src/code/PublishPSResource.cs index f3508cc96..ed92d5a58 100644 --- a/src/code/PublishPSResource.cs +++ b/src/code/PublishPSResource.cs @@ -794,16 +794,18 @@ private Hashtable ParseRequiredModules(Hashtable parsedMetadataHash) { if (LanguagePrimitives.TryConvertTo(reqModule, out Hashtable moduleHash)) { + string moduleName = moduleHash["ModuleName"] as string; + if (moduleHash.ContainsKey("ModuleVersion")) { - dependenciesHash.Add(moduleHash["ModuleName"], moduleHash["ModuleVersion"]); + dependenciesHash.Add(moduleName, moduleHash["ModuleVersion"]); } else if (moduleHash.ContainsKey("RequiredVersion")) { - dependenciesHash.Add(moduleHash["ModuleName"], moduleHash["RequiredVersion"]); + dependenciesHash.Add(moduleName, moduleHash["RequiredVersion"]); } else { - dependenciesHash.Add(moduleHash["ModuleName"], string.Empty); + dependenciesHash.Add(moduleName, string.Empty); } } else if (LanguagePrimitives.TryConvertTo(reqModule, out string moduleName)) @@ -838,7 +840,7 @@ private bool CheckDependenciesExist(Hashtable dependencies, string repositoryNam // Need to make individual calls since we're look for exact version numbers or ranges. var depName = dependency.Key as string; // test version - string depVersion = dependencies[dependency] as string; + string depVersion = dependencies[depName] as string; depVersion = string.IsNullOrWhiteSpace(depVersion) ? "*" : depVersion; if (!Utils.TryGetVersionType(