PowerShell and DevOps: Building a CI/CD Pipeline for a Module

choubertsprojects

VPN offers!

1. NordVPN

2. Surfshark

3. ExpressVPN

PowerShell and DevOps have been on the rise in popularity for years now, with many shops migrating from VBS code to .ps1 files. However, there are still some skeptics who think it won’t last much longer than a few months before people decide that scripting is too slow or cumbersome. What’s happening behind the scenes and how can you help your team build out more efficient pipelines?

The “powershell script to trigger azure devops pipeline” is a PowerShell script that can be used to build a CI/CD pipeline for modules. The powershell script will allow developers to integrate with the Azure DevOps Pipeline.

PowerShell and DevOps: Building a CI/CD Pipeline for a Module

PowerShell allows you to create everything from simple scripts to multi-hundred-line behemoths. When you become bored of writing PS1 script after PS1 script, you start thinking about reusable tools and merging PowerShell with DevOps through modules.

To create a module, launch a text editor and save the file as a PSM1. Done. You’ve done it! You’ve made a module! But only if it were as simple as that. A software development strategy is required to create a professional, repeatable module that can be used in production. In his eBook Building PowerShell Modules, Brandon Olin gives a solid example.

To create a “professional” PowerShell module, treat it as if it were C#, Java, or Python code. All of the same disciplines should be applied to a module as a developer would to a production software program. How do you go about doing that? Building a CI/CD pipeline is one option.

In this post, you’ll learn how to set up a CI/CD pipeline in Azure DevOps, commonly known as a build/release pipeline. You’ll see how to get a lot of value out of an automated build and test scenario (deployment coming soon)!

But hold on! There’s more! This is the first installment in a two-part series. In the following post, you’ll learn how to connect your PowerShell module pipeline to a NuGet feed and automate deployments.

Overview of the PowerShell DevOps Project

This post will be split down into a series of tutorials. You must read the whole essay from beginning to end. You’ll have a comprehensive Azure DevOps pipeline based on an example PowerShell module by the time you’re done.

This article will be divided into four parts, as follows:

  1. Setting up the demo environment — In this part, you’ll learn how to set up a GitHub repo.
  2. Overview of a PowerShell module — On this part, you’ll learn about a basic PowerShell module and its related artifacts, which are all housed in a GitHub repository. It makes no difference what the module performs. The module described here will just serve as a guide to help you learn how to insert your own custom module.
  3. Creating a DevOps project on Azure – This section contains a sequence of instructions that will help you quickly set up an Azure DevOps project for this course.
  4. Building the pipeline — In this part, you’ll see an example of a YAML-based Azure DevOps pipeline that updates the module and performs Pester Examinations.

The Multi-Stage Pipeline UI will be used to construct the pipeline. This feature is currently under Preview as of this writing.

Prerequisites

You’ll learn a lot, but you’ll also be expected to bring a few things to the table. If you want to follow along, you’ll need the following items:

  • A subscription to Azure
  • A GitHub account is required.
  • A DevOps organization on Azure — Instructions on how to accomplish this may be found in the Microsoft QuickStart handbook. You’ll be working on a PowerShellModuleProject project in this tutorial.
  • Installed Azure CLI — If you already have an Azure DevOps project, you won’t need this.
  • Installed the Pester Azure DevOps extension

Warning: Unless you have Azure credit, the acts you’re about to do may cost real money. For further details, see the Azure DevOps price page.

Using the Sample GitHub Repo to Import

You may utilize a PowerShell module that is already in a GitHub repository. If you don’t have a repo set up yet, you may use the one established for this tutorial. To utilize the supplied example repo, you must first create a copy or clone of your own. One method of cloning a GitHub repository is to “import” the code into a new repository.

Create a new repository on your GitHub account. A page similar to the one below should appear. Once you’ve done so, click the Import code option.

Using a GitHub Account to Create a New RepositoryUsing a GitHub Account to Create a New Repository

After that, you’ll be sent to the page below. Paste this tutorial’s example PowerShell module repo URL https://github.com/adbertram/PowerShellModuleProject in the Your previous repository’s clone URL box and select Begin Import as shown below.

Using GitHub to importUsing GitHub to import

You should soon see all of the contents of the example lesson accessible in your repo within a short amount of time.

Prompt for a New RepositoryPrompt for a New Repository

Overview of the PowerShell Repository

You should now have your own copy of the example GitHub repo, with a file structure similar to the one shown below. Some of these files, such as PSM1 or PSD1, may appear recognizable, while others may not. You’d best have a GitHub repo if you’re going to speak PowerShell and DevOps!

Overview of the Powershell Project on GitHubOverview of the Powershell Project on GitHub

In this post, you won’t learn the ins and outs of PowerShell module design. Understanding and Building PowerShell Modules and Brandon Olin’s eBook Building PowerShell Modules are good places to start if you want to learn more about this subject.

The following things may be found in this GitHub repository:

  • PowerShellModuleProject.psm1 — The PSM1 file that contains the code for exporting all of the module’s functions.
  • The Manifest of Modules is PowerShellModuleProject.psd1.
  • PesterTests.ps1 — A collection of example Pester Examinations in PowerShellModuleProject.ps1.
  • A public folder containing PS1 scripts with the same name as a single function that will be exported.
  • A secret folder containing a single PS1 script that will not be exported.
  • A Create a scripts folder that includes the Pipeline in YAML as well as all of the PowerShell scripts that will be executed by Azure Pipelines.

Scripts and Functions for the PowerShell Module

There are many methods for exporting functions in a module. Including all of the functions in the PSM1 file is a standard technique to expose them. This works for tiny modules, but it quickly gets unmanageable when dealing with hundreds of functions.

To make module functions easier to maintain, I prefer to divide them into two folders: public and private, each containing one script per function. Then, using the PSM1 file as the script, dot source all of the functions and export them all to the public folder.

Below is a screenshot of the PowerShellModuleProject.psm1 file.

Set-StrictMode -Version Latest # # # # # # # # # # # # # # # # # # # # # Get the files that define public and private functions. @Public = $Public (Get-ChildItem -Path -Path -Path -Path -Path -ErrorAction SilentlyContinue) $PSScriptRootPublic*.ps1 @(Get-ChildItem -Path $PSScriptRootPrivate*.ps1 -ErrorAction SilentlyContinue) $Private = @(Get-ChildItem -Path $PSScriptRootPrivate*.ps1 -ErrorAction SilentlyContinue) $Private = @(Get-Child # Create a dot source for the files. $import in @($Public + $Private)) foreach Write-Verbose “Importing $($import.FullName)” is a good option. $import.FullName $import.FullName $import.FullName $import catch Write-Error “Failed to import function $($import.FullName):

PowerShell allows you to create everything from simple scripts to multi-hundred-line behemoths. When you become bored of writing PS1 script after PS1 script, you start thinking about reusable tools and merging PowerShell with DevOps through modules.

To create a module, launch a text editor and save the file as a PSM1. Done. You’ve done it! You’ve made a module! But only if it were as simple as that. A software development strategy is required to create a professional, repeatable module that can be used in production. In his eBook Building PowerShell Modules, Brandon Olin gives a solid example.

To create a “professional” PowerShell module, treat it as if it were C#, Java, or Python code. All of the same disciplines should be applied to a module as a developer would to a production software program. How do you go about doing that? Building a CI/CD pipeline is one option.

In this post, you’ll learn how to set up a CI/CD pipeline in Azure DevOps, commonly known as a build/release pipeline. You’ll see how to get a lot of value out of an automated build and test scenario (deployment coming soon)!

But hold on! There’s more! This is the first installment in a two-part series. In the following post, you’ll learn how to connect your PowerShell module pipeline to a NuGet feed and automate deployments.

Overview of the PowerShell DevOps Project

This post will be split down into a series of tutorials. You must read the whole essay from beginning to end. You’ll have a comprehensive Azure DevOps pipeline based on an example PowerShell module by the time you’re done.

This article will be divided into four parts, as follows:

  1. Setting up the demo environment — In this part, you’ll learn how to set up a GitHub repo.
  2. Overview of a PowerShell module — On this part, you’ll learn about a basic PowerShell module and its related artifacts, which are all housed in a GitHub repository. It makes no difference what the module performs. The module described here will just serve as a guide to help you learn how to insert your own custom module.
  3. Creating a DevOps project on Azure – This section contains a sequence of instructions that will help you quickly set up an Azure DevOps project for this course.
  4. Building the pipeline — In this part, you’ll see an example of a YAML-based Azure DevOps pipeline that updates the module and performs Pester Examinations.

The Multi-Stage Pipeline UI will be used to construct the pipeline. This feature is currently under Preview as of this writing.

Prerequisites

You’ll learn a lot, but you’ll also be expected to bring a few things to the table. If you want to follow along, you’ll need the following items:

  • A subscription to Azure
  • A GitHub account is required.
  • A DevOps organization on Azure — Instructions on how to accomplish this may be found in the Microsoft QuickStart handbook. You’ll be working on a PowerShellModuleProject project in this tutorial.
  • Installed Azure CLI — If you already have an Azure DevOps project, you won’t need this.
  • Installed the Pester Azure DevOps extension

Warning: Unless you have Azure credit, the acts you’re about to do may cost real money. For further details, see the Azure DevOps price page.

Using the Sample GitHub Repo to Import

You may utilize a PowerShell module that is already in a GitHub repository. If you don’t have a repo set up yet, you may use the one established for this tutorial. To utilize the supplied example repo, you must first create a copy or clone of your own. One method of cloning a GitHub repository is to “import” the code into a new repository.

Create a new repository on your GitHub account. A page similar to the one below should appear. Once you’ve done so, click the Import code option.

Using a GitHub Account to Create a New RepositoryUsing a GitHub Account to Create a New Repository

After that, you’ll be sent to the page below. Paste this tutorial’s example PowerShell module repo URL https://github.com/adbertram/PowerShellModuleProject in the Your previous repository’s clone URL box and select Begin Import as shown below.

Using GitHub to importUsing GitHub to import

You should soon see all of the contents of the example lesson accessible in your repo within a short amount of time.

Prompt for a New RepositoryPrompt for a New Repository

Overview of the PowerShell Repository

You should now have your own copy of the example GitHub repo, with a file structure similar to the one shown below. Some of these files, such as PSM1 or PSD1, may appear recognizable, while others may not. You’d best have a GitHub repo if you’re going to speak PowerShell and DevOps!

Overview of the Powershell Project on GitHubOverview of the Powershell Project on GitHub

In this post, you won’t learn the ins and outs of PowerShell module design. Understanding and Building PowerShell Modules and Brandon Olin’s eBook Building PowerShell Modules are good places to start if you want to learn more about this subject.

The following things may be found in this GitHub repository:

  • PowerShellModuleProject.psm1 — The PSM1 file that contains the code for exporting all of the module’s functions.
  • The Manifest of Modules is PowerShellModuleProject.psd1.
  • PesterTests.ps1 — A collection of example Pester Examinations in PowerShellModuleProject.ps1.
  • A public folder containing PS1 scripts with the same name as a single function that will be exported.
  • A secret folder containing a single PS1 script that will not be exported.
  • A Create a scripts folder that includes the Pipeline in YAML as well as all of the PowerShell scripts that will be executed by Azure Pipelines.

Scripts and Functions for the PowerShell Module

There are many methods for exporting functions in a module. Including all of the functions in the PSM1 file is a standard technique to expose them. This works for tiny modules, but it quickly gets unmanageable when dealing with hundreds of functions.

To make module functions easier to maintain, I prefer to divide them into two folders: public and private, each containing one script per function. Then, using the PSM1 file as the script, dot source all of the functions and export them all to the public folder.

Below is a screenshot of the PowerShellModuleProject.psm1 file.

Set-StrictMode -Version Latest # Get public and private function definition files. $Public = @(Get-ChildItem -Path $PSScriptRootPublic*.ps1 -ErrorAction SilentlyContinue) $Private = @(Get-ChildItem -Path $PSScriptRootPrivate*.ps1 -ErrorAction SilentlyContinue) # Dot source the files. foreach ($import in @($Public + $Private)) { try { Write-Verbose “Importing $($import.FullName)” . $import.FullName } catch { Write-Error “Failed to import function $($import.FullName): $_” } } ## Export all of the public functions making them available to the user foreach ($file in $Public) { Export-ModuleMember -Function $file.BaseName }

The Manifest of Modules

Every PowerShell module project should always have a module manifest. Although the sample below does not use all of the accessible properties, it does cover the most important ones.

The hashtable keys ModuleVersion and FunctionsToExport should be noted. While kept in GitHub, both of these keys contain placeholders. Because you’ll be managing an Azure DevOps build for this PowerShell module, the placeholders are there. At build time, the build will execute a Create a script to replace these settings.

@{ RootModule = ‘PowerShellModuleProject.psm1’ ModuleVersion = ‘<ModuleVersion>’ GUID = ’73a14fd2-886e-43a6-a203-e53b2152cd5b’ Author = ‘Adam Bertram’ CompanyName = ‘Adam the Automator, LLC.’ PowerShellVersion = ‘6.0’ FunctionsToExport = @(‘<FunctionsToExport>’) }

Pester Examinations

The Pester test script given with this tutorial (PowerShellModuleProject.Tests.ps1) isn’t anything special. Testing is an essential part of any PowerShell DevOps effort. The purpose of this test script is to provide some example tests for the construction process. Do not consider your module thoroughly tested if you just use these two tests! To understand how to write genuine exams, read The Pester Book.

The test suites listed below guarantee that:

  • The module will be successfully imported.
  • There is a manifest for the module.
  • PSScriptAnalyzer’s default code-linting rules are given by the module.

Install-Module -Name PSScriptAnalyzer -Force describe ‘Module-level tests’ { it ‘the module imports successfully’ { { Import-Module “$PSScriptRootPowerShellModuleProject.psm1” -ErrorAction Stop } | should -not throw } it ‘There is a manifest for the module.’ { Test-Path “$PSScriptRootPowerShellModuleProject.psd1” | should -Be $true } it ‘passes all default PSScriptAnalyzer rules’ { Invoke-ScriptAnalyzer -Path “$PSScriptRootPowerShellModuleProject.psm1” | should -BeNullOrEmpty } }

Create a script

Finally, we have the Create a script. The PowerShell project you’ll be creating an automated build for is simple, a single Create a script below will do most of the heavy lifting.

You can read the comments with the code to understand what each step does. The Create a script is updating The Manifest of Modules’s version and dynamically adding all exportable functions.

$env:BUILDVER = $buildVersion ‘PowerShellModuleProject’ is the name of the module. $manifestPath = Join-Path -Path; $manifestPath = Join-Path -Path; $manifestP SYSTEM DEFAULTWORKINGDIRECTORY -ChildPath “$moduleName.psd1” $env:SYSTEM DEFAULTWORKINGDIRECTORY -ChildPath “$moduleName.psd1” ## In the manifest, update the build version. $manifest Get-Content -Path Content = Get-Content -Path -Raw $manifestPath $manifest $manifest = $content “,”,”,”,”,”,”,”, ## $buildVersion ## Locate all public functions $publicFuncFolderPath = Join-Path -Path -Path -Path -Path -Path -Path -Pa $PSScriptRoot -ChildPath ‘public’ if ((Test-Path -Path -Path -Path -Path -Path -Path -Path -Path -Pa $publicFunctionNames = Get-ChildItem -Path $publicFunctionFolderPath $publicFunctionNames = Get-ChildItem -Path $publicFunctionNames = Get-ChildItem -Path $publicFunctionName $publicFuncFolderPath -Filter ‘*.ps1’ | Select-Object -ExpandProperty BaseName)) $publicFuncFolderPath -Filter ‘*.ps1’ | Select-Object -ExpandProperty BaseName)) $publicFuncFold $funcStrings = “‘$($publicFunctionNames -join “‘,’”)’” if $funcStrings = “‘$($publicFunctionNames -join “‘,’”)’” if $funcStrings = “‘$($publicF $funcStrings = $null $funcStrings = $null $funcStrings = $null $funcStrings ## Set the FunctionsToExport property to all public functions. $manifestContent $manifestContent $manifestContent $manifestContent $manifestCon “””””””””””” $funcStrings Set-Content -Path $manifestContent $manifestPath

Quick Setup for Azure DevOps Projects

You should already be part of an Azure DevOps team. If that’s the case, you’ll need to start working on a project. A project may be created in a variety of ways. The Azure CLI is my preferred method. The commands you’ll need to start a project from scratch are shown below.

Run the scripts below in a PowerShell console, substituting the variables with your own subscription (required).

$subscriptionName = ‘<your subscription name>’ $azDoOrgName = ‘<your Azure DevOps org name>’ $projectName = ‘PowerShellModuleProject’ az login az account set –subscription $subscriptionName az extension add –name azure-devops az devops configure –defaults organization=https://dev.azure.com/$azDoOrgName az devops project create –name $projectName az devops configure –defaults project=$projectName

Check see Building an Azure DevOps Pipeline [Soup to Nuts] for a detailed description of each command. The Azure CLI is used to create an Azure DevOps project in the first section of this tutorial.

Setup of the Pipeline

It’s time to construct the pipeline once you’ve built the PowerShell DevOps project. All of the instructions needed to conduct the build, testing, and release procedures are included in the pipeline. Check out the Azure DevOps documentation or the Establishing a Pipeline part of the Building an Azure DevOps Pipeline [Soup to Nuts] article if you’re not acquainted with creating a pipeline.

A Pipeline in YAML has already been developed for you in the example GitHub repository for PowerShellModuleProject. Choose Existing Azure Pipelines YAML file as shown below when constructing the pipeline in Azure DevOps and getting to the Configure phase.

GitHub repository for PowerShellModuleProjectGitHub repository for PowerShellModuleProject

The build scripts folder contains the Pipeline in YAML. Azure Pipelines should already be aware of this and provide you the opportunity to choose a route from the Path menu, as seen below. To evaluate the pipeline once you’ve chosen a course, click Continue.

Pipeline in YAMLPipeline in YAML

To start the pipeline, go to the Review section and click Run. The pipeline will be created and then started by clicking Run.

Starting Pipeline in YAMLStarting Pipeline in YAML

You should see the pipeline hop through each of the three phases it was designed with once it is started.

A Powershell Azure PipelineA Powershell Azure Pipeline

You’ve now created an A Powershell Azure Pipeline project! But wait…what exactly did that do?

Pipeline in YAML Explanation

All phases in a pipeline are defined using YAML in Azure Pipelines (preview as of this writing). The pipeline was named azure-pipelines.yml and was put in the GitHub repo under the build scripts folder in this example project.

The sample pipeline in the GitHub repo isn’t the simplest, but it’s also not the most sophisticated you can create. The stages depend on what your module performs and what functionalities are available. It should, however, serve as an example of what is achievable.

Rather of going through each thing one by one, let’s take a look at what this pipeline accomplishes in general. Start with the Microsoft YAML reference if you’d need further information on individual components. The articles in the YAML reference set explain in detail what each element in the pipeline performs.

The Initiator

The Initiator is defined at the top. Choosing master here tells the pipeline to run as soon as a Git commit is detected. This trigger can be changed but is the default.

The Name

The pipeline’s name is an optional property that determines what you see when it runs, among other things.

‘PowerShell Module Project’ is the name of the project.

The Pipeline's NameThe Pipeline’s Name

Variables

Recall that ModuleVersion = ‘<ModuleVersion>’ line in The Manifest of Modules.  The module version is a placeholder to be defined at build time. You need to ensure this placeholder gets replaced by an actual version at build time.

Semantic versioning is one method for doing this. A typical way for assigning a version to a construction artifact is semantic versioning. A major, minor, and patch number are specified in the YAML format below. The major and minor numbers are now static 0 values, but the patch variable increases by one for each build.

The form [major] is created by combining all of these variables. [minor]. Using the buildVer variable, [patch] The buildVer variable will be 0.0.1, 0.0.2, 0.0.3, and so on after the build completes.

major: 0 minor: 0 variables: major: 0 minor: 0 variables: major: 0 minor: $ (patch) (Build.BuildID) $ buildVersion (major). $(minor). $(Build.BuildID)

The buildVer variable comes into play when the already-mentioned Create a script runs. You can see in the below snippet from the Create a script, the PowerShell script is reading the buildVer pipeline variable and inserting it into The Manifest of Modules.

$buildVersion = $env:BUILDVER $manifestContent = $manifestContent -replace ‘<ModuleVersion>’, $buildVersion

Understanding Azure DevOps Variables [Complete Guide] is a good place to start if you want to learn more about Azure DevOps variables.

The Pool

You’ll eventually come across the pool if you keep going down the pipeline. The pool specifies the VM image on which the build agent will execute. Because you don’t need anything special, the normal Ubuntu build agent will suffice.

vmImage: “ubuntu-latest” pool

Stages

Finally, we’ve arrived at the stages. This is where the true magic takes place. You have a lot of choices here, but for the sake of this tutorial, there are just two stages: Build and Test. The Deploy step will be discussed in the next article.

Because the pipeline isn’t doing anything special, each step contains a task with the same name as an optional job.

Build

The PowerShell script is run during the Build stage. The PowerShell process is started by looking for the build.ps1 script in the build scripts folder.

– stage: create employment – task: construct steps: – assignment: [email protected] inputs: ‘$(System.DefaultWorkingDirectory)/build scripts/build.ps1’ filePath: ‘$(System.DefaultWorkingDirectory)/build scripts/build.ps1’

Test

The Task for Pester Test Runner runs all tests in the PowerShellModuleProject.Tests.ps1 script and returns all test results to the PowerShellModuleProject.Tests.XML file, followed by the Test stage, which executes the Pester Test Runner job. When the pipeline is finished, the test results will be published on the pipeline’s test result page.

Install-Module -Name PSScriptAnalyzer -Force describe ‘Module-level tests’ { it ‘the module imports successfully’ { { Import-Module -Name “$PSScriptRootPowerShellModuleProject.psm1” -ErrorAction Stop } | should not throw } it ‘There is a manifest for the module.’ { Test-Path “$PSScriptRootPowerShellModuleProject.psd1” | should -Be $true } it ‘passes all default PSScriptAnalyzer rules’ { Invoke-ScriptAnalyzer -Path “$PSScriptRootPowerShellModuleProject.psm1” | should -BeNullOrEmpty } }

Task for Pester Test RunnerTask for Pester Test Runner

Deploy

After the test stage, it’s time to move on to the deployment step. Check out Publishing NuGet Packages to Azure Artifacts Automatically for more information on how to publish this project to a NuGet feed using Azure Artifacts.

Summary

You learnt one example of how to establish an automated CI/CD pipeline for a PowerShell module in this article. You should now have the foundational knowledge necessary to become more professional with your PowerShell modules and treat them like actual code!

Additional Reading

” catch Write-Error “Failed to import function $($import.FullName): $ ” ## Make all public functions accessible to the user foreach ($file in $Public) by exporting them. $file.BaseName -Function Export-ModuleMember

The Manifest of Modules

Every PowerShell module project should always have a module manifest. Although the sample below does not use all of the accessible properties, it does cover the most important ones.

The hashtable keys ModuleVersion and FunctionsToExport should be noted. While kept in GitHub, both of these keys contain placeholders. Because you’ll be managing an Azure DevOps build for this PowerShell module, the placeholders are there. At build time, the build will execute a Create a script to replace these settings.

@{ RootModule = ‘PowerShellModuleProject.psm1’ ModuleVersion = ‘<ModuleVersion>’ GUID = ’73a14fd2-886e-43a6-a203-e53b2152cd5b’ Author = ‘Adam Bertram’ CompanyName = ‘Adam the Automator, LLC.’ PowerShellVersion = ‘6.0’ FunctionsToExport = @(‘<FunctionsToExport>’) }

Pester Examinations

The Pester test script given with this tutorial (PowerShellModuleProject.Tests.ps1) isn’t anything special. Testing is an essential part of any PowerShell DevOps effort. The purpose of this test script is to provide some example tests for the construction process. Do not consider your module thoroughly tested if you just use these two tests! To understand how to write genuine exams, read The Pester Book.

The test suites listed below guarantee that:

  • The module will be successfully imported.
  • There is a manifest for the module.
  • PSScriptAnalyzer’s default code-linting rules are given by the module.

Install-Module -Name PSScriptAnalyzer -Force describe ‘Module-level tests’ { it ‘the module imports successfully’ { { Import-Module “$PSScriptRootPowerShellModuleProject.psm1” -ErrorAction Stop } | should -not throw } it ‘There is a manifest for the module.’ { Test-Path “$PSScriptRootPowerShellModuleProject.psd1” | should -Be $true } it ‘passes all default PSScriptAnalyzer rules’ { Invoke-ScriptAnalyzer -Path “$PSScriptRootPowerShellModuleProject.psm1” | should -BeNullOrEmpty } }

Create a script

Finally, we have the Create a script. The PowerShell project you’ll be creating an automated build for is simple, a single Create a script below will do most of the heavy lifting.

You can read the comments with the code to understand what each step does. The Create a script is updating The Manifest of Modules’s version and dynamically adding all exportable functions.

$env:BUILDVER = $buildVersion ‘PowerShellModuleProject’ is the name of the module. $manifestPath = Join-Path -Path; $manifestPath = Join-Path -Path; $manifestP SYSTEM DEFAULTWORKINGDIRECTORY -ChildPath “$moduleName.psd1” $env:SYSTEM DEFAULTWORKINGDIRECTORY -ChildPath “$moduleName.psd1” ## In the manifest, update the build version. $manifest Get-Content -Path Content = Get-Content -Path -Raw $manifestPath $manifest $manifest = $content “,”,”,”,”,”,”,”, ## $buildVersion ## Locate all public functions $publicFuncFolderPath = Join-Path -Path -Path -Path -Path -Path -Path -Pa $PSScriptRoot -ChildPath ‘public’ if ((Test-Path -Path -Path -Path -Path -Path -Path -Path -Path -Pa $publicFunctionNames = Get-ChildItem -Path $publicFunctionFolderPath $publicFunctionNames = Get-ChildItem -Path $publicFunctionNames = Get-ChildItem -Path $publicFunctionName $publicFuncFolderPath -Filter ‘*.ps1’ | Select-Object -ExpandProperty BaseName)) $publicFuncFolderPath -Filter ‘*.ps1’ | Select-Object -ExpandProperty BaseName)) $publicFuncFold $funcStrings = “‘$($publicFunctionNames -join “‘,’”)’” if $funcStrings = “‘$($publicFunctionNames -join “‘,’”)’” if $funcStrings = “‘$($publicF $funcStrings = $null $funcStrings = $null $funcStrings = $null $funcStrings ## Set the FunctionsToExport property to all public functions. $manifestContent $manifestContent $manifestContent $manifestContent $manifestCon “””””””””””” $funcStrings Set-Content -Path $manifestContent $manifestPath

Quick Setup for Azure DevOps Projects

You should already be part of an Azure DevOps team. If that’s the case, you’ll need to start working on a project. A project may be created in a variety of ways. The Azure CLI is my preferred method. The commands you’ll need to start a project from scratch are shown below.

Run the scripts below in a PowerShell console, substituting the variables with your own subscription (required).

$subscriptionName = ‘<your subscription name>’ $azDoOrgName = ‘<your Azure DevOps org name>’ $projectName = ‘PowerShellModuleProject’ az login az account set –subscription $subscriptionName az extension add –name azure-devops az devops configure –defaults organization=https://dev.azure.com/$azDoOrgName az devops project create –name $projectName az devops configure –defaults project=$projectName

Check see Building an Azure DevOps Pipeline [Soup to Nuts] for a detailed description of each command. The Azure CLI is used to create an Azure DevOps project in the first section of this tutorial.

Setup of the Pipeline

It’s time to construct the pipeline once you’ve built the PowerShell DevOps project. All of the instructions needed to conduct the build, testing, and release procedures are included in the pipeline. Check out the Azure DevOps documentation or the Establishing a Pipeline part of the Building an Azure DevOps Pipeline [Soup to Nuts] article if you’re not acquainted with creating a pipeline.

A Pipeline in YAML has already been developed for you in the example GitHub repository for PowerShellModuleProject. Choose Existing Azure Pipelines YAML file as shown below when constructing the pipeline in Azure DevOps and getting to the Configure phase.

GitHub repository for PowerShellModuleProjectGitHub repository for PowerShellModuleProject

The build scripts folder contains the Pipeline in YAML. Azure Pipelines should already be aware of this and provide you the opportunity to choose a route from the Path menu, as seen below. To evaluate the pipeline once you’ve chosen a course, click Continue.

Pipeline in YAMLPipeline in YAML

To start the pipeline, go to the Review section and click Run. The pipeline will be created and then started by clicking Run.

Starting Pipeline in YAMLStarting Pipeline in YAML

You should see the pipeline hop through each of the three phases it was designed with once it is started.

A Powershell Azure PipelineA Powershell Azure Pipeline

You’ve now created an A Powershell Azure Pipeline project! But wait…what exactly did that do?

Pipeline in YAML Explanation

All phases in a pipeline are defined using YAML in Azure Pipelines (preview as of this writing). The pipeline was named azure-pipelines.yml and was put in the GitHub repo under the build scripts folder in this example project.

The sample pipeline in the GitHub repo isn’t the simplest, but it’s also not the most sophisticated you can create. The stages depend on what your module performs and what functionalities are available. It should, however, serve as an example of what is achievable.

Rather of going through each thing one by one, let’s take a look at what this pipeline accomplishes in general. Start with the Microsoft YAML reference if you’d need further information on individual components. The articles in the YAML reference set explain in detail what each element in the pipeline performs.

The Initiator

The Initiator is defined at the top. Choosing master here tells the pipeline to run as soon as a Git commit is detected. This trigger can be changed but is the default.

The Name

The pipeline’s name is an optional property that determines what you see when it runs, among other things.

‘PowerShell Module Project’ is the name of the project.

The Pipeline's NameThe Pipeline’s Name

Variables

Recall that ModuleVersion = ‘<ModuleVersion>’ line in The Manifest of Modules.  The module version is a placeholder to be defined at build time. You need to ensure this placeholder gets replaced by an actual version at build time.

Semantic versioning is one method for doing this. A typical way for assigning a version to a construction artifact is semantic versioning. A major, minor, and patch number are specified in the YAML format below. The major and minor numbers are now static 0 values, but the patch variable increases by one for each build.

The form [major] is created by combining all of these variables. [minor]. Using the buildVer variable, [patch] The buildVer variable will be 0.0.1, 0.0.2, 0.0.3, and so on after the build completes.

major: 0 minor: 0 variables: major: 0 minor: 0 variables: major: 0 minor: $ (patch) (Build.BuildID) $ buildVersion (major). $(minor). $(Build.BuildID)

The buildVer variable comes into play when the already-mentioned Create a script runs. You can see in the below snippet from the Create a script, the PowerShell script is reading the buildVer pipeline variable and inserting it into The Manifest of Modules.

$buildVersion = $env:BUILDVER $manifestContent = $manifestContent -replace ‘<ModuleVersion>’, $buildVersion

Understanding Azure DevOps Variables [Complete Guide] is a good place to start if you want to learn more about Azure DevOps variables.

The Pool

You’ll eventually come across the pool if you keep going down the pipeline. The pool specifies the VM image on which the build agent will execute. Because you don’t need anything special, the normal Ubuntu build agent will suffice.

vmImage: “ubuntu-latest” pool

Stages

Finally, we’ve arrived at the stages. This is where the true magic takes place. You have a lot of choices here, but for the sake of this tutorial, there are just two stages: Build and Test. The Deploy step will be discussed in the next article.

Because the pipeline isn’t doing anything special, each step contains a task with the same name as an optional job.

Build

The PowerShell script is run during the Build stage. The PowerShell process is started by looking for the build.ps1 script in the build scripts folder.

– stage: create employment – task: construct steps: – assignment: [email protected] inputs: ‘$(System.DefaultWorkingDirectory)/build scripts/build.ps1’ filePath: ‘$(System.DefaultWorkingDirectory)/build scripts/build.ps1’

Test

The Task for Pester Test Runner runs all tests in the PowerShellModuleProject.Tests.ps1 script and returns all test results to the PowerShellModuleProject.Tests.XML file, followed by the Test stage, which executes the Pester Test Runner job. When the pipeline is finished, the test results will be published on the pipeline’s test result page.

Install-Module -Name PSScriptAnalyzer -Force describe ‘Module-level tests’ { it ‘the module imports successfully’ { { Import-Module -Name “$PSScriptRootPowerShellModuleProject.psm1” -ErrorAction Stop } | should not throw } it ‘There is a manifest for the module.’ { Test-Path “$PSScriptRootPowerShellModuleProject.psd1” | should -Be $true } it ‘passes all default PSScriptAnalyzer rules’ { Invoke-ScriptAnalyzer -Path “$PSScriptRootPowerShellModuleProject.psm1” | should -BeNullOrEmpty } }

Task for Pester Test RunnerTask for Pester Test Runner

Deploy

After the test stage, it’s time to move on to the deployment step. Check out Publishing NuGet Packages to Azure Artifacts Automatically for more information on how to publish this project to a NuGet feed using Azure Artifacts.

Summary

You learnt one example of how to establish an automated CI/CD pipeline for a PowerShell module in this article. You should now have the foundational knowledge necessary to become more professional with your PowerShell modules and treat them like actual code!

Additional Reading

The “azure devops powershell repository” is a PowerShell module that allows developers to build and deploy their modules. This article discusses how to build a CI/CD pipeline for this module.

Frequently Asked Questions

How do I create a pipeline in Azure DevOps using PowerShell?

A: Pipelines in Azure DevOps are created using the PowerShell commandlet New-AzurePipeline. The below syntax creates a new pipeline called mypipeline:
New-AzurePipeline -Name mypipeline -Description My Pipeline

Is PowerShell used in DevOps?

A: Yes, PowerShell is an essential tool in the DevOps workflow.

How do you build a CI CD pipeline DevOps?

A: To build a CD pipeline, you would need to use tools such as Jenkins and Chef. These tools allow for the orchestration of different tasks that are required in order to deploy your finished product.

Related Tags

  • azure devops powershell module
  • github powershell module example
  • azure devops powershell stop pipeline
  • psscriptanalyzer azure devops
  • azure devops install powershell module