I am presenting Continuous Delivery for your PowerShell Module to the PowerShell Gallery at PSDayUK in London. Go and register if you will be close to London on Friday 22nd September.
In 45 minutes we will
– Use Plaster to create our module framework
– Use GitHub for Version Control
– Use Pester to develop our module with TDD
– Use VSTS to Build, Test (with Pester) and Release our changes to the PowerShell Gallery
45 minutes will not give me much time to dive deep into what is done but I will release all of my code on GitHub.
One of the things I needed to accomplish was to update the version number in the module manifest file. I did this with some regex and this is how I achieved it.
I went to regex101.com and pasted in the contents of a module file into the test string box and start to work out what I need. I need the value after ModuleVersion = ‘ so I started like this
Under the quick reference it has some explanations which will help you. Keep going until you have the correct value in the match information. In the image below you can see that it has a Group 1 in green which matches the value I want (0.9.13). There is also an explanation of how it has got there. This is what I shall use in the PowerShell script
Now we can go to PowerShell. First get the contents of the file
# get the contents of the module manifest file try { $file = (Get-Content .\BeardAnalysis.psd1) } catch { Write-Error "Failed to Get-Content" }
Then we use [regex]::matches() to get our value as shown below. I always like to write in the comments what the regex is doing so that I (or others) know what was intended. We also set the value to a type of Version. I reference the group 1 value that I saw in the website.
# Use RegEx to get the Version Number and set it as a version datatype # \s* - between 0 and many whitespace # ModuleVersion - literal # \s - 1 whitespace # = - literal # \s - 1 whitespace # ' - literal # () - capture Group # \d* - between 0 and many digits # ' - literal # \s* between 0 and many whitespace [version]$Version = [regex]::matches($file, "\s*ModuleVersion\s=\s'(\d*.\d*.\d*)'\s*").groups[1].value
Next we need to add one to the version number
# Add one to the build of the version number [version]$NewVersion = "{0}.{1}.{2}" -f $Version.Major, $Version.Minor, ($Version.Build + 1)
and then replace the value in the file, notice the Get-Content has braces around it
# Replace Old Version Number with New Version number in the file try { (Get-Content .\BeardAnalysis.psd1) -replace $version, $NewVersion | Out-File .\BeardAnalysis.psd1 Write-Output "Updated Module Version from $Version to $NewVersion" } catch { $_ Write-Error "failed to set file" }
That’s how I do it and the process I use when I need regex!
Here is the full script
# get the contents of the module manifest file try { $file = (Get-Content .\BeardAnalysis.psd1) } catch { Write-Error "Failed to Get-Content" } # Use RegEx to get the Version Number and set it as a version datatype # \s* - between 0 and many whitespace # ModuleVersion - literal # \s - 1 whitespace # = - literal # \s - 1 whitespace # ' - literal # () - capture Group # \d* - between 0 and many digits # ' - literal # \s* between 0 and many whitespace [version]$Version = [regex]::matches($file, "\s*ModuleVersion\s=\s'(\d*.\d*.\d*)'\s*").groups[1].value Write-Output "Old Version - $Version" # Add one to the build of the version number [version]$NewVersion = "{0}.{1}.{2}" -f $Version.Major, $Version.Minor, ($Version.Build + 1) Write-Output "New Version - $NewVersion" # Replace Old Version Number with New Version number in the file try { (Get-Content .\BeardAnalysis.psd1) -replace $version, $NewVersion | Out-File .\BeardAnalysis.psd1 Write-Output "Updated Module Version from $Version to $NewVersion" } catch { $_ Write-Error "failed to set file" }
An easier way
My fabulous friend and MVP Ravikanth Chaganti has told me of a better way using Import-PowerShellDataFile
This command is available on PowerShell v5 and above. There is no need to use regex now 🙂 You can just get the manifest as an object and then use the Update-ModuleManifest to update the file
$manifest = Import-PowerShellDataFile .\BeardAnalysis.psd1 [version]$version = $Manifest.ModuleVersion # Add one to the build of the version number [version]$NewVersion = "{0}.{1}.{2}" -f $Version.Major, $Version.Minor, ($Version.Build + 1) # Update the manifest file Update-ModuleManifest -Path .\BeardAnalysis.psd1 -ModuleVersion $NewVersion
I was going to say, my god youre working hard to get the manifest 😁. I think Test-ModuleManifest does something similar to the import data file.
i ran into the following weird problem:
created a module
c:\Users\Administrator\Documents\WindowsPowerShell\Modules\Toolbox\
with two subfolders:
\0.0.1\
\0.0.2\
in each folder i added:
ToolBox.psd1
ToolBox.psm1
for folder 0.0.1 i edited the psd1 file
# Script module or binary module file associated with this manifest.
RootModule = ‘ToolBox’
# Version number of this module.
ModuleVersion = ‘0.0.1’
and ofcourse
# Script module or binary module file associated with this manifest.
RootModule = ‘ToolBox’
# Version number of this module.
ModuleVersion = ‘0.0.2’
the name of the module has to be the same as the folder name (same as RootModule)
the module reads all the *.ps1 files in the folders
\private\*.ps1
\public\*.ps1
when i would create a third new version (0.0.3) i would do the following if automated:
make a copy of the latest version 0.0.2 and rename the folder 0.0.3
\0.0.3\
the contents of version 0.0.2 will be copied to 0.0.3
when i edit manually the contents of the toolbox.psd1 file
# Version number of this module.
ModuleVersion = ‘0.0.2’ -> ModuleVersion = ‘0.0.3’
everything goes fine and i can load it as the new version.
however, if i have copied it and want to use the version number updater methode:
$mod = c:\Users\Administrator\Documents\WindowsPowerShell\Modules\Toolbox\0.0.3\toolbox.psd1
$manifest = Import-PowerShellDataFile $mod
$manifest
(shows version 0.0.2)
then i would do:
Update-ModuleManifest -Path $mod -ModuleVersion ‘0.0.3’
and it raises an error:
Update-ModuleManifest : Cannot update the manifest properly. ‘The ModuleVersion key in module manifest
‘C:\Users\Administrator\Documents\WindowsPowerShell\Modules\Toolbox\0.0.3\toolbox.psd1’ specifies module version ‘0.0.2’ which does not match its version folder name at
‘C:\Users\Administrator\Documents\WindowsPowerShell\Modules\Toolbox\0.0.3′. Change the value of the ModuleVersion key to match the version folder name.’
At line:1 char:1
+ Update-ModuleManifest -Path c:\Users\Administrator\Documents\Windows …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (c:\Users\Admini….3\toolbox.psd1:String) [Update-ModuleManifest], ArgumentException
+ FullyQualifiedErrorId : InvalidModuleManifestFile,Update-ModuleManifest
So to change the version i need to “Change the value of the ModuleVersion key to match the version folder name.”
Powershell 5.1 on a windows 2012 R2 standard server.
I guess that makes sense, you are updating the version in the folder that you are using. I would separate the development of the code from the artefact that you are using
I am updating the manifest in a folder provided from source control before zipping it up to publish to a PowerShell Repository.
So I would perform the update on the code in source control and then publish it or copy it to the modules folder
Thnaks for the quick reply. 🙂
Im not updating the version that i am using: i still use the version (0.0.2) that is copy to a new one (0.0.3). I didn’t load the newly created module version. (import-module -force). All the other properties i can set.
i now read the manifest (from current active module Import-PowerShellDataFile ) and create a new manifest (New-ModuleManifest) with all the same properties. and raising the module version.
not bieng able to update the version number in this specific case feels more like a bug.