Building an Azure Bicep release pipeline

If you follow the Microsoft Learn materials for Bicep mentioned in my previous Bicep post, you’ll notice that the learning materials deploy Bicep directly from the build pipeline. However if you’re building enterprise software, you’ll have multiple environments to deploy to.

This is where we typically use a release pipeline to promote a single artifact created by the build pipeline to the different environments with minimal configuration differences between the environments. In a good software development lifecycle you want to avoid rebuilding your codebase for every environment, but instead use a stable and well-tested artifact.

You can either create a normal pipeline and use variables to differentiate the multiple environments or go for a staged release pipeline where each stage is an environment. As always, it depends, but I usually prefer using a multi-stage release pipeline to deploy across environments. One of the main reasons is that you have a clear view of which step is deployed to which environment.

Azure DevOps Release pipeline

Infrastructure as Code is code as well, so we’re able to use the same principles of promoting a single artifact. For Bicep we can deploy a Bicep template as-is without the need for building an executable. There is also built-in support for multiple environments by using parameter files.

az deployment group create --resource-group <resource-group-name> --template-file <path-to-bicep> --parameters <path-to-bicep-parameters> 

Our build pipeline is nothing more than making a copy of the whole source directory. With this copy we have a ‘fixed’ version of the code in our artifact, which can’t change between environments and allows for promoting a tested configuration to other environments.

resources:
- repo: self
pool:
 vmImage: 'ubuntu-latest'
trigger:
  branches:
    include: [
      "master"
    ]
  paths:
    include: [
      "/"
    ]
steps:
- task: CopyFiles@2
  displayName: "Copy Files"
  inputs:
    Contents: |
      /**
      !**/.git/**
      !*.yml      
    TargetFolder: $(Build.ArtifactStagingDirectory)

- task: PublishBuildArtifacts@1
  displayName: "Publish Artifact: bicep templates"
  inputs:
    PathtoPublish: $(Build.ArtifactStagingDirectory)
    ArtifactName: sources
    publishLocation: Container

The magic happens in our release pipeline. First of all you’ll need a service principal with the correct rights to deploy to your Azure subscription. Depending on the scope of your Bicep templates this service principal needs access to a resource group, subscription or even management group or complete tenant.

Azure DevOps Release pipeline

First we select the artifact to use for our pipeline and then we start adding steps, one for each environment. I’ve also added a bonus step for template validation before running an actual deployment. This is done by replacing az deployment group create with az deployment group what-if, or simply adding --confirm-with-what-if to the first statement.

Since there is no explicit Bicep task yet, you can use either a PowerShell script or an Azure CLI task to deploy the Bicep templates. Personally I prefer Azure CLI, but since I had to deploy to a management group scope I was limited to PowerShell.

New-AzManagementGroupDeployment -ManagementGroupId mg-nonproduction -Location westeurope `
    -TemplateFile $(System.DefaultWorkingDirectory)\_IaC\sources\templates\main.bicep `
    -TemplateParameterFile $(System.DefaultWorkingDirectory)\_IaC\sources\templates\parameters\DEV.parameters.json `
    -Name (Get-Date -Format "yyyyMMddHHmmss") -Whatif

You can spot the different parts of the command, as you might have learned from following the learning materials. First of all we have the command to create a new deployment and its scope and location (which is only for the deployment files, not the actual Azure resources’ location). Next are both the template and parameter file that we receive from the artifact’s file directory. Note that I have defined a parameter file for each environment.

Finally make sure you’re using the right service principal with access to the scope you want to deploy to and you can start deploying.

Update: Meanwhile we have a few extra Learn modules available to help us out with releasing Bicep templates, be sure to check them out:

Licensed under CC BY-NC-SA 4.0; code samples licensed under MIT.
comments powered by Disqus
Built with Hugo - Based on Theme Stack designed by Jimmy