functions/Update-ForgeDscModule.ps1
Function Update-ForgeDscModule { <# .SYNOPSIS Rebuild and publish Puppetized DSC modules .DESCRIPTION Rebuild and publish Puppetized DSC modules, bumping their Puppet build version by one. .PARAMETER ForgeNameSpace The namespace on the Forge to search for modules .PARAMETER Name The name of one or more Puppetized DSC modules to update. If no name is specified, will update all Puppetized DSC modules in the specified Forge namespace. .PARAMETER Version The specific version to update; if specified, can only be used with a single Name; rebuild one version of one module and publish it. .PARAMETER ForgeApiUri The Puppet Forge API URI to search and publish to; defaults to the public Puppet Forge .PARAMETER ForgeToken The Forge API Token for the target account. If not specified, will use the FORGE_TOKEN environment variable. Must pass a token either directly or via the environment variable to successfully publish to the Forge. .PARAMETER BuildFolderPath The path, relative or absolute, to the folder in which to Puppetize the module. If not specified, will do so in a folder called import in the current location. .PARAMETER PackageFolderPath The path, relative or absolute, to the folder in which to build the module. If not specified, will build in the pkg folder inside the BuildFolderPath. .PARAMETER LatestMajorVersionOnly If specified, will only rebuild releases from the latest major version for each module being updated. .PARAMETER MaximumVersionCountToRebuild If specified, will only rebuild and publish up to this many releases. .PARAMETER SleepAfterFailure If specified, will wait the specified number of seconds after a failure and before starting the next update attempt. Useful in local debugging and execution. .EXAMPLE Update-ForgeDscModule -ForgeNameSpace 'foo' This will search for every Puppetized DSC module in the 'foo' namespace of the public Puppet Forge and attempt to rebuild and publish (with an incremented Puppet build version) each release. .EXAMPLE Update-ForgeDscModule -ForgeNameSpace 'foo' -Name 'bar', 'baz' This will search for the 'bar' and 'baz' Puppetized DSC modules in the 'foo' namespace of the public Puppet Forge and attempt to rebuild and publish (with an incremented Puppet build version) each release of those modules. .EXAMPLE Update-ForgeDscModule -ForgeNameSpace 'foo' LatestMajorVersionOnly This will search for every Puppetized DSC module in the 'foo' namespace of the public Puppet Forge and attempt to rebuild and publish (with an incremented Puppet build version) only releases from the latest major version of each module; so if a module was released at 2.1.0.0, 2.0.0.0, 1.2.0.0, 1.1.0.0, and 1.0.0.0, only 2.1.0.0 and 2.0.0.0 would be rebuilt and published. .EXAMPLE Update-ForgeDscModule -ForgeNameSpace 'foo' MaximumVersionCountToRebuild 3 This will search for every Puppetized DSC module in the 'foo' namespace of the public Puppet Forge and attempt to rebuild and publish (with an incremented Puppet build version) only releases from the latest major version of each module; so if a module was released at 2.1.0.0, 2.0.0.0, 1.2.0.0, 1.1.0.0, and 1.0.0.0, only 2.1.0.0, 2.0.0.0, and 1.2.0.0 would be rebuilt and published. .INPUTS None. .OUTPUTS None. #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High', DefaultParameterSetName = 'ByNameSpace')] param ( [Parameter(Mandatory, ParameterSetName = 'ByNameSpace')] [Parameter(Mandatory, ParameterSetName = 'ByName')] [Parameter(Mandatory, ParameterSetName = 'ByNameAndVersion')] [string]$ForgeNameSpace, [Parameter(Mandatory, ParameterSetName = 'ByName')] [Parameter(Mandatory, ParameterSetName = 'ByNameAndVersion')] [string[]]$Name, [Parameter(Mandatory, ParameterSetName = 'ByNameAndVersion')] [version]$Version, [Parameter(ParameterSetName = 'ByNameSpace')] [Parameter(ParameterSetName = 'ByName')] [Parameter(ParameterSetName = 'ByNameAndVersion')] [string]$ForgeApiUri, [Parameter(ParameterSetName = 'ByNameSpace')] [Parameter(ParameterSetName = 'ByName')] [Parameter(ParameterSetName = 'ByNameAndVersion')] [string]$ForgeToken, [Parameter(ParameterSetName = 'ByNameSpace')] [Parameter(ParameterSetName = 'ByName')] [Parameter(ParameterSetName = 'ByNameAndVersion')] [string]$BuildFolderPath, [Parameter(ParameterSetName = 'ByNameSpace')] [Parameter(ParameterSetName = 'ByName')] [Parameter(ParameterSetName = 'ByNameAndVersion')] [string]$PackageFolderPath, [Parameter(ParameterSetName = 'ByNameSpace')] [Parameter(ParameterSetName = 'ByName')] [switch]$LatestMajorVersionOnly, [Parameter(ParameterSetName = 'ByNameSpace')] [Parameter(ParameterSetName = 'ByName')] [int]$MaximumVersionCountToRebuild, [Parameter(ParameterSetName = 'ByNameSpace')] [Parameter(ParameterSetName = 'ByName')] [int]$SleepAfterFailure = 0 ) Begin { $DefaultErrorActionPreference = $ErrorActionPreference If (![string]::IsNullOrEmpty($Version)) { If ($Name.Count -ne 1) { If ($Name.Count -eq 0) { $Message = 'Specified a Version without a Name; must specify a single Name if specifying Version' } If ($Name.Count -gt 1) { $Message = 'Specified a Version with multiple Names; must specify a single Name if specifying Version' } Throw $Message } # Standardize on a puppetized four-digit version string $PuppetizedVersion = ConvertTo-StandardizedVersionString -Version $Version $PuppetizedVersion = $PuppetizedVersion -replace '\.(\d+)$', '-$1' Write-PSFMessage -Level Verbose -Message "Puppetized Version: $PuppetizedVersion" } } Process { $FilterParams = @{} If (![string]::IsNullOrEmpty($ForgeApiUri)) { $FilterParams.ForgeSearchUri = "$ForgeApiUri/modules" } If (![string]::IsNullOrEmpty($ForgeNameSpace)) { $FilterParams.ForgeNameSpace = $ForgeNameSpace } If (![string]::IsNullOrEmpty($Name)) { $FilterParams.Name = $Name } Write-PSFMessage -Level Verbose -Message "Looking for DSC modules on the Forge with the filter:`r`n$($FilterParams | ConvertTo-Json)" $ModulesToRebuild = Get-ForgeModuleInfo @FilterParams foreach ($Module in $ModulesToRebuild) { $ReleasesToRebuild = Get-LatestBuild -Version $Module.Releases #region Filter Releases to Rebuild If ($LatestMajorVersionOnly) { $LatestMajorVersion = $ReleasesToRebuild[0].Version -split '\.' | Select-Object -First 1 $ReleasesToRebuild = $ReleasesToRebuild | Where-Object -FilterScript { $_.Version -match "^$LatestMajorVersion\." } } If ($MaximumVersionCountToRebuild -gt 0) { $ReleasesToRebuild = $ReleasesToRebuild | Select-Object -First $MaximumVersionCountToRebuild } If (![string]::IsNullOrEmpty($PuppetizedVersion)) { $ReleasesToRebuild = $ReleasesToRebuild | Where-Object -FilterScript { $_.Version -eq $PuppetizedVersion } If ($null -eq $ReleasesToRebuild) { Write-PSFMessage -Level Warning "Unable to find any releases at version '$PuppetizedVersion' for the '$($Module.Name)' module in the '$ForgeNameSpace' namespace" } } #endregion foreach ($VersionAndBuild in $ReleasesToRebuild) { try { $ErrorActionPreference = 'Stop' #region Build from Gallery $PuppetizeParameters = @{ PuppetModuleAuthor = $ForgeNameSpace PowerShellModuleName = [string]$Module.PowerShellModuleInfo.Name PowerShellModuleVersion = [string]$VersionAndBuild.Version -replace '-', '.' PassThru = $true } If (![string]::IsNullOrEmpty($BuildFolderPath)) { $PuppetizeParameters.OutputDirectory = $BuildFolderPath } Write-PSFMessage -Level Verbose -Message "Puppetizing with:`r`n$($PuppetizeParameters | ConvertTo-Json)" $ModuleFolderPath = New-PuppetDscModule @PuppetizeParameters | Select-Object -ExpandProperty FullName #endregion #region Update Build Version # Copy the VersionAndBuild object so as to be able to keep the comparison info $NewVersion = $VersionAndBuild | ConvertTo-Json | ConvertFrom-Json $Newversion.Build += 1 $NewVersion = $NewVersion | ConvertFrom-VersionBuild Write-PSFMessage -Level Verbose -Message "Bumping build version from $($VersionAndBuild | ConvertFrom-VersionBuild) to $NewVersion" Set-PuppetModuleVersion -PuppetModuleFolderPath $ModuleFolderPath -Version $NewVersion #endregion #region Export & Publish $PublishParameters = @{ PuppetModuleFolderPath = $ModuleFolderPath Build = $true Publish = $true Force = $true } If (![string]::IsNullOrEmpty($ForgeToken)) { $PublishParameters.ForgeToken = $ForgeToken } If (![string]::IsNullOrEmpty($ForgeApiUri)) { $PublishParameters.ForgeUploadUrl = "$ForgeApiUri/releases" } If (![string]::IsNullOrEmpty($PackageFolderPath)) { $PublishParameters.ExportFolderPath = $PackageFolderPath } Write-PSFMessage -Level Verbose -Message "Publishing $($Module.Name) at $($NewVersion) with`r`n$(($PublishParameters | ConvertTo-Json) -replace $ForgeToken, '<FORGE_TOKEN>')" Publish-PuppetModule @PublishParameters #endregion } catch { $ErrorActionPreference = $DefaultErrorActionPreference $ErrorParameters = @{ Message = "Unable to puppetize and publish $($Module.Name) for $($VersionAndBuild.Version)" ErrorRecord = $PSItem } If ($ErrorActionPreference -eq 'Stop') { $ErrorParameters.EnableException = $true } Stop-PSFFunction @ErrorParameters If ($SleepAfterFailure -gt 0) { Start-Sleep -Seconds $SleepAfterFailure } } } } } End { } } |