PSPublishHelper.psm1
$Script:Nuspec = @"
<?xml version="1.0"?> <package > <metadata> <id>{0}</id> <version>{1}</version> <authors>{2}</authors> <owners>{3}</owners> <description>{4}</description> <releaseNotes>{5}</releaseNotes> <requireLicenseAcceptance>{6}</requireLicenseAcceptance> <copyright>{7}</copyright> <tags>{8}</tags> {9} {10} {11} <dependencies> {12} </dependencies> </metadata> </package> "@#Region '.\src\PSPublishHelper\private\Copy-PSModule.ps1' 0 function Copy-PSModule { [CmdletBinding()] param ( [Parameter(Mandatory)] [ValidateNotNull()] [PSModuleInfo] $Module, [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string] $Path ) end { $Params = @{ Path = $Path Recurse = $true Force = $true ErrorAction = 'SilentlyContinue' } Microsoft.PowerShell.Management\Remove-Item @Params $Params = @{ Path = $Path ItemType = 'Directory' Force = $true } $null = Microsoft.PowerShell.Management\New-Item @Params Microsoft.PowerShell.Management\Get-ChildItem $Module.ModuleBase -recurse | ForEach-Object { if ($_.PSIsContainer) { $Params = @{ Force = $true Confirm = $false WhatIf = $false Recurse = $true Container = $true Destination = $Path } $_ | Microsoft.PowerShell.Management\Copy-Item @Params } else { $Params = @{ Force = $true Confirm = $false WhatIf = $false Destination = $Path } $_ | Microsoft.PowerShell.Management\Copy-Item @Params } } } } #EndRegion '.\src\PSPublishHelper\private\Copy-PSModule.ps1' 51 #Region '.\src\PSPublishHelper\private\Format-PSModuleDependency.ps1' 0 function Format-PSModuleDependency { [OutputType([string])] [CmdletBinding()] param ( [Parameter(ValueFromPipeline)] [Microsoft.PowerShell.Commands.ModuleSpecification] $Dependency ) process { if (-not $Dependency) { return } $Version = [string]::Empty # Version format in NuSpec: # "[2.0]" --> (== 2.0) Required Version # "2.0" --> (>= 2.0) Minimum Version # # When only MaximumVersion is specified in the ModuleSpecification # (,1.0] = x <= 1.0 # # When both Minimum and Maximum versions are specified in the ModuleSpecification # [1.0,2.0] = 1.0 <= x <= 2.0 if($Dependency.RequiredVersion) { $Version = "[{0}]" -f $Dependency.RequiredVersion } elseif($Dependency.Version -and $Dependency.MaximumVersion) { $Version = "[{0},{1}]" -f $Dependency.Version, $Dependency.MaximumVersion } elseif($Dependency.MaximumVersion) { $Version = "(,{0}]" -f $Dependency.MaximumVersion } elseif($Dependency.Version) { $Version = "{0}" -f $Dependency.Version } if ([System.string]::IsNullOrWhiteSpace($Version)) { "<dependency id='{0}'/>" -f $Dependency.Name } else { "<dependency id='{0}' version='{1}' />" -f $Dependency.Name, $Version } } } #EndRegion '.\src\PSPublishHelper\private\Format-PSModuleDependency.ps1' 39 #Region '.\src\PSPublishHelper\private\Get-AvailableRoleCapabilityName.ps1' 0 function Get-AvailableRoleCapabilityName { [CmdletBinding()] Param ( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [PSModuleInfo] $Module ) $RoleCapabilitiesDir = Join-Path $Module.ModuleBase 'RoleCapabilities' if(Microsoft.PowerShell.Management\Test-Path -Path $RoleCapabilitiesDir -PathType Container) { $Params = @{ Path = $RoleCapabilitiesDir Filter = '*.psrc' } Microsoft.PowerShell.Management\Get-ChildItem @Params | ForEach-Object -MemberName BaseName } } #EndRegion '.\src\PSPublishHelper\private\Get-AvailableRoleCapabilityName.ps1' 20 #Region '.\src\PSPublishHelper\private\Get-EscapedString.ps1' 0 function Get-EscapedString { [CmdletBinding()] [OutputType([String])] Param ( [Parameter(ValueFromPipeline)] [string] $Value ) process { [System.Security.SecurityElement]::Escape($Value) } } #EndRegion '.\src\PSPublishHelper\private\Get-EscapedString.ps1' 14 #Region '.\src\PSPublishHelper\private\Get-ExportedDscResources.ps1' 0 function Get-ExportedDscResources { [CmdletBinding()] Param( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [PSModuleInfo] $Module ) $Params = @{ Name = 'Get-DscResource' Module = 'PSDesiredStateConfiguration' ErrorAction = 'Ignore' } if(-not $script:IsCoreCLR -and (Get-Command @Params)) { $OldPSModulePath = $env:PSModulePath try { $env:PSModulePath = Join-Path -Path $PSHOME -ChildPath "Modules" $ModuleBaseParent = Split-Path -Path $Module.ModuleBase -Parent $env:PSModulePath = "{0}{1}{2}" -f @( $env:PSModulePath, [System.IO.Path]::PathSeparator, $ModuleBaseParent ) $Params = @{ ErrorAction = 'SilentlyContinue' WarningAction = 'SilentlyContinue' } PSDesiredStateConfiguration\Get-DscResource @Params | Microsoft.PowerShell.Core\ForEach-Object { if( $_.Module -and $_.Module.Name -eq $Module.Name ){ $_.Name } } } finally { $env:PSModulePath = $OldPSModulePath } } else { $dscResourcesDir = Join-Path $Module.ModuleBase "DscResources" if(Microsoft.PowerShell.Management\Test-Path $dscResourcesDir) { Microsoft.PowerShell.Management\Get-ChildItem -Path $dscResourcesDir -Directory -Name } } } #EndRegion '.\src\PSPublishHelper\private\Get-ExportedDscResources.ps1' 49 #Region '.\src\PSPublishHelper\private\Get-NupkgFilePath.ps1' 0 function Get-NupkgFilePath { [CmdletBinding()] param ( [Parameter(Mandatory)] [ValidateNotNull()] [PSModuleInfo] $Module, [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string] $Path ) end { $PSData = Resolve-PSData -Module $Module $Version = Resolve-PSModuleVersion -Module $Module -PSData $PSData $FileName = '{0}.{1}.nupkg' -f $Module.Name, $Version Join-Path $Path $FileName } } #EndRegion '.\src\PSPublishHelper\private\Get-NupkgFilePath.ps1' 20 #Region '.\src\PSPublishHelper\private\Get-NuspecContents.ps1' 0 function Get-NuspecContents { [OutputType([String])] [CmdletBinding()] param ( [PSModuleInfo] $Module, [Hashtable] $PSData ) end { $VersionText = Resolve-PSModuleVersion -Module $Module -PSData $PSData $TagsText = Resolve-PSModuleTags -Module $Module -Tags $PSData.Tags $RequireLicenseAcceptanceText = ([bool]$PSData.RequireLicenseAcceptance).ToString().ToLower() $Description = $Module.Description if ([string]::IsNullOrWhiteSpace($Description)) { $Description = $Module.Name } $ArgumentList = [System.Collections.Generic.List[string]]::new() @( $Module.Name, $VersionText, $Module.Author, $Module.CompanyName, $Description, $Module.ReleaseNotes, $RequireLicenseAcceptanceText, $Module.Copyright, $TagsText ) | Get-EscapedString | ForEach-Object { $ArgumentList.Add($_) } $LicenseUriText = if ($PSData.LicenseUri) { '<licenseUrl>{0}</licenseUrl>' -f ($PSData.LicenseUri | Get-EscapedString) } $ArgumentList.Add($LicenseUriText) $ProjectUriText = if ($PSData.ProjectUri) { '<projectUrl>{0}</projectUrl>' -f ($PSData.ProjectUri | Get-EscapedString) } $ArgumentList.Add($ProjectUriText) $IconUriText = if ($PSData.IconUri) { '<iconUrl>{0}</iconUrl>' -f ($PSData.IconUri | Get-EscapedString) } $ArgumentList.Add($IconUriText) $DependencyText = @( $Module | Resolve-PSModuleDependency -ExternalModuleDependencies $PSData.ExternalModuleDependencies | Format-PSModuleDependency ) -Join ([Environment]::NewLine) $ArgumentList.Add($DependencyText) $Script:Nuspec -f $ArgumentList.ToArray() } } #EndRegion '.\src\PSPublishHelper\private\Get-NuspecContents.ps1' 61 #Region '.\src\PSPublishHelper\private\Get-NuspecFilePath.ps1' 0 function Get-NuspecFilePath { [CmdletBinding()] param ( [Parameter(Mandatory)] [ValidateNotNull()] [PSModuleInfo] $Module, [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string] $Path ) end { $FileName = '{0}.nuspec' -f $Module.Name Join-Path $Path $FileName } } #EndRegion '.\src\PSPublishHelper\private\Get-NuspecFilePath.ps1' 18 #Region '.\src\PSPublishHelper\private\Get-PSModuleManifestData.ps1' 0 function Get-PSModuleManifestData { [CmdletBinding()] param ( [Parameter(Mandatory,ValueFromPipeline)] [ValidateNotNull()] [PSModuleInfo] $Module ) process { if ($Module.Path -match '\.psd1$') { $Manifest = $Module.Path } else { $ManifestName = '{0}.psd1' -f $Module.Name $Manifest = Join-Path $Module.ModuleBase $ManifestName } Import-PowerShellDataFile -Path $Manifest } } #EndRegion '.\src\PSPublishHelper\private\Get-PSModuleManifestData.ps1' 18 #Region '.\src\PSPublishHelper\private\Get-TemporaryPath.ps1' 0 function Get-TemporaryPath { [OutputType([string])] [CmdletBinding()] param ( [Parameter(Mandatory,ValueFromPipeline)] [ValidateNotNull()] [PSModuleInfo] $Module ) process { $Base = Join-Path ([System.IO.Path]::GetTempPath()) (Get-Random) Join-Path $Base $Module.Name } } #EndRegion '.\src\PSPublishHelper\private\Get-TemporaryPath.ps1' 14 #Region '.\src\PSPublishHelper\private\Resolve-NugetCommand.ps1' 0 function Resolve-NugetCommand { [CmdletBinding()] param ( [Parameter()] [System.Management.Automation.PSCmdlet] $Cmdlet ) end { $ErrorCmdlet = $Cmdlet if (-not $Cmdlet) { $ErrorCmdlet = $PSCmdlet } $Params = @{ Name = 'nuget' CommandType = 'Application' ErrorAction = 'SilentlyContinue' } $Nuget = Get-Command @Params | Select-Object -First 1 if(-not $Nuget) { $ErrorRecord = [System.Management.Automation.ErrorRecord]::new( [System.Management.Automation.ItemNotFoundException]::new( "Unable to find nuget binary. Nuget is required" ), "NugetNotFound", [System.Management.Automation.ErrorCategory]::NotInstalled, $null ) $ErrorCmdlet.ThrowTerminatingError($ErrorRecord) } $Nuget } } #EndRegion '.\src\PSPublishHelper\private\Resolve-NugetCommand.ps1' 32 #Region '.\src\PSPublishHelper\private\Resolve-PSData.ps1' 0 function Resolve-PSData { [OutputType([Hashtable])] [CmdletBinding()] param ( [PSModuleInfo] $Module, [string] $ReleaseNotes, [string[]] $Tags, [Uri] $LicenseUri, [Uri] $IconUri, [Uri] $ProjectUri ) end { $Result = @{} $PSData = @{ ReleaseNotes = $ReleaseNotes Tags = $Tags LicenseUri = $LicenseUri IconUri = $IconUri ProjectUri = $ProjectUri Prerelease = $null RequireLicenseAcceptance = $null ExternalModuleDependencies = @() } foreach ($item in $PSData.GetEnumerator()) { $key = $item.key $Result[$key] = $item.value if (-not $item.value -and $key -ne 'Prerelease') { $Result[$key] = $Module.PrivateData.PSdata.$key } elseif (-not $item.value -and $key -eq 'Prerelease') { $Result[$key] = $Module.PrivateData.PSData.$key } Write-Verbose "$($key): $($Result[$key])" } $Result } } #EndRegion '.\src\PSPublishHelper\private\Resolve-PSData.ps1' 47 #Region '.\src\PSPublishHelper\private\Resolve-PSModule.ps1' 0 function Resolve-PSModule { [OutputType([System.Management.Automation.PSModuleInfo])] [CmdletBinding()] param ( [Parameter()] [System.Management.Automation.PSCmdlet] $Cmdlet, [Parameter()] [string] $Name, [Parameter()] [string] $RequiredVersion ) end { if($Cmdlet) { $ErrorCmdlet = $Cmdlet } else { $ErrorCmdlet = $PSCmdlet } $Version, $Prerelease = $RequiredVersion -split '-', 2 $Filter = { $_.Version.ToString() -eq $Version -and ( $_.PrivateData.PSData.Prerelease -eq $Prerelease -or $_.PrivateData.PSData.Prerelease -eq "-$Prerelease" ) } $Result = Get-Module -ListAvailable -Name $Name | Where-Object -FilterScript $Filter | Select-Object -First 1 if (-not $Result) { $ErrorRecord = [System.Management.Automation.ErrorRecord]::new( [System.Management.Automation.ItemNotFoundException]::new( "Unable to find Module $Name Version $RequiredVersion" ), "ModuleNotFound", [System.Management.Automation.ErrorCategory]::InvalidArgument, $null ) $ErrorCmdlet.ThrowTerminatingError($ErrorRecord) } $Result } } #EndRegion '.\src\PSPublishHelper\private\Resolve-PSModule.ps1' 51 #Region '.\src\PSPublishHelper\private\Resolve-PSModuleDependency.ps1' 0 function Resolve-PSModuleDependency { [OutputType([Microsoft.PowerShell.Commands.ModuleSpecification])] [CmdletBinding()] param ( [Parameter(Mandatory, ValueFromPipeline)] [PSModuleInfo] $Module, [String[]] $ExternalModuleDependencies ) process { # The manifest contains the actual ModuleSpec used for Version requirements $ModuleData = $Module | Get-PSModuleManifestData # A module in RequiredModules is not a dependency if it's listed in ExternalModuleDependencies $ModuleData.RequiredModules | Resolve-PSModuleInfo | Where-Object { $_.Name -notin $ExternalModuleDependencies } $NestModuleInfo = $ModuleData.NestedModules | Resolve-PSModuleInfo # A module in NestedModules become a dependency # when it is not not packaged with the module $NestedDependencies = $Module.NestedModules | Where-Object { -not $_.ModuleBase.StartsWith($Module.ModuleBase, [System.StringComparison]::OrdinalIgnoreCase) -or -not $_.Path -or -not (Microsoft.PowerShell.Management\Test-Path -LiteralPath $_.Path) } | Foreach-Object -MemberName Name $NestModuleInfo | Where-Object {$_.Name -in $NestedDependencies} } } #EndRegion '.\src\PSPublishHelper\private\Resolve-PSModuleDependency.ps1' 33 #Region '.\src\PSPublishHelper\private\Resolve-PSModuleInfo.ps1' 0 function Resolve-PSModuleInfo { [OutputType([Microsoft.PowerShell.Commands.ModuleSpecification])] [CmdletBinding()] param ( [Parameter(ValueFromPipeline)] [PSObject] $InputObject ) process { # '*' can be specified in the MaximumVersion of a ModuleSpecification to convey # that maximum possible value of that version part. # like 1.0.0.* --> 1.0.0.99999999 if($InputObject.MaximumVersion){ $InputObject.MaximumVersion = $InputObject.MaximumVersion -replace '\*','99999999' } [Microsoft.PowerShell.Commands.ModuleSpecification]$InputObject } } #EndRegion '.\src\PSPublishHelper\private\Resolve-PSModuleInfo.ps1' 20 #Region '.\src\PSPublishHelper\private\Resolve-PSModuleTags.ps1' 0 function Resolve-PSModuleTags { [CmdletBinding()] param ( [PSModuleInfo] $Module, [String[]] $Tags ) end { $TagsList = [System.Collections.Generic.HashSet[String]]::new() foreach($Tag in $Tags) { $null = $TagsList.Add($Tag) } $null = $TagsList.add('PSModule') foreach($Cmdlet in $Module.ExportedCmdlets.Keys) { $null = $TagsList.Add('PSIncludes_Cmdlet') $null = $TagsList.add(('PSCmdlet_{0}' -f $Cmdlet)) } foreach($Func in $Module.ExportedFunctions.Keys) { $null = $TagsList.Add('PSIncludes_Function') $null = $TagsList.add(('PSFunction_{0}' -f $func)) } foreach($Command in $Module.ExportedCommands.Keys) { $null = $TagsList.add(('PSCommand_{0}' -f $Command)) } if(!$IsCoreCLR) { foreach ($DscResource in (Get-ExportedDscResources -Module $Module -ErrorAction SilentlyContinue)) { $null = $TagsList.Add('PSIncludes_DscResource') $null = $TagsList.add(('PSDscResource_{0}' -f $DscResource)) } } else { Write-Verbose 'Skipping DSC resource enumeration as it is not supported on PS Core.' Write-Verbose 'Please use Windows PowerShell to build DSC modules.' } foreach ($Role in (Get-AvailableRoleCapabilityName -Module $Module)) { $null = $TagsList.Add('PSIncludes_RoleCapability') $null = $TagsList.add(('PSRoleCapability_{0}' -f $Role)) } $TagsList -join ' ' } } #EndRegion '.\src\PSPublishHelper\private\Resolve-PSModuleTags.ps1' 50 #Region '.\src\PSPublishHelper\private\Resolve-PSModuleVersion.ps1' 0 function Resolve-PSModuleVersion { [OutputType([string])] [CmdletBinding()] param ( [Parameter()] [PsModuleInfo] $Module, [Parameter()] [Hashtable] $PSData ) end { $Version = [string]$Module.Version if($PSData.Prerelease) { $Prerelease = $PSData.Prerelease if($Prerelease.StartsWith('-')) { $version = '{0}{1}' -f $Version, $Prerelease } else { $version = '{0}-{1}' -f $Version, $Prerelease } } $Version } } #EndRegion '.\src\PSPublishHelper\private\Resolve-PSModuleVersion.ps1' 25 #Region '.\src\PSPublishHelper\public\Publish-PSModuleNuget.ps1' 0 function Publish-PSModuleNuget { [CmdletBinding(DefaultParameterSetName = 'NameAndVersion')] param ( [Parameter( Mandatory, ParameterSetName = 'NameAndVersion' )] [ValidateNotNullOrEmpty()] [string] $Name, [Parameter( Mandatory, ParameterSetName = 'NameAndVersion' )] [ValidateNotNullOrEmpty()] [string] $RequiredVersion, [Parameter( Mandatory, ParameterSetName = 'PSModuleInfo', ValueFromPipeline )] [ValidateNotNull()] [PSModuleInfo] $InputObject, [Parameter( Mandatory, ParameterSetName = 'NameAndVersion' )] [Parameter( Mandatory, ParameterSetName = 'PSModuleInfo' )] [ValidateNotNullOrEmpty()] [ValidateScript({ if(-not (Test-Path -PathType Container -Path $_)){throw} else {$true} })] [string] $OutputPath, [Parameter(Mandatory = $false, ParameterSetName = 'PSModuleInfo')] [Parameter(Mandatory = $false, ParameterSetName = 'NameAndVersion')] [string] $ReleaseNotes, [Parameter(Mandatory = $false, ParameterSetName = 'PSModuleInfo')] [Parameter(Mandatory = $false, ParameterSetName = 'NameAndVersion')] [string[]] $Tags, [Parameter(Mandatory = $false, ParameterSetName = 'PSModuleInfo')] [Parameter(Mandatory = $false, ParameterSetName = 'NameAndVersion')] [Uri] $LicenseUri, [Parameter(Mandatory = $false, ParameterSetName = 'PSModuleInfo')] [Parameter(Mandatory = $false, ParameterSetName = 'NameAndVersion')] [Uri] $IconUri, [Parameter(Mandatory = $false, ParameterSetName = 'PSModuleInfo')] [Parameter(Mandatory = $false, ParameterSetName = 'NameAndVersion')] [Uri] $ProjectUri, [Parameter(Mandatory = $false, ParameterSetName = 'PSModuleInfo')] [Parameter(Mandatory = $false, ParameterSetName = 'NameAndVersion')] [Switch] $PassThru ) begin { $Nuget = Resolve-NugetCommand -Cmdlet $PSCmdlet -ErrorAction Stop Write-Verbose "Nuget found at $($Nuget.Path)" $OutputPath = Convert-Path $OutputPath -ErrorAction Stop Write-Verbose "Output Path: $OutputPath" } process { if($PSCmdlet.ParameterSetName -eq 'NameAndVersion') { $Params = @{ Cmdlet = $PSCmdlet Name = $Name RequiredVersion = $RequiredVersion ErrorAction = 'stop' } $InputObject = Resolve-PSModule @Params } Write-Verbose "Using Module from $($InputObject.ModuleBase)" $Params = @{ IconUri = $IconUri ReleaseNotes = $ReleaseNotes Module = $InputObject Tags = $Tags ProjectUri = $ProjectUri LicenseUri = $LicenseUri } $PSData = Resolve-PSData @Params $Params = @{ Module = $InputObject PSData = $PSData ErrorAction = 'stop' } $NuspecContents = Get-NuspecContents @Params $TempPath = $InputObject | Get-TemporaryPath try { Copy-PSModule -Module $InputObject -Path $TempPath -ErrorAction Stop $NuspecPath = Get-NuspecFilePath -Module $InputObject -Path $TempPath -ErrorAction Stop $NuspecContents | Set-Content -Path $NuspecPath -Force -Confirm:$false -WhatIf:$false -ErrorAction Stop $NupkgFilePath = Get-NupkgFilePath -Module $InputObject -Path $OutputPath -ErrorAction Stop Push-Location -StackName PSPublishHelperNugetPack -Path $TempPath -ErrorAction Stop $Output = & $Nuget pack $NuspecPath -OutputDirectory $OutputPath -BasePath $TempPath -Verbosity detailed -NonInteractive -NoDefaultExcludes Write-Verbose "Nuget Pack Output:" foreach($Line in $Output) { if($Line -notmatch 'NU5110|NU5111'){ Write-Verbose $Line } } } finally { Pop-Location -StackName PSPublishHelperNugetPack $Params = @{ Path = Split-path -Parent $TempPath Recurse = $true Force = $true ErrorAction = 'SilentlyContinue' } Microsoft.PowerShell.Management\Remove-Item @Params } if($PassThru) { Get-item -Path $NupkgFilePath -ErrorAction SilentlyContinue } } } #EndRegion '.\src\PSPublishHelper\public\Publish-PSModuleNuget.ps1' 143 |