Tasks/New-WhiskeyProGetUniversalPackage.ps1
function New-WhiskeyProGetUniversalPackage { [CmdletBinding()] [Whiskey.Task("ProGetUniversalPackage")] [Whiskey.RequiresTool('PowerShellModule::ProGetAutomation','ProGetAutomationPath',Version='0.9.*',VersionParameterName='ProGetAutomationVersion')] param( [Parameter(Mandatory=$true)] [Whiskey.Context] $TaskContext, [Parameter(Mandatory=$true)] [hashtable] $TaskParameter ) Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState Import-WhiskeyPowerShellModule -Name 'ProGetAutomation' $manifestProperties = @{} if( $TaskParameter.ContainsKey('ManifestProperties') ) { $manifestProperties = $TaskParameter['ManifestProperties'] foreach( $taskProperty in @( 'Name', 'Description', 'Version' )) { if( $manifestProperties.Keys -contains $taskProperty ) { Stop-WhiskeyTask -TaskContext $TaskContext -Message ('"ManifestProperties" contains key "{0}". This property cannot be manually defined in "ManifestProperties" as it is set automatically from the corresponding task property "{0}".' -f $taskProperty) return } } } foreach( $mandatoryProperty in @( 'Name', 'Description' ) ) { if( -not $TaskParameter.ContainsKey($mandatoryProperty) ) { Stop-WhiskeyTask -TaskContext $TaskContext -Message ('Property "{0}" is mandatory.' -f $mandatoryProperty) return } } $name = $TaskParameter['Name'] $validNameRegex = '^[0-9A-z\-\._]{1,50}$' if ($name -notmatch $validNameRegex) { Stop-WhiskeyTask -TaskContext $TaskContext -Message '"Name" property is invalid. It should be a string of one to fifty characters: numbers (0-9), upper and lower-case letters (A-z), dashes (-), periods (.), and underscores (_).' return } $version = $TaskParameter['Version'] # ProGet uses build metadata to distinguish different versions, so we can't use a full semantic version. if( $version ) { if( ($version -notmatch '^\d+\.\d+\.\d+$') ) { Stop-WhiskeyTask -TaskContext $TaskContext -Message ('Property "Version" is invalid. It must be a three part version number, i.e. MAJOR.MINOR.PATCH.') return } [SemVersion.SemanticVersion]$semVer = $null if( -not ([SemVersion.SemanticVersion]::TryParse($version, [ref]$semVer)) ) { Stop-WhiskeyTask -TaskContext $TaskContext -Message ('Property "Version" is not a valid semantic version.') return } $semVer = New-Object 'SemVersion.SemanticVersion' $semVer.Major,$semVer.Minor,$semVer.Patch,$TaskContext.Version.SemVer2.Prerelease,$TaskContext.Version.SemVer2.Build $version = New-WhiskeyVersionObject -SemVer $semVer } else { $version = $TaskContext.Version } $compressionLevel = [IO.Compression.CompressionLevel]::Optimal if( $TaskParameter['CompressionLevel'] ) { $expectedValues = [enum]::GetValues([IO.Compression.CompressionLevel]) $compressionLevel = $TaskParameter['CompressionLevel'] if( $compressionLevel -notin $expectedValues ) { [int]$intCompressionLevel = 0 if( -not [int]::TryParse($TaskParameter['CompressionLevel'],[ref]$intCompressionLevel) ) { Stop-WhiskeyTask -TaskContext $TaskContext -Message ('Property "CompressionLevel": "{0}" is not a valid compression level. It must be one of: {1}' -f $TaskParameter['CompressionLevel'],($expectedValues -join ', ')); return } $compressionLevel = $intCompressionLevel if( $compressionLevel -ge 5 ) { $compressionLevel = [IO.Compression.CompressionLevel]::Optimal } else { $compressionLevel = [IO.Compression.CompressionLevel]::Fastest } Write-Warning -Message ('The ProGetUniversalPackage task no longer supports integer-style compression levels. Please update your task in your whiskey.yml file to use one of the new values: {0}. We''re converting the number you provided, "{1}", to "{2}".' -f ($expectedValues -join ', '),$TaskParameter['CompressionLevel'],$compressionLevel) } } $parentPathParam = @{ } $sourceRoot = $TaskContext.BuildRoot if( $TaskParameter.ContainsKey('SourceRoot') ) { $sourceRoot = $TaskParameter['SourceRoot'] | Resolve-WhiskeyTaskPath -TaskContext $TaskContext -PropertyName 'SourceRoot' $parentPathParam['ParentPath'] = $sourceRoot } $tempRoot = Join-Path -Path $TaskContext.Temp -ChildPath 'upack' New-Item -Path $tempRoot -ItemType 'Directory' | Out-Null $tempPackageRoot = Join-Path -Path $tempRoot -ChildPath 'package' New-Item -Path $tempPackageRoot -ItemType 'Directory' | Out-Null $upackJsonPath = Join-Path -Path $tempRoot -ChildPath 'upack.json' $manifestProperties | ConvertTo-Json | Set-Content -Path $upackJsonPath # Add the version.json file $versionJsonPath = Join-Path -Path $tempPackageRoot -ChildPath 'version.json' @{ Version = $version.Version.ToString(); SemVer2 = $version.SemVer2.ToString(); SemVer2NoBuildMetadata = $version.SemVer2NoBuildMetadata.ToString(); PrereleaseMetadata = $version.SemVer2.Prerelease; BuildMetadata = $version.SemVer2.Build; SemVer1 = $version.SemVer1.ToString(); } | ConvertTo-Json -Depth 1 | Set-Content -Path $versionJsonPath function Copy-ToPackage { param( [Parameter(Mandatory=$true)] [object[]] $Path, [Switch] $AsThirdPartyItem ) foreach( $item in $Path ) { $override = $False if( (Get-Member -InputObject $item -Name 'Keys') ) { $sourcePath = $null $override = $True foreach( $key in $item.Keys ) { $destinationItemName = $item[$key] $sourcePath = $key } } else { $sourcePath = $item } $pathparam = 'path' if( $AsThirdPartyItem ) { $pathparam = 'ThirdPartyPath' } $sourcePaths = $sourcePath | Resolve-WhiskeyTaskPath -TaskContext $TaskContext -PropertyName $pathparam @parentPathParam if( -not $sourcePaths ) { return } foreach( $sourcePath in $sourcePaths ) { $relativePath = $sourcePath -replace ('^{0}' -f ([regex]::Escape($sourceRoot))),'' $relativePath = $relativePath.Trim([IO.Path]::DirectorySeparatorChar) $addParams = @{ BasePath = $sourceRoot } $overrideInfo = '' if( $override ) { $addParams = @{ PackageItemName = $destinationItemName } $overrideInfo = ' -> {0}' -f $destinationItemName } $addParams['CompressionLevel'] = $compressionLevel if( $AsThirdPartyItem ) { Write-WhiskeyInfo -Context $TaskContext -Message (' packaging unfiltered item {0}{1}' -f $relativePath,$overrideInfo) Get-Item -Path $sourcePath | Add-ProGetUniversalPackageFile -PackagePath $outFile @addParams -ErrorAction Stop continue } if( (Test-Path -Path $sourcePath -PathType Leaf) ) { Write-WhiskeyInfo -Context $TaskContext -Message (' packaging file {0}{1}' -f $relativePath,$overrideInfo) Add-ProGetUniversalPackageFile -PackagePath $outFile -InputObject $sourcePath @addParams -ErrorAction Stop continue } if( -not $TaskParameter['Include'] ) { Stop-WhiskeyTask -TaskContext $TaskContext -Message ('Property "Include" is mandatory because "{0}" is in your "Path" property and it is a directory. The "Include" property is a whitelist of files (wildcards supported) to include in your package. Only files in directories that match an item in the "Include" list will be added to your package.' -f $sourcePath) return } function Find-Item { param( [Parameter(Mandatory)] $Path ) if( (Test-Path -Path $Path -PathType Leaf) ) { return Get-Item -Path $Path } $Path = Join-Path -Path $Path -ChildPath '*' & { Get-ChildItem -Path $Path -Include $TaskParameter['Include'] -Exclude $TaskParameter['Exclude'] -File Get-Item -Path $Path -Exclude $TaskParameter['Exclude'] | Where-Object { $_.PSIsContainer } } | ForEach-Object { if( $_.PSIsContainer ) { Find-Item -Path $_.FullName } else { $_ } } } if( $override ) { $addParams['BasePath'] = $sourcePath $addParams.Remove('PackageItemName') $overrideInfo = ' -> {0}' -f $destinationItemName if ($destinationItemName -ne '.') { $addParams['PackageParentPath'] = $destinationItemName } } Write-WhiskeyInfo -Context $TaskContext -Message (' packaging filtered directory {0}{1}' -f $relativePath,$overrideInfo) Find-Item -Path $sourcePath | Add-ProGetUniversalPackageFile -PackagePath $outFile @addParams -ErrorAction Stop } } } $badChars = [IO.Path]::GetInvalidFileNameChars() | ForEach-Object { [regex]::Escape($_) } $fixRegex = '[{0}]' -f ($badChars -join '') $fileName = '{0}.{1}.upack' -f $name,($version.SemVer2NoBuildMetadata -replace $fixRegex,'-') $outFile = Join-Path -Path $TaskContext.OutputDirectory -ChildPath $fileName if( (Test-Path -Path $outFile -PathType Leaf) ) { Remove-Item -Path $outFile -Force } if( -not $manifestProperties.ContainsKey('title') ) { $manifestProperties['title'] = $TaskParameter['Name'] } $outFileDisplay = $outFile -replace ('^{0}' -f [regex]::Escape($TaskContext.BuildRoot)),'' $outFileDisplay = $outFileDisplay.Trim([IO.Path]::DirectorySeparatorChar) Write-WhiskeyInfo -Context $TaskContext -Message ('Creating universal package "{0}".' -f $outFileDisplay) New-ProGetUniversalPackage -OutFile $outFile ` -Version $version.SemVer2NoBuildMetadata.ToString() ` -Name $TaskParameter['Name'] ` -Description $TaskParameter['Description'] ` -AdditionalMetadata $manifestProperties Add-ProGetUniversalPackageFile -PackagePath $outFile -InputObject $versionJsonPath -ErrorAction Stop if( $TaskParameter['Path'] ) { Copy-ToPackage -Path $TaskParameter['Path'] } if( $TaskParameter.ContainsKey('ThirdPartyPath') -and $TaskParameter['ThirdPartyPath'] ) { Copy-ToPackage -Path $TaskParameter['ThirdPartyPath'] -AsThirdPartyItem } } |