Skip to content

Commit

Permalink
Merge pull request #1784 from afroz429/afroz429-requiredmodules-requi…
Browse files Browse the repository at this point in the history
…redversion

Fixes bug with nuspec dependency version range calculation for RequiredModules
  • Loading branch information
anamnavi authored Mar 5, 2025
2 parents 6915968 + 3d28e75 commit 5de7cbe
Show file tree
Hide file tree
Showing 2 changed files with 224 additions and 12 deletions.
58 changes: 46 additions & 12 deletions src/code/PublishHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1122,20 +1122,47 @@ private string CreateNuspec(
if (requiredModules != null)
{
XmlElement dependenciesElement = doc.CreateElement("dependencies", nameSpaceUri);

foreach (string dependencyName in requiredModules.Keys)
{
XmlElement element = doc.CreateElement("dependency", nameSpaceUri);

element.SetAttribute("id", dependencyName);

string dependencyVersion = requiredModules[dependencyName].ToString();
if (!string.IsNullOrEmpty(dependencyVersion))
{
element.SetAttribute("version", requiredModules[dependencyName].ToString());
var requiredModulesVersionInfo = (Hashtable)requiredModules[dependencyName];
string versionRange = String.Empty;
if (requiredModulesVersionInfo.ContainsKey("RequiredVersion"))
{
// For RequiredVersion, use exact version notation [x.x.x]
string requiredModulesVersion = requiredModulesVersionInfo["RequiredVersion"].ToString();
versionRange = $"[{requiredModulesVersion}]";
}
else if (requiredModulesVersionInfo.ContainsKey("ModuleVersion") && requiredModulesVersionInfo.ContainsKey("MaximumVersion"))
{
// Version range when both min and max specified: [min,max]
versionRange = $"[{requiredModulesVersionInfo["ModuleVersion"]}, {requiredModulesVersionInfo["MaximumVersion"]}]";
}
else if (requiredModulesVersionInfo.ContainsKey("ModuleVersion"))
{
// Only min specified: min (which means ≥ min)
versionRange = requiredModulesVersionInfo["ModuleVersion"].ToString();
}
else if (requiredModulesVersionInfo.ContainsKey("MaximumVersion"))
{
// Only max specified: (, max]
versionRange = $"(, {requiredModulesVersionInfo["MaximumVersion"]}]";
}

if (!string.IsNullOrEmpty(versionRange))
{
element.SetAttribute("version", versionRange);
}
}

dependenciesElement.AppendChild(element);
}

metadataElement.AppendChild(dependenciesElement);
}

Expand Down Expand Up @@ -1173,19 +1200,26 @@ private Hashtable ParseRequiredModules(Hashtable parsedMetadataHash)
if (LanguagePrimitives.TryConvertTo<Hashtable>(reqModule, out Hashtable moduleHash))
{
string moduleName = moduleHash["ModuleName"] as string;

if (moduleHash.ContainsKey("ModuleVersion"))
var versionInfo = new Hashtable();

// RequiredVersion cannot be used with ModuleVersion or MaximumVersion
if (moduleHash.ContainsKey("RequiredVersion"))
{
dependenciesHash.Add(moduleName, moduleHash["ModuleVersion"]);
versionInfo["RequiredVersion"] = moduleHash["RequiredVersion"].ToString();
}
else if (moduleHash.ContainsKey("RequiredVersion"))
else
{
dependenciesHash.Add(moduleName, moduleHash["RequiredVersion"]);
}
else
{
dependenciesHash.Add(moduleName, string.Empty);
// ModuleVersion and MaximumVersion can be used together
if (moduleHash.ContainsKey("ModuleVersion"))
{
versionInfo["ModuleVersion"] = moduleHash["ModuleVersion"].ToString();
}
if (moduleHash.ContainsKey("MaximumVersion"))
{
versionInfo["MaximumVersion"] = moduleHash["MaximumVersion"].ToString();
}
}
dependenciesHash.Add(moduleName, versionInfo);
}
else if (LanguagePrimitives.TryConvertTo<string>(reqModule, out string moduleName))
{
Expand Down
178 changes: 178 additions & 0 deletions test/PublishPSResourceTests/CompressPSResource.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,39 @@ function CreateTestModule
'@ | Out-File -FilePath $moduleSrc
}

function CompressExpandRetrieveNuspec
{
param(
[string]$PublishModuleBase,
[string]$PublishModuleName,
[string]$ModuleVersion,
[string]$RepositoryPath,
[string]$ModuleBasePath,
[string]$TestDrive,
[object[]]$RequiredModules,
[switch]$SkipModuleManifestValidate
)

$testFile = Join-Path -Path "TestSubDirectory" -ChildPath "TestSubDirFile.ps1"
$null = New-ModuleManifest -Path (Join-Path -Path $PublishModuleBase -ChildPath "$PublishModuleName.psd1") -ModuleVersion $version -Description "$PublishModuleName module" -RequiredModules $RequiredModules
$null = New-Item -Path (Join-Path -Path $PublishModuleBase -ChildPath $testFile) -Force

$null = Compress-PSResource -Path $PublishModuleBase -DestinationPath $repositoryPath -SkipModuleManifestValidate:$SkipModuleManifestValidate

# Must change .nupkg to .zip so that Expand-Archive can work on Windows PowerShell
$nupkgPath = Join-Path -Path $RepositoryPath -ChildPath "$PublishModuleName.$version.nupkg"
$zipPath = Join-Path -Path $RepositoryPath -ChildPath "$PublishModuleName.$version.zip"
Rename-Item -Path $nupkgPath -NewName $zipPath
$unzippedPath = Join-Path -Path $TestDrive -ChildPath "$PublishModuleName"
$null = New-Item $unzippedPath -Itemtype directory -Force
$null = Expand-Archive -Path $zipPath -DestinationPath $unzippedPath

$nuspecPath = Join-Path -Path $unzippedPath -ChildPath "$PublishModuleName.nuspec"
$nuspecxml = [xml](Get-Content $nuspecPath)
$null = Remove-Item $unzippedPath -Force -Recurse
return $nuspecxml
}

Describe "Test Compress-PSResource" -tags 'CI' {
BeforeAll {
Get-NewPSResourceRepositoryFile
Expand Down Expand Up @@ -152,6 +185,7 @@ Describe "Test Compress-PSResource" -tags 'CI' {
Expand-Archive -Path $zipPath -DestinationPath $unzippedPath

Test-Path -Path (Join-Path -Path $unzippedPath -ChildPath $testFile) | Should -Be $True
$null = Remove-Item $unzippedPath -Force -Recurse
}

It "Compresses a script" {
Expand Down Expand Up @@ -218,6 +252,150 @@ Describe "Test Compress-PSResource" -tags 'CI' {
$fileInfoObject.Name | Should -Be "$script:PublishModuleName.$version.nupkg"
}

It "Compress-PSResource creates nuspec dependecy version range when RequiredVersion is in RequiredModules section" {
$version = "1.0.0"
$requiredModules = @(
@{
'ModuleName' = 'PSGetTestRequiredModule'
'GUID' = (New-Guid).Guid
'RequiredVersion' = '2.0.0'
}
)
$compressParams = @{
'PublishModuleBase' = $script:PublishModuleBase
'PublishModuleName' = $script:PublishModuleName
'ModuleVersion' = $version
'RepositoryPath' = $script:repositoryPath
'TestDrive' = $TestDrive
'RequiredModules' = $requiredModules
'SkipModuleManifestValidate' = $true
}
$nuspecxml = CompressExpandRetrieveNuspec @compressParams
# removing spaces as the nuget packaging is formatting the version range and adding spaces even when the original nuspec file doesn't have spaces.
# e.g (,2.0.0] is being formatted to (, 2.0.0]
$nuspecxml.package.metadata.dependencies.dependency.version.replace(' ', '') | Should -BeExactly '[2.0.0]'
}

It "Compress-PSResource creates nuspec dependecy version range when ModuleVersion is in RequiredModules section" {
$version = "1.0.0"
$requiredModules = @(
@{
'ModuleName' = 'PSGetTestRequiredModule'
'GUID' = (New-Guid).Guid
'ModuleVersion' = '2.0.0'
}
)
$compressParams = @{
'PublishModuleBase' = $script:PublishModuleBase
'PublishModuleName' = $script:PublishModuleName
'ModuleVersion' = $version
'RepositoryPath' = $script:repositoryPath
'TestDrive' = $TestDrive
'RequiredModules' = $requiredModules
'SkipModuleManifestValidate' = $true
}
$nuspecxml = CompressExpandRetrieveNuspec @compressParams
$nuspecxml.package.metadata.dependencies.dependency.version.replace(' ', '') | Should -BeExactly '2.0.0'
}

It "Compress-PSResource creates nuspec dependecy version range when MaximumVersion is in RequiredModules section" {
$version = "1.0.0"
$requiredModules = @(
@{
'ModuleName' = 'PSGetTestRequiredModule'
'GUID' = (New-Guid).Guid
'MaximumVersion' = '2.0.0'
}
)
$compressParams = @{
'PublishModuleBase' = $script:PublishModuleBase
'PublishModuleName' = $script:PublishModuleName
'ModuleVersion' = $version
'RepositoryPath' = $script:repositoryPath
'TestDrive' = $TestDrive
'RequiredModules' = $requiredModules
'SkipModuleManifestValidate' = $true
}
$nuspecxml = CompressExpandRetrieveNuspec @compressParams
$nuspecxml.package.metadata.dependencies.dependency.version.replace(' ', '') | Should -BeExactly '(,2.0.0]'
}

It "Compress-PSResource creates nuspec dependecy version range when ModuleVersion and MaximumVersion are in RequiredModules section" {
$version = "1.0.0"
$requiredModules = @(
@{
'ModuleName' = 'PSGetTestRequiredModule'
'GUID' = (New-Guid).Guid
'ModuleVersion' = '1.0.0'
'MaximumVersion' = '2.0.0'
}
)
$compressParams = @{
'PublishModuleBase' = $script:PublishModuleBase
'PublishModuleName' = $script:PublishModuleName
'ModuleVersion' = $version
'RepositoryPath' = $script:repositoryPath
'TestDrive' = $TestDrive
'RequiredModules' = $requiredModules
'SkipModuleManifestValidate' = $true
}
$nuspecxml = CompressExpandRetrieveNuspec @compressParams
$nuspecxml.package.metadata.dependencies.dependency.version.replace(' ', '') | Should -BeExactly '[1.0.0,2.0.0]'
}

It "Compress-PSResource creates nuspec dependecy version range when there are multiple modules in RequiredModules section" {
$version = "1.0.0"
$requiredModules = @(
@{
'ModuleName' = 'PSGetTestRequiredModuleRequiredVersion'
'GUID' = (New-Guid).Guid
'RequiredVersion' = '1.0.0'
},
@{
'ModuleName' = 'PSGetTestRequiredModuleModuleVersion'
'GUID' = (New-Guid).Guid
'ModuleVersion' = '2.0.0'
},
@{
'ModuleName' = 'PSGetTestRequiredModuleMaximumVersion'
'GUID' = (New-Guid).Guid
'MaximumVersion' = '3.0.0'
},
@{
'ModuleName' = 'PSGetTestRequiredModuleModuleAndMaximumVersion'
'GUID' = (New-Guid).Guid
'ModuleVersion' = '4.0.0'
'MaximumVersion' = '5.0.0'
}
)
$compressParams = @{
'PublishModuleBase' = $script:PublishModuleBase
'PublishModuleName' = $script:PublishModuleName
'ModuleVersion' = $version
'RepositoryPath' = $script:repositoryPath
'TestDrive' = $TestDrive
'RequiredModules' = $requiredModules
'SkipModuleManifestValidate' = $true
}
$nuspecxml = CompressExpandRetrieveNuspec @compressParams
foreach ($dependency in $nuspecxml.package.metadata.dependencies.dependency) {
switch ($dependency.id) {
"PSGetTestRequiredModuleRequiredVersion" {
$dependency.version.replace(' ', '') | Should -BeExactly '[1.0.0]'
}
"PSGetTestRequiredModuleModuleVersion" {
$dependency.version.replace(' ', '') | Should -BeExactly '2.0.0'
}
"PSGetTestRequiredModuleMaximumVersion" {
$dependency.version.replace(' ', '') | Should -BeExactly '(,3.0.0]'
}
"PSGetTestRequiredModuleModuleAndMaximumVersion" {
$dependency.version.replace(' ', '') | Should -BeExactly '[4.0.0,5.0.0]'
}
}
}
}

<# Test for Signing the nupkg. Signing doesn't work
It "Compressed Module is able to be signed with a certificate" {
$version = "1.0.0"
Expand Down

0 comments on commit 5de7cbe

Please sign in to comment.