PSDeployScripts/PSGalleryScript.ps1
<# .SYNOPSIS Deploys a script to a PowerShell repository like the PowerShell Gallery. .DESCRIPTION Deploys a script to a PowerShell repository like the PowerShell Gallery. This only supports publishing items that do not already have a PSScriptInfo header. We might support this down the line when Update-ScriptFileInfo is fixed. Notes on how we define the PSScriptInfo header based on your WithOptions parameters and other info: * If you specify a WithOptions parameter, that takes precedence over an existing publication * If you do not specify a WithOptions parameter and have previously published this, we query and re-use data from the existing published script * In a few special cases (required fields), we will generate initial data if you do not include it in WithOptions or have an existing published script: GUID - We create a new GUID VERSION - we set to 1.0.0 AUTHOR - We set to Unknown DESCRIPTION - We set to the file name (e.g. if I publish Open-IseFunction.ps1, DESCRIPTION=Open-ISEFunction) .PARAMETER Deployment Deployment to run Source is the path of the module to deploy. Target is a valid PSRepository name. Defaults to PSGallery .PARAMETER ApiKey API Key used to authenticate to PowerShell repository. .PARAMETER VERSION VERSION for script info We set to 1.0.0 if you don't include it here or in a previously published version Note that you need to bump this for a successful publish, you can't overwrite an existing version .PARAMETER GUID GUID for script info We create a new one if you don't include it here or in a previously published version .PARAMETER AUTHOR AUTHOR for script info We set to unknown if you don't include it here or in a previously published version .PARAMETER DESCRIPTION DESCRIPTION for script info We set to the basename of your script if you don't include it here or in a previously published version .PARAMETER COMPANYNAME COMPANYNAME for script info .PARAMETER COPYRIGHT COPYRIGHT for script info .PARAMETER TAGS TAGS for script info .PARAMETER LICENSEURI LICENSEURI for script info .PARAMETER PROJECTURI PROJECTURI for script info .PARAMETER ICONURI ICONURI for script info .PARAMETER EXTERNALMODULEDEPENDENCIES EXTERNALMODULEDEPENDENCIES for script info .PARAMETER REQUIREDSCRIPTS REQUIREDSCRIPTS for script info .PARAMETER EXTERNALSCRIPTDEPENDENCIES EXTERNALSCRIPTDEPENDENCIES for script info .PARAMETER RELEASENOTES RELEASENOTES for script info #> [cmdletbinding()] param( [ValidateScript({ $_.PSObject.TypeNames[0] -eq 'PSDeploy.Deployment' })] [psobject[]]$Deployment, [Parameter(Mandatory)] [string]$ApiKey ) # We make the assumption that WithOptions may be updated by the user or build process. It takes precedence. function Pick-Precedence { [cmdletbinding()] param( $Name, $PSGalleryOutput = $Existing ) $WithOptionsValue = $null $WithOptionsValue = $Deploy.DeploymentOptions.$Name $ExistingValue = $null $ExistingValue = $PSGalleryOutput.$Name if($WithOptionsValue) { $WithOptionsValue } else { $ExistingValue } } foreach($deploy in $Deployment) { if(-not $deploy.Targets) { #Default to the PSGallery $deploy.Targets = @('PSGallery') } foreach($target in $deploy.Targets) { Write-Verbose -Message "Starting deployment [$($deploy.DeploymentName)] to PowerShell repository [$Target]" # Validate that $target has been setup as a valid PowerShell repository $validRepo = Get-PSRepository -Name $target -Verbose:$false -ErrorAction SilentlyContinue if (-not $validRepo) { throw "[$target] has not been setup as a valid PowerShell repository." } # Check gallery for existing. We don't want a new GUID every time... $Name = ( Get-Item $Deploy.source -ErrorAction Stop ).BaseName $Existing = $null $Existing = @( Find-Script -Name $Name -Repository $Target ) if ($Existing.Count -gt 1) { Write-Error "We found more than one script matching $Name. Did you include a wildcard?" continue } elseif($Existing.Count -eq 1) { # guid is in the additionalmetadata hash $Existing[0] | Add-Member -MemberType NoteProperty -Name GUID -Value $Existing.AdditionalMetadata['GUID'] } # Extract deployment options / header values. Not all of these are props. $AllNodes = echo VERSION GUID AUTHOR COMPANYNAME COPYRIGHT, TAGS LICENSEURI PROJECTURI ICONURI, EXTERNALMODULEDEPENDENCIES, REQUIREDSCRIPTS, EXTERNALSCRIPTDEPENDENCIES, RELEASENOTES, DESCRIPTION foreach($item in $AllNodes) { $value = $null $value = Pick-Precedence -Name $Item -PSGalleryOutput $Existing Set-Variable -Name $Item -Value $value } # Items that might be blank on new scripts, that we need filled out if(-not $GUID) { $GUID = [GUID]::NewGuid().Guid } if(-not $VERSION) { $VERSION = '1.0.0' } if(-not $AUTHOR) { $AUTHOR = 'Unknown' } if(-NOT $DESCRIPTION) { $DESCRIPTION = $Name } # Build up the header $Header = "<#PSScriptInfo`r`n" $Nodes = echo VERSION GUID AUTHOR DESCRIPTION COMPANYNAME COPYRIGHT TAGS LICENSEURI PROJECTURI, ICONURI EXTERNALMODULEDEPENDENCIES REQUIREDSCRIPTS EXTERNALSCRIPTDEPENDENCIES RELEASENOTES foreach($item in $Nodes) { $Value = $null If($Value = Get-Variable -Name $item -ValueOnly -ErrorAction SilentlyContinue) { $header += ".$item`r`n $Value`r`n" } } $header += "#>`r`n" # Write the header, publish $SourceContent = Get-Content $Deploy.Source -Raw Set-Content $Deploy.Source -Value "$Header$SourceContent" -Force # Start building params $Params = @{ Path = $Deploy.Source Repository = $Target NugetApiKey = $Deploy.DeploymentOptions.ApiKey Verbose = $VerbosePreference } Publish-Script @params } } |