Insight Tech APAC Blog Logo

Deploying Bicep Templates using GitHub Actions

stephentulp
December 14, 2023

9 minutes to read

Bicep Advent Calendar

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.

GitHub Deployment

  1. Developer creates a branch from the main branch and makes changes to the Bicep templates.
  2. These changes are committed into the branch.
  3. Once all the changes are committed, a pull request is created.
  4. Before the pull request is merged, workflows are triggered to validate the Bicep templates (Linting, Unit tests, etc.).
  5. Someone with the required permissions reviews the pull request and approves it so that it merges it into the main branch.
  6. 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.

GitHub Action 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: