Skip to content

Instantly share code, notes, and snippets.

@Jaykul
Last active December 28, 2023 05:34
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Jaykul/0031bbb459c1ab6ced2bde7558130ede to your computer and use it in GitHub Desktop.
Save Jaykul/0031bbb459c1ab6ced2bde7558130ede to your computer and use it in GitHub Desktop.
Update Module Version ... or anything else
function Update-Manifest {
#.Synopsis
# Update a PowerShell module manifest
#.Description
# By default Update-Manifest increments the ModuleVersion, but it can set any key in the Module Manifest, its PrivateData, or the PSData in PrivateData.
#
# NOTE: This cannot currently create new keys, or uncomment keys.
#.Example
# Update-Manifest .\Configuration.psd1
#
# Increments the Build part of the ModuleVersion in the Configuration.psd1 file
#.Example
# Update-Manifest .\Configuration.psd1 -Increment Major
#
# Increments the Major version part of the ModuleVersion in the Configuration.psd1 file
#.Example
# Update-Manifest .\Configuration.psd1 -Value '0.4'
#
# Sets the ModuleVersion in the Configuration.psd1 file to 0.4
#.Example
# Update-Manifest .\Configuration.psd1 -Property ReleaseNotes -Value 'Add the awesome Update-Manifest function!'
#
# Sets the PrivateData.PSData.ReleaseNotes value in the Configuration.psd1 file!
[CmdletBinding()]
param(
# The path to the module manifest file
[Parameter(ValueFromPipelineByPropertyName="True", Position=0)]
[Alias("PSPath")]
[string]$Manifest,
# The property to be set in the manifest. It must already exist in the file (and not be commented out)
# This searches the Manifest root properties, then the properties PrivateData, then the PSData
[Parameter(ParameterSetName="Overwrite")]
[string]$PropertyName = 'ModuleVersion',
# A new value for the property
[Parameter(ParameterSetName="Overwrite", Mandatory)]
$Value,
# By default Update-Manifest increments ModuleVersion; this controls which part of the version number is incremented
[Parameter(ParameterSetName="Increment")]
[ValidateSet("Major","Minor","Build","Revision")]
[string]$Increment = "Build",
# When set, and incrementing the ModuleVersion, output the new version number.
[Parameter(ParameterSetName="Increment")]
[switch]$Passthru
)
$KeyValue = Get-ManifestValue $Manifest -PropertyName $PropertyName -Passthru
if($PSCmdlet.ParameterSetName -eq "Increment") {
$Version = [Version]$KeyValue.SafeGetValue()
$Version = switch($Increment) {
"Major" {
[Version]::new($Version.Major + 1, 0)
}
"Minor" {
$Minor = if($Version.Minor -le 0) { 1 } else { $Version.Minor + 1 }
[Version]::new($Version.Major, $Minor)
}
"Build" {
$Build = if($Version.Build -le 0) { 1 } else { $Version.Build + 1 }
[Version]::new($Version.Major, $Version.Minor, $Build)
}
"Revision" {
$Revision = if($Version.Revision -le 0) { 1 } else { $Version.Revision + 1 }
[Version]::new($Version.Major, $Version.Minor, $Version.Build, $Revision)
}
}
$Value = $Version
if($Passthru) { $Value }
}
$Value = ConvertTo-Metadata $Value
$Extent = $KeyValue.Extent
while($KeyValue.parent) { $KeyValue = $KeyValue.parent }
$ManifestContent = $KeyValue.Extent.Text.Remove(
$Extent.StartOffset,
($Extent.EndOffset - $Extent.StartOffset)
).Insert($Extent.StartOffset, $Value)
if(Test-Path $Manifest) {
Set-Content $Manifest $ManifestContent
} else {
$ManifestContent
}
}
function Get-ManifestValue {
#.Synopsis
# Reads a specific value from a module manifest
#.Description
# By default Get-ManifestValue gets the ModuleVersion, but it can read any key in the Module Manifest, including the PrivateData, or the PSData inside the PrivateData.
#.Example
# Get-ManifestValue .\Configuration.psd1
#
# Returns the module version number (as a string)
#.Example
# Get-ManifestValue .\Configuration.psd1 ReleaseNotes
#
# Returns the release notes!
[CmdletBinding()]
param(
# The path to the module manifest file
[Parameter(ValueFromPipelineByPropertyName="True", Position=0)]
[Alias("PSPath")]
[string]$Manifest,
# The property to be read from the manifest. Get-ManifestValue searches the Manifest root properties, then the properties PrivateData, then the PSData
[Parameter(ParameterSetName="Overwrite", Position=1)]
[string]$PropertyName = 'ModuleVersion',
[switch]$Passthru
)
$ErrorActionPreference = "Stop"
if(Test-Path $Manifest) {
$ManifestContent = Get-Content $Manifest -Raw
} else {
$ManifestContent = $Manifest
}
$Tokens = $Null; $ParseErrors = $Null
$AST = [System.Management.Automation.Language.Parser]::ParseInput( $ManifestContent, $Manifest, [ref]$Tokens, [ref]$ParseErrors )
$ManifestHash = $AST.Find( {$args[0] -is [System.Management.Automation.Language.HashtableAst]}, $true )
$KeyValue = $ManifestHash.KeyValuePairs.Where{ $_.Item1.Value -eq $PropertyName }.Item2
# Recursively search for PropertyName in the PrivateData and PrivateData.PSData
if(!$KeyValue) {
$global:PrivateData = $ManifestHash.KeyValuePairs.Where{ $_.Item1.Value -eq 'PrivateData' }.Item2.PipelineElements.Expression
$KeyValue = $PrivateData.KeyValuePairs.Where{ $_.Item1.Value -eq $PropertyName }.Item2
if(!$KeyValue) {
$global:PSData = $PrivateData.KeyValuePairs.Where{ $_.Item1.Value -eq 'PSData' }.Item2.PipelineElements.Expression
$KeyValue = $PSData.KeyValuePairs.Where{ $(Write-Verbose "'$($_.Item1.Value)' -eq '$PropertyName'"); $_.Item1.Value -eq $PropertyName }.Item2
if(!$KeyValue) {
Write-Error "Couldn't find '$PropertyName' to update in '$(Convert-Path $ManifestPath)'"
return
}
}
}
if($Passthru) { $KeyValue } else { $KeyValue.SafeGetValue() }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment