Now that I have my module on Github and built the module on Azure Pipelines, I want to publish it to the Powershell Gallery. The first step it of course to create a free account; once you have the account you can head to your profile, click on API Keys and then Create:
The Create dialog allows to choose the key name, the expiration and very important, the scope (what permission the key will have on the Gallery) and which packages the key is allowed to control through Global Pattern. In my case I want the key to expire every year, I want the key to grant permission to publish new packages and update existing ones and I want this key to be used only for LSE modules: notice I used LSE*
as Global Pattern, this way this same key will allow me to publish and manage new packages as long as their name begins with LSE
.
Azure Pipelines allows to securely store secrets (passwords and keys) as variables, if you want to do so you can use the Variables tab in your Pipeline then click the padlock icon:
Anyway I prefer to store the key in Azure KeyVault since I may decide to use it outside the Pipeline, in a script I can run manually for example. After adding the secret to KeyVault we need to authorize Azure Pipelines to retrieve the key: in Azure DevOps go to your project settings, select Service Connections under Pipelines, create a new service connection of type Azure Resource Manager
I am using a Service Principal created through the Service Connection dialog (you’ll get prompted to authorize Azure Pipelines to access your Azure Subscription)
I also have to grant the new Service Principal read access to Secrets under Access Policy in KeyVault.
Now I need to modify my Build Pipeline and add a Publish Pipeline Artifact
task. It takes only two arguments: artifactName
(LSECosmos on my example) and targetPath
(this is the path on the Pipeline Agent disk where to dump the files produced by the Build):
- task: PublishPipelineArtifact@0 inputs: artifactName: 'LSECosmos' targetPath: 'LSECosmos'
Now we can start to work on the Release pipeline: let’s start with an Empty Job
.
First thing, let’s add an Artifact and configure it to use the LSECosmos we just added as last step of the Build Pipeline. I’m going to use the Build
type:
I also want this Release to be triggered every time a Build succeeds, to do so let’s click on the round lightning bolt button and enable Continuous Deployment Integration
Then I need a new Stage and a number of Tasks to actually execute the steps needed to publish the module. My first step is to retrieve the Powershell Gallery Key from KeyVault:
Here I just need to use the appropriate Azure Subscription connection (you may have to authenticate and authorize Azure Pipelines to access the Subscription and KeyVault) and specify the KeyVault and Secret name to use:
It is not shown in the screenshot but under Output Variables I am storing the Key in a variable called LSECosmosPSGalleryKey so that I can use it in the next Task. In a typical classic scenario I would need a Download Pipeline Artifact
task to copy the artifacts (files) published by the Release Pipeline to use them with the Build Pipeline:
Anyway using the new Pipeline Artifacts instead (still in preview) the copy step is not needed; also, for large projects Pipeline Artifacts is faster than Build Artifacts (one more reason to upgrade to the new version).
The second (and in my case last) task is a very simple Powershell inline script, I need to make sure dependencies are in place (my module needs Az.Accounts and Az.Resources) and simply run Publish-Module -Path "$(System.ArtifactsDirectory)/_carlocardella.LSECosmos/LSECosmos" -NuGetApiKey "$(LSECosmosPSGalleryKey)"
In my Build Pipeline I decided to execute a script from my repo because I wanted to be able to execute the same build/script manually if needed; with the Release Pipeline though I am not following this approach because the script needs to use some Pipeline specific environment variables that would not exist outside of Azure Pipelines to I would not be able to manually run this script anyway. The module path I’m using ( "$(System.ArtifactsDirectory)/_carlocardella.LSECosmos/LSECosmos"
) comes from the default Release Pipeline download folder $(System.ArtifactsDirectory)
plus the name of my Build Pipeline (_carlocardella.LSECosmos
) plus the published Artifact name (LSECosmos
), while the Gallery Key is the same output variable created in the KeyVault Task: $(LSECosmosPSGalleryKey)
.
To test the Release pipeline we can use the Create Release button:
Next time I’ll merge some new commit to master
in my Github repo I will get a new Build, then the Release pipeline will kick in (assuming the Build is successful of course š) and the new LSECosmos module version will be published to the Powershell Gallery
TheĀ greatestĀ mistakeĀ you can make is to be continually fearing you will make one. – Elbert Hubbard |