Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions src/private/package/GetNovaPackageUploadFileInfo.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
function Get-NovaPackageUploadFileInfo {
[CmdletBinding()]
param(
[Parameter(Mandatory)][string]$PackageType,
[Parameter(Mandatory)][string]$PackagePath,
[string]$PackageFileName
)

$resolvedPackageFileName = $PackageFileName
if ( [string]::IsNullOrWhiteSpace($resolvedPackageFileName)) {
$resolvedPackageFileName = [System.IO.Path]::GetFileName($PackagePath)
}

return [pscustomobject]@{
Type = $PackageType
PackagePath = $PackagePath
PackageFileName = $resolvedPackageFileName
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
function Get-NovaPackageUploadOutputDirectoryFileList {
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '', Justification = 'Package upload output directory file list is the domain term represented by this helper.')]
[CmdletBinding()]
param(
[Parameter(Mandatory)][string]$OutputDirectory,
[Parameter(Mandatory)][string]$SearchPattern,
[Parameter(Mandatory)][string]$PackageType
)

$matchingFileList = @(
Get-ChildItem -LiteralPath $OutputDirectory -File -ErrorAction Stop |
Where-Object {$_.Name -like $SearchPattern} |
Sort-Object Name
)

if ($matchingFileList.Count -eq 0) {
Stop-NovaOperation -Message "Package file not found for package type '$PackageType' in '$OutputDirectory'. Expected pattern: $SearchPattern. Run New-NovaModulePackage first or provide -PackagePath." -ErrorId 'Nova.Workflow.PackageOutputArtifactNotFound' -Category InvalidOperation -TargetObject $PackageType
}

return $matchingFileList
}
15 changes: 15 additions & 0 deletions src/private/package/GetNovaPackageUploadRequestedTypeList.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
function Get-NovaPackageUploadRequestedTypeList {
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '', Justification = 'Package upload requested type list is the domain term represented by this helper.')]
[CmdletBinding()]
param(
[Parameter(Mandatory)][pscustomobject]$ProjectInfo,
[string[]]$PackageType
)

$requestedTypeList = @($PackageType | Where-Object {-not [string]::IsNullOrWhiteSpace("$_")})
if ($requestedTypeList.Count -eq 0) {
return @()
}

return @(Resolve-NovaPackageUploadTypeList -ProjectInfo $ProjectInfo -PackageType $requestedTypeList)
}
7 changes: 1 addition & 6 deletions src/private/package/ResolveNovaPackageUploadExplicitFile.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,5 @@ function Resolve-NovaPackageUploadExplicitFile {
Stop-NovaOperation -Message "Package selection is ambiguous. Explicit PackagePath '$resolvedPackagePath' resolves to type '$resolvedPackageType', but requested PackageType values are: $( $RequestedPackageTypeList -join ', ' )." -ErrorId 'Nova.Validation.PackageUploadSelectionAmbiguous' -Category InvalidArgument -TargetObject $resolvedPackagePath
}

return [pscustomobject]@{
Type = $resolvedPackageType
PackagePath = $resolvedPackagePath
PackageFileName = [System.IO.Path]::GetFileName($resolvedPackagePath)
}
return Get-NovaPackageUploadFileInfo -PackageType $resolvedPackageType -PackagePath $resolvedPackagePath
}

Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@ function Resolve-NovaPackageUploadExplicitFileList {
[string[]]$PackageType
)

$requestedTypeList = @()
if (@($PackageType).Count -gt 0) {
$requestedTypeList = @(Resolve-NovaPackageUploadTypeList -ProjectInfo $ProjectInfo -PackageType $PackageType)
}
$requestedTypeList = @(Get-NovaPackageUploadRequestedTypeList -ProjectInfo $ProjectInfo -PackageType $PackageType)

$resolvedFileList = @(
$PackagePath |
Expand All @@ -20,4 +17,3 @@ function Resolve-NovaPackageUploadExplicitFileList {

return $resolvedFileList
}

Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ function Resolve-NovaPackageUploadOutputFileList {
[string[]]$PackageType
)

$resolvedTypeList = @(Resolve-NovaPackageUploadTypeList -ProjectInfo $ProjectInfo -PackageType $PackageType)
$outputDirectory = Get-NovaPackageOutputDirectory -ProjectInfo $ProjectInfo
if (-not (Test-Path -LiteralPath $outputDirectory -PathType Container)) {
Stop-NovaOperation -Message "Package output directory not found: $outputDirectory. Run New-NovaModulePackage first or provide -PackagePath." -ErrorId 'Nova.Environment.PackageOutputDirectoryNotFound' -Category ObjectNotFound -TargetObject $outputDirectory
}

return @(
@(Resolve-NovaPackageUploadTypeList -ProjectInfo $ProjectInfo -PackageType $PackageType) |
$resolvedTypeList |
ForEach-Object {
Resolve-NovaPackageUploadOutputFileSet -OutputDirectory $outputDirectory -ProjectInfo $ProjectInfo -PackageType $_
}
Expand Down
16 changes: 2 additions & 14 deletions src/private/package/ResolveNovaPackageUploadOutputFileSet.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,11 @@ function Resolve-NovaPackageUploadOutputFileSet {
)

$searchPattern = Get-NovaPackageArtifactSearchPattern -ProjectInfo $ProjectInfo -PackageType $PackageType
$matchingFileList = @(
Get-ChildItem -LiteralPath $OutputDirectory -File -ErrorAction Stop |
Where-Object {$_.Name -like $searchPattern} |
Sort-Object Name
)

if ($matchingFileList.Count -eq 0) {
Stop-NovaOperation -Message "Package file not found for package type '$PackageType' in '$OutputDirectory'. Expected pattern: $searchPattern. Run New-NovaModulePackage first or provide -PackagePath." -ErrorId 'Nova.Workflow.PackageOutputArtifactNotFound' -Category InvalidOperation -TargetObject $PackageType
}
$matchingFileList = @(Get-NovaPackageUploadOutputDirectoryFileList -OutputDirectory $OutputDirectory -SearchPattern $searchPattern -PackageType $PackageType)

return @(
$matchingFileList | ForEach-Object {
[pscustomobject]@{
Type = $PackageType
PackagePath = $_.FullName
PackageFileName = $_.Name
}
Get-NovaPackageUploadFileInfo -PackageType $PackageType -PackagePath $_.FullName -PackageFileName $_.Name
}
)
}
126 changes: 126 additions & 0 deletions tests/NovaCommandModel.PackageUpload.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ foreach ($functionName in $global:novaCommandModelTestSupportFunctionNameList) {
$scriptBlock = (Get-Command -Name $functionName -CommandType Function -ErrorAction Stop).ScriptBlock
Set-Item -Path "function:global:$functionName" -Value $scriptBlock
}

foreach ($functionName in $global:novaCommandModelPackageUploadTestSupportFunctionNameList) {
$scriptBlock = (Get-Command -Name $functionName -CommandType Function -ErrorAction Stop).ScriptBlock
Set-Item -Path "function:global:$functionName" -Value $scriptBlock
Expand Down Expand Up @@ -240,6 +241,131 @@ Describe 'Nova command model - package upload behavior' {
}
}

It 'Get-NovaPackageUploadFileList prefers explicit package paths over output discovery' {
InModuleScope $script:moduleName {
$projectInfo = [pscustomobject]@{ProjectName = 'PackageProject'}
$explicitFileList = @(
[pscustomobject]@{Type = 'Zip'; PackagePath = '/tmp/project/artifacts/packages/PackageProject.2.3.4.zip'; PackageFileName = 'PackageProject.2.3.4.zip'}
)

Mock Resolve-NovaPackageUploadExplicitFileList {$explicitFileList}
Mock Resolve-NovaPackageUploadOutputFileList {throw 'explicit package selection should not fall back to output discovery'}

$result = @(Get-NovaPackageUploadFileList -ProjectInfo $projectInfo -PackagePath @(' ', '/tmp/project/artifacts/packages/PackageProject.2.3.4.zip', '') -PackageType @('Zip'))

$result.PackagePath | Should -Be @('/tmp/project/artifacts/packages/PackageProject.2.3.4.zip')
Assert-MockCalled Resolve-NovaPackageUploadExplicitFileList -Times 1 -ParameterFilter {
$ProjectInfo.ProjectName -eq 'PackageProject' -and
$PackagePath.Count -eq 1 -and
$PackagePath[0] -eq '/tmp/project/artifacts/packages/PackageProject.2.3.4.zip' -and
$PackageType.Count -eq 1 -and
$PackageType[0] -eq 'Zip'
}
Assert-MockCalled Resolve-NovaPackageUploadOutputFileList -Times 0
}
}

It 'Get-NovaPackageUploadFileList falls back to output discovery when explicit package paths are not provided' {
InModuleScope $script:moduleName {
$projectInfo = [pscustomobject]@{ProjectName = 'PackageProject'}
$outputFileList = @(
[pscustomobject]@{Type = 'Zip'; PackagePath = '/tmp/project/artifacts/packages/PackageProject.2.3.4.zip'; PackageFileName = 'PackageProject.2.3.4.zip'}
)

Mock Resolve-NovaPackageUploadExplicitFileList {throw 'output discovery should be used when PackagePath is empty'}
Mock Resolve-NovaPackageUploadOutputFileList {$outputFileList}

$result = @(Get-NovaPackageUploadFileList -ProjectInfo $projectInfo -PackagePath @('', ' ') -PackageType @('Zip'))

$result.PackagePath | Should -Be @('/tmp/project/artifacts/packages/PackageProject.2.3.4.zip')
Assert-MockCalled Resolve-NovaPackageUploadExplicitFileList -Times 0
Assert-MockCalled Resolve-NovaPackageUploadOutputFileList -Times 1 -ParameterFilter {
$ProjectInfo.ProjectName -eq 'PackageProject' -and
$PackageType.Count -eq 1 -and
$PackageType[0] -eq 'Zip'
}
}
}

It 'Get-NovaPackageUploadRequestedTypeList returns an empty list when PackageType is omitted or whitespace' {
InModuleScope $script:moduleName {
$projectInfo = [pscustomobject]@{ProjectName = 'PackageProject'}

Mock Resolve-NovaPackageUploadTypeList {throw 'type resolution should be skipped when no package types were requested'}

$result = @(Get-NovaPackageUploadRequestedTypeList -ProjectInfo $projectInfo -PackageType @('', ' '))

$result.Count | Should -Be 0
Assert-MockCalled Resolve-NovaPackageUploadTypeList -Times 0
}
}

It 'Resolve-NovaPackageUploadExplicitFileList resolves requested types once and deduplicates by package path' {
InModuleScope $script:moduleName {
$projectInfo = [pscustomobject]@{ProjectName = 'PackageProject'}

Mock Get-NovaPackageUploadRequestedTypeList {@('Zip')}
Mock Resolve-NovaPackageUploadExplicitFile {
[pscustomobject]@{
Type = 'Zip'
PackagePath = '/tmp/project/artifacts/packages/PackageProject.2.3.4.zip'
PackageFileName = 'PackageProject.2.3.4.zip'
}
}

$result = @(Resolve-NovaPackageUploadExplicitFileList -ProjectInfo $projectInfo -PackagePath @('/tmp/project/artifacts/packages/PackageProject.2.3.4.zip', './artifacts/packages/PackageProject.2.3.4.zip') -PackageType @('Zip'))

$result.Count | Should -Be 1
$result[0].PackageFileName | Should -Be 'PackageProject.2.3.4.zip'
Assert-MockCalled Get-NovaPackageUploadRequestedTypeList -Times 1 -ParameterFilter {
$ProjectInfo.ProjectName -eq 'PackageProject' -and
$PackageType.Count -eq 1 -and
$PackageType[0] -eq 'Zip'
}
Assert-MockCalled Resolve-NovaPackageUploadExplicitFile -Times 2 -ParameterFilter {
$RequestedPackageTypeList.Count -eq 1 -and
$RequestedPackageTypeList[0] -eq 'Zip'
}
}
}

It 'Resolve-NovaPackageUploadOutputFileList resolves types before discovering artifacts in the output directory' {
InModuleScope $script:moduleName {
$projectInfo = [pscustomobject]@{ProjectName = 'PackageProject'}

Mock Resolve-NovaPackageUploadTypeList {@('NuGet', 'Zip')}
Mock Get-NovaPackageOutputDirectory {'/tmp/project/artifacts/packages'}
Mock Test-Path {$true} -ParameterFilter {$LiteralPath -eq '/tmp/project/artifacts/packages' -and $PathType -eq 'Container'}
Mock Resolve-NovaPackageUploadOutputFileSet {
[pscustomobject]@{
Type = $PackageType
PackagePath = "/tmp/project/artifacts/packages/PackageProject.2.3.4.$($PackageType.ToLower() )"
PackageFileName = "PackageProject.2.3.4.$($PackageType.ToLower() )"
}
}

$result = @(Resolve-NovaPackageUploadOutputFileList -ProjectInfo $projectInfo -PackageType @('NuGet', 'Zip'))

$result.Type | Should -Be @('NuGet', 'Zip')
Assert-MockCalled Resolve-NovaPackageUploadTypeList -Times 1 -ParameterFilter {
$ProjectInfo.ProjectName -eq 'PackageProject' -and
$PackageType.Count -eq 2
}
Assert-MockCalled Resolve-NovaPackageUploadOutputFileSet -Times 1 -ParameterFilter {$PackageType -eq 'NuGet' -and $OutputDirectory -eq '/tmp/project/artifacts/packages'}
Assert-MockCalled Resolve-NovaPackageUploadOutputFileSet -Times 1 -ParameterFilter {$PackageType -eq 'Zip' -and $OutputDirectory -eq '/tmp/project/artifacts/packages'}
}
}

It 'Get-NovaPackageUploadFileInfo falls back to the package path file name when none is provided' {
InModuleScope $script:moduleName {
$result = Get-NovaPackageUploadFileInfo -PackageType 'Zip' -PackagePath '/tmp/project/artifacts/packages/PackageProject.2.3.4.zip'

$result.Type | Should -Be 'Zip'
$result.PackagePath | Should -Be '/tmp/project/artifacts/packages/PackageProject.2.3.4.zip'
$result.PackageFileName | Should -Be 'PackageProject.2.3.4.zip'
}
}

It 'Resolve-NovaPackageUploadTarget resolves target precedence correctly when <Name>' -ForEach (Get-TestNovaPackageUploadTargetResolutionCases) {
$testCase = $_
$layout = Initialize-TestNovaPackageUploadLayout -ProjectRoot (Join-Path $TestDrive $testCase.ProjectRootName)
Expand Down
Loading