Deploying Bicep Templates using GitHub Actions
Stephen Tulp
December 14, 2023
9 minutes to read
Introduction
Today we will look at how we can use GitHub Actions showcasing a simple workflow to deploy Bicep templates to Azure. This workflow will cover some of the concepts that we have covered across the month.
Before we get into the workflow and breaking down the steps, let’s visualize what an end-to-end process could look like for this.
- Developer creates a branch from the main branch and makes changes to the Bicep templates.
- These changes are committed into the branch.
- Once all the changes are committed, a pull request is created.
- Before the pull request is merged, workflows are triggered to validate the Bicep templates (Linting, Unit tests, etc.).
- Someone with the required permissions reviews the pull request and approves it so that it merges it into the main branch.
- This triggers the deployment workflow which deploys the Bicep templates to Azure.
GitHub Action Workflow
Lets take a look at the overall workflow that we will be using before breaking down each of the jobs across Build
, Validate
, Test
and Deploy
. The workflow is defined in the .github/workflows
folder in the Insight Bicep Advent Calendar Repo.
---
name: Landing Zone Vending Deployment
on:
push:
branches:
- main
paths:
- src/configuration/sub-sap-prd-01.parameters.bicepparam
- src/orchestration/main.bicep
workflow_dispatch: {}
env:
managementGroupId: ''
location: 'australiaeast'
moduleName: LandingZoneVendingMachine
templateFile: src/orchestration/main.bicep
templateParameterFile: src/configuration/sub-sap-prd-01.parameters.bicepparam
runNumber: $
secrets: $
jobs:
Build:
runs-on: ubuntu-latest
steps:
- name: "Checkout Repository"
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Bicep Build
uses: Azure/cli@v1.0.7
with:
inlineScript: |
az bicep build -f $ --stdout
Validate:
runs-on: ubuntu-latest
needs: Build
steps:
- name: Checkout Repository
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Run PSRule Analysis
uses: microsoft/ps-rule@latest
with:
inputType: inputPath
inputPath: $
modules: PSRule.Rules.Azure, PSRule.Rules.CAF
baseline: Azure.GA_2023_09
outputFormat: NUnit3
outputPath: reports/ps-rule-results.xml
continue-on-error: false
- name: Azure Login
uses: azure/login@v1.4.5
with:
creds: $
- name: Validate Deployment
uses: Azure/cli@v1.0.7
with:
inlineScript: |
az deployment mg validate -n "$-$" -m $ -l $ -f $ -p $
WhatIf:
runs-on: ubuntu-latest
needs: Validate
steps:
- name: Checkout Repository
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Azure Login
uses: azure/login@v1.4.5
with:
creds: $
- name: What-If
uses: Azure/cli@v1.0.7
with:
inlineScript: |
az deployment mg what-if -n "$-$" -m $ -l $ > whatif -f $ -p $ --exclude-change-types Ignore NoChange Unsupported --result-format FullResourcePayloads
Deploy:
runs-on: ubuntu-latest
needs: WhatIf
if: github.ref == 'refs/heads/main'
steps:
- name: Checkout Repository
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Azure Login
uses: azure/login@v1.4.5
with:
creds: $
- name: Create Deployment
uses: Azure/cli@v1.0.7
with:
inlineScript: |
az deployment mg create -n "$-$" -m $ -l $ -f $ -p $
Name Declaration
Defines the name of the workflow, this appears in the Actions tab
of the GitHub repo.
name: Landing Zone Vending Deployment
Triggers
The workflow will be triggered on a push to the main branch, where changes occur in the .bicepparam
and main.bicep
file. THe workflow_dispatch allows for manual triggering of the workflow for on demand runs.
on:
push:
branches:
- main
paths:
- src/configuration/sub-sap-prd-01.parameters.bicepparam
- src/orchestration/main.bicep
workflow_dispatch: {}
Environment Variables
Defining environment variables that will be used across jobs in the workflow.
env:
managementGroupId: ''
location: 'australiaeast'
moduleName: LandingZoneVendingMachine
templateFile: src/orchestration/main.bicep
templateParameterFile: src/configuration/sub-sap-prd-01.parameters.bicepparam
runNumber: $
secrets: $
The following environment variables are defined in the workflow:
managementGroupId
- The management group that the deployment will be deployed to.location
- The location that the deployment will be deployed to.moduleName
- The name of the module that will be deployed.templateFile
- The path to the Bicep template file.templateParameterFile
- The path to the Bicep parameter file.runNumber
- The run number of the workflow.secrets
- The Azure credentials that will be used to authenticate to Azure securely.
THe secrets
environment variable is defined in the GitHub repo under Settings > Secrets
and is defined as AZURE_CREDENTIALS
. The process for setting this up can be found here
### Jobs
The workflow contains four main jobs: `build`, `validate`, `test` and `Deploy`. Each job contains one or more steps that perform a specific task.
#### Build
The build job is responsible for building the Bicep template, this will convert the Bicep template to ARM template JSON.
```console
Build:
runs-on: ubuntu-latest
steps:
- name: "Checkout Repository"
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Bicep Build
uses: Azure/cli@v1.0.7
with:
inlineScript: |
az bicep build -f $ --stdout
Validate
The validate job is responsible for validating the Bicep template against PSRule. This will ensure that the Bicep template is compliant with the rules defined in the PSRule configuration and the Microsoft Well Architected Framework. This job also runs the az deployment mg validate
command to validate the Bicep template against Azure Resource Manager.
Validate:
runs-on: ubuntu-latest
needs: Build
steps:
- name: Checkout Repository
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Run PSRule Analysis
uses: microsoft/ps-rule@latest
with:
inputType: inputPath
inputPath: $
modules: PSRule.Rules.Azure, PSRule.Rules.CAF
baseline: Azure.GA_2023_09
outputFormat: NUnit3
outputPath: reports/ps-rule-results.xml
continue-on-error: false
- name: Azure Login
uses: azure/login@v1.4.5
with:
creds: $
- name: Validate Deployment
uses: Azure/cli@v1.0.7
with:
inlineScript: |
az deployment mg validate -n "$-$" -m $ -l $ -f $ -p $
Test
The test job is responsible for running the az deployment mg what-if
command to perform a what-if analysis on the Bicep template. This will show what changes will occur if the Bicep template is deployed to Azure.
WhatIf:
runs-on: ubuntu-latest
needs: Validate
steps:
- name: Checkout Repository
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Azure Login
uses: azure/login@v1.4.5
with:
creds: $
- name: What-If
uses: Azure/cli@v1.0.7
with:
inlineScript: |
az deployment mg what-if -n "$-$" -m $ -l $ > whatif -f $ -p $ --exclude-change-types Ignore NoChange Unsupported --result-format FullResourcePayloads
Deploy
The deploy job is responsible for deploying the Bicep template to Azure using the az deployment mg create
command.
Deploy:
runs-on: ubuntu-latest
needs: WhatIf
if: github.ref == 'refs/heads/main'
steps:
- name: Checkout Repository
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Azure Login
uses: azure/login@v1.4.5
with:
creds: $
- name: Create Deployment
uses: Azure/cli@v1.0.7
with:
inlineScript: |
az deployment mg create -n "$-$" -m $ -l $ -f $ -p $
The diagram below shows the workflow with the jobs and steps that are involved in the workflow. The above jobs can be consolidated, for example Build & Validate
but splitting it out into separate jobs allows for more granular control and visibility of the workflow.
Conclusion
Today we looked at how we can use GitHub Actions to deploy Bicep templates to Azure. We analyzed the overall workflow and the steps that are involved in the workflow. We also looked at the different steps that are involved in each job. Tomorrow we will start putting this all together and do an end-to-end deployment of the Landing Zone into Azure.
Further Reading
Some further reading on the topics covered in this post: