Skip to content

Commit 0890639

Browse files
authored
feat(#104): implement package upload file selection utilities (#131)
- Add Get-NovaPackageUploadFileInfo function for package file info retrieval - Introduce Get-NovaPackageUploadOutputDirectoryFileList for file listing in output directory - Create Get-NovaPackageUploadRequestedTypeList to filter requested package types - Update ResolveNovaPackageUploadExplicitFile and ResolveNovaPackageUploadOutputFileList to utilize new functions
1 parent f3595c6 commit 0890639

8 files changed

Lines changed: 187 additions & 26 deletions
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
function Get-NovaPackageUploadFileInfo {
2+
[CmdletBinding()]
3+
param(
4+
[Parameter(Mandatory)][string]$PackageType,
5+
[Parameter(Mandatory)][string]$PackagePath,
6+
[string]$PackageFileName
7+
)
8+
9+
$resolvedPackageFileName = $PackageFileName
10+
if ( [string]::IsNullOrWhiteSpace($resolvedPackageFileName)) {
11+
$resolvedPackageFileName = [System.IO.Path]::GetFileName($PackagePath)
12+
}
13+
14+
return [pscustomobject]@{
15+
Type = $PackageType
16+
PackagePath = $PackagePath
17+
PackageFileName = $resolvedPackageFileName
18+
}
19+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
function Get-NovaPackageUploadOutputDirectoryFileList {
2+
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '', Justification = 'Package upload output directory file list is the domain term represented by this helper.')]
3+
[CmdletBinding()]
4+
param(
5+
[Parameter(Mandatory)][string]$OutputDirectory,
6+
[Parameter(Mandatory)][string]$SearchPattern,
7+
[Parameter(Mandatory)][string]$PackageType
8+
)
9+
10+
$matchingFileList = @(
11+
Get-ChildItem -LiteralPath $OutputDirectory -File -ErrorAction Stop |
12+
Where-Object {$_.Name -like $SearchPattern} |
13+
Sort-Object Name
14+
)
15+
16+
if ($matchingFileList.Count -eq 0) {
17+
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
18+
}
19+
20+
return $matchingFileList
21+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
function Get-NovaPackageUploadRequestedTypeList {
2+
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '', Justification = 'Package upload requested type list is the domain term represented by this helper.')]
3+
[CmdletBinding()]
4+
param(
5+
[Parameter(Mandatory)][pscustomobject]$ProjectInfo,
6+
[string[]]$PackageType
7+
)
8+
9+
$requestedTypeList = @($PackageType | Where-Object {-not [string]::IsNullOrWhiteSpace("$_")})
10+
if ($requestedTypeList.Count -eq 0) {
11+
return @()
12+
}
13+
14+
return @(Resolve-NovaPackageUploadTypeList -ProjectInfo $ProjectInfo -PackageType $requestedTypeList)
15+
}

src/private/package/ResolveNovaPackageUploadExplicitFile.ps1

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,5 @@ function Resolve-NovaPackageUploadExplicitFile {
1515
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
1616
}
1717

18-
return [pscustomobject]@{
19-
Type = $resolvedPackageType
20-
PackagePath = $resolvedPackagePath
21-
PackageFileName = [System.IO.Path]::GetFileName($resolvedPackagePath)
22-
}
18+
return Get-NovaPackageUploadFileInfo -PackageType $resolvedPackageType -PackagePath $resolvedPackagePath
2319
}
24-

src/private/package/ResolveNovaPackageUploadExplicitFileList.ps1

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,7 @@ function Resolve-NovaPackageUploadExplicitFileList {
77
[string[]]$PackageType
88
)
99

10-
$requestedTypeList = @()
11-
if (@($PackageType).Count -gt 0) {
12-
$requestedTypeList = @(Resolve-NovaPackageUploadTypeList -ProjectInfo $ProjectInfo -PackageType $PackageType)
13-
}
10+
$requestedTypeList = @(Get-NovaPackageUploadRequestedTypeList -ProjectInfo $ProjectInfo -PackageType $PackageType)
1411

1512
$resolvedFileList = @(
1613
$PackagePath |
@@ -20,4 +17,3 @@ function Resolve-NovaPackageUploadExplicitFileList {
2017

2118
return $resolvedFileList
2219
}
23-

src/private/package/ResolveNovaPackageUploadOutputFileList.ps1

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@ function Resolve-NovaPackageUploadOutputFileList {
66
[string[]]$PackageType
77
)
88

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

1415
return @(
15-
@(Resolve-NovaPackageUploadTypeList -ProjectInfo $ProjectInfo -PackageType $PackageType) |
16+
$resolvedTypeList |
1617
ForEach-Object {
1718
Resolve-NovaPackageUploadOutputFileSet -OutputDirectory $outputDirectory -ProjectInfo $ProjectInfo -PackageType $_
1819
}

src/private/package/ResolveNovaPackageUploadOutputFileSet.ps1

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,11 @@ function Resolve-NovaPackageUploadOutputFileSet {
88
)
99

1010
$searchPattern = Get-NovaPackageArtifactSearchPattern -ProjectInfo $ProjectInfo -PackageType $PackageType
11-
$matchingFileList = @(
12-
Get-ChildItem -LiteralPath $OutputDirectory -File -ErrorAction Stop |
13-
Where-Object {$_.Name -like $searchPattern} |
14-
Sort-Object Name
15-
)
16-
17-
if ($matchingFileList.Count -eq 0) {
18-
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
19-
}
11+
$matchingFileList = @(Get-NovaPackageUploadOutputDirectoryFileList -OutputDirectory $OutputDirectory -SearchPattern $searchPattern -PackageType $PackageType)
2012

2113
return @(
2214
$matchingFileList | ForEach-Object {
23-
[pscustomobject]@{
24-
Type = $PackageType
25-
PackagePath = $_.FullName
26-
PackageFileName = $_.Name
27-
}
15+
Get-NovaPackageUploadFileInfo -PackageType $PackageType -PackagePath $_.FullName -PackageFileName $_.Name
2816
}
2917
)
3018
}

tests/NovaCommandModel.PackageUpload.Tests.ps1

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ foreach ($functionName in $global:novaCommandModelTestSupportFunctionNameList) {
2222
$scriptBlock = (Get-Command -Name $functionName -CommandType Function -ErrorAction Stop).ScriptBlock
2323
Set-Item -Path "function:global:$functionName" -Value $scriptBlock
2424
}
25+
2526
foreach ($functionName in $global:novaCommandModelPackageUploadTestSupportFunctionNameList) {
2627
$scriptBlock = (Get-Command -Name $functionName -CommandType Function -ErrorAction Stop).ScriptBlock
2728
Set-Item -Path "function:global:$functionName" -Value $scriptBlock
@@ -240,6 +241,131 @@ Describe 'Nova command model - package upload behavior' {
240241
}
241242
}
242243

244+
It 'Get-NovaPackageUploadFileList prefers explicit package paths over output discovery' {
245+
InModuleScope $script:moduleName {
246+
$projectInfo = [pscustomobject]@{ProjectName = 'PackageProject'}
247+
$explicitFileList = @(
248+
[pscustomobject]@{Type = 'Zip'; PackagePath = '/tmp/project/artifacts/packages/PackageProject.2.3.4.zip'; PackageFileName = 'PackageProject.2.3.4.zip'}
249+
)
250+
251+
Mock Resolve-NovaPackageUploadExplicitFileList {$explicitFileList}
252+
Mock Resolve-NovaPackageUploadOutputFileList {throw 'explicit package selection should not fall back to output discovery'}
253+
254+
$result = @(Get-NovaPackageUploadFileList -ProjectInfo $projectInfo -PackagePath @(' ', '/tmp/project/artifacts/packages/PackageProject.2.3.4.zip', '') -PackageType @('Zip'))
255+
256+
$result.PackagePath | Should -Be @('/tmp/project/artifacts/packages/PackageProject.2.3.4.zip')
257+
Assert-MockCalled Resolve-NovaPackageUploadExplicitFileList -Times 1 -ParameterFilter {
258+
$ProjectInfo.ProjectName -eq 'PackageProject' -and
259+
$PackagePath.Count -eq 1 -and
260+
$PackagePath[0] -eq '/tmp/project/artifacts/packages/PackageProject.2.3.4.zip' -and
261+
$PackageType.Count -eq 1 -and
262+
$PackageType[0] -eq 'Zip'
263+
}
264+
Assert-MockCalled Resolve-NovaPackageUploadOutputFileList -Times 0
265+
}
266+
}
267+
268+
It 'Get-NovaPackageUploadFileList falls back to output discovery when explicit package paths are not provided' {
269+
InModuleScope $script:moduleName {
270+
$projectInfo = [pscustomobject]@{ProjectName = 'PackageProject'}
271+
$outputFileList = @(
272+
[pscustomobject]@{Type = 'Zip'; PackagePath = '/tmp/project/artifacts/packages/PackageProject.2.3.4.zip'; PackageFileName = 'PackageProject.2.3.4.zip'}
273+
)
274+
275+
Mock Resolve-NovaPackageUploadExplicitFileList {throw 'output discovery should be used when PackagePath is empty'}
276+
Mock Resolve-NovaPackageUploadOutputFileList {$outputFileList}
277+
278+
$result = @(Get-NovaPackageUploadFileList -ProjectInfo $projectInfo -PackagePath @('', ' ') -PackageType @('Zip'))
279+
280+
$result.PackagePath | Should -Be @('/tmp/project/artifacts/packages/PackageProject.2.3.4.zip')
281+
Assert-MockCalled Resolve-NovaPackageUploadExplicitFileList -Times 0
282+
Assert-MockCalled Resolve-NovaPackageUploadOutputFileList -Times 1 -ParameterFilter {
283+
$ProjectInfo.ProjectName -eq 'PackageProject' -and
284+
$PackageType.Count -eq 1 -and
285+
$PackageType[0] -eq 'Zip'
286+
}
287+
}
288+
}
289+
290+
It 'Get-NovaPackageUploadRequestedTypeList returns an empty list when PackageType is omitted or whitespace' {
291+
InModuleScope $script:moduleName {
292+
$projectInfo = [pscustomobject]@{ProjectName = 'PackageProject'}
293+
294+
Mock Resolve-NovaPackageUploadTypeList {throw 'type resolution should be skipped when no package types were requested'}
295+
296+
$result = @(Get-NovaPackageUploadRequestedTypeList -ProjectInfo $projectInfo -PackageType @('', ' '))
297+
298+
$result.Count | Should -Be 0
299+
Assert-MockCalled Resolve-NovaPackageUploadTypeList -Times 0
300+
}
301+
}
302+
303+
It 'Resolve-NovaPackageUploadExplicitFileList resolves requested types once and deduplicates by package path' {
304+
InModuleScope $script:moduleName {
305+
$projectInfo = [pscustomobject]@{ProjectName = 'PackageProject'}
306+
307+
Mock Get-NovaPackageUploadRequestedTypeList {@('Zip')}
308+
Mock Resolve-NovaPackageUploadExplicitFile {
309+
[pscustomobject]@{
310+
Type = 'Zip'
311+
PackagePath = '/tmp/project/artifacts/packages/PackageProject.2.3.4.zip'
312+
PackageFileName = 'PackageProject.2.3.4.zip'
313+
}
314+
}
315+
316+
$result = @(Resolve-NovaPackageUploadExplicitFileList -ProjectInfo $projectInfo -PackagePath @('/tmp/project/artifacts/packages/PackageProject.2.3.4.zip', './artifacts/packages/PackageProject.2.3.4.zip') -PackageType @('Zip'))
317+
318+
$result.Count | Should -Be 1
319+
$result[0].PackageFileName | Should -Be 'PackageProject.2.3.4.zip'
320+
Assert-MockCalled Get-NovaPackageUploadRequestedTypeList -Times 1 -ParameterFilter {
321+
$ProjectInfo.ProjectName -eq 'PackageProject' -and
322+
$PackageType.Count -eq 1 -and
323+
$PackageType[0] -eq 'Zip'
324+
}
325+
Assert-MockCalled Resolve-NovaPackageUploadExplicitFile -Times 2 -ParameterFilter {
326+
$RequestedPackageTypeList.Count -eq 1 -and
327+
$RequestedPackageTypeList[0] -eq 'Zip'
328+
}
329+
}
330+
}
331+
332+
It 'Resolve-NovaPackageUploadOutputFileList resolves types before discovering artifacts in the output directory' {
333+
InModuleScope $script:moduleName {
334+
$projectInfo = [pscustomobject]@{ProjectName = 'PackageProject'}
335+
336+
Mock Resolve-NovaPackageUploadTypeList {@('NuGet', 'Zip')}
337+
Mock Get-NovaPackageOutputDirectory {'/tmp/project/artifacts/packages'}
338+
Mock Test-Path {$true} -ParameterFilter {$LiteralPath -eq '/tmp/project/artifacts/packages' -and $PathType -eq 'Container'}
339+
Mock Resolve-NovaPackageUploadOutputFileSet {
340+
[pscustomobject]@{
341+
Type = $PackageType
342+
PackagePath = "/tmp/project/artifacts/packages/PackageProject.2.3.4.$($PackageType.ToLower() )"
343+
PackageFileName = "PackageProject.2.3.4.$($PackageType.ToLower() )"
344+
}
345+
}
346+
347+
$result = @(Resolve-NovaPackageUploadOutputFileList -ProjectInfo $projectInfo -PackageType @('NuGet', 'Zip'))
348+
349+
$result.Type | Should -Be @('NuGet', 'Zip')
350+
Assert-MockCalled Resolve-NovaPackageUploadTypeList -Times 1 -ParameterFilter {
351+
$ProjectInfo.ProjectName -eq 'PackageProject' -and
352+
$PackageType.Count -eq 2
353+
}
354+
Assert-MockCalled Resolve-NovaPackageUploadOutputFileSet -Times 1 -ParameterFilter {$PackageType -eq 'NuGet' -and $OutputDirectory -eq '/tmp/project/artifacts/packages'}
355+
Assert-MockCalled Resolve-NovaPackageUploadOutputFileSet -Times 1 -ParameterFilter {$PackageType -eq 'Zip' -and $OutputDirectory -eq '/tmp/project/artifacts/packages'}
356+
}
357+
}
358+
359+
It 'Get-NovaPackageUploadFileInfo falls back to the package path file name when none is provided' {
360+
InModuleScope $script:moduleName {
361+
$result = Get-NovaPackageUploadFileInfo -PackageType 'Zip' -PackagePath '/tmp/project/artifacts/packages/PackageProject.2.3.4.zip'
362+
363+
$result.Type | Should -Be 'Zip'
364+
$result.PackagePath | Should -Be '/tmp/project/artifacts/packages/PackageProject.2.3.4.zip'
365+
$result.PackageFileName | Should -Be 'PackageProject.2.3.4.zip'
366+
}
367+
}
368+
243369
It 'Resolve-NovaPackageUploadTarget resolves target precedence correctly when <Name>' -ForEach (Get-TestNovaPackageUploadTargetResolutionCases) {
244370
$testCase = $_
245371
$layout = Initialize-TestNovaPackageUploadLayout -ProjectRoot (Join-Path $TestDrive $testCase.ProjectRootName)

0 commit comments

Comments
 (0)