GitHub Actions Pipeline to execute Azure Bicep Templates to provision Azure Resources

Prasad ReddyPrasad Reddy
5 min read

In this section, we will explore how to set up a comprehensive GitHub Actions pipeline specifically designed for deploying Azure resources using Azure Bicep. Azure Bicep is a domain-specific language (DSL) that simplifies the process of managing Azure resources by providing a more readable syntax compared to traditional JSON ARM templates.

Link to Git Repo

https://github.com/vprasadreddy/azure-bicep-templates/blob/main/.github/workflows/azure_bicep_github_action_pipeline.yml

Visual Studio Code Extensions Installed

  1. Bicep

  2. Azure Pipelines

Prerequisites

  1. Create a Service Principal using AZ CLI

  2. Create GitHub Repo Secrets

  3. Create an Azure Resource Group

  4. Create GitHub Actions YAML pipeline

  5. Run the pipeline

Create a Service Principal using AZ CLI

  1. Get Azure Subscription ID from Azure Portal.

2. Create a Service Principal to be used in GitHub action pipeline to communicate with Azure. Replace subscription_id in below command with the Subscription ID obtained from above.

az ad sp create-for-rbac --name "github-actions-pipeline-spn" --role contributor --scopes /subscriptions/subscription_id --json-auth

3. After running the above command, it will generate a JSON output as shown below.

{
  "clientId": "xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "clientSecret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "subscriptionId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "tenantId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "activeDirectoryEndpointUrl": "https://login.microsoftonline.com",
  "resourceManagerEndpointUrl": "https://management.azure.com/",
  "activeDirectoryGraphResourceId": "https://graph.windows.net/",
  "sqlManagementEndpointUrl": "https://management.core.windows.net:8443/",
  "galleryEndpointUrl": "https://gallery.azure.com/",
  "managementEndpointUrl": "https://management.core.windows.net/"
}

Create GitHub Repo Secrets

  1. Create a json object called AZURE_CREDENTIALS with clientId, clientSecret, subscriptionId, tenantId as a GitHub secret in GitHub Repo as shown in the image below.
  {
    "clientId": "xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "clientSecret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "subscriptionId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "tenantId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  }

Similarly create AZURE_CLIENT_ID, AZURE_CLIENT_SECRET & AZURE_TENANT_ID secrets.

Create an Azure Resource Group

  1. Go to Azure Portal https://portal.azure.com/#home and search for Resource groups in the search box. Select the option Resource groups from the dropdown.

  1. Create a Resource group by following below steps.

Create GitHub Actions YAML pipeline

  1. Create YAML pipeline under .github/workflows folder in your project directory.

.github/workflows/azure_bicep_github_action_pipeline.yml

  1. In the YAML pipeline replace env variables values.

  2. Change AZURE_RESOURCE_GROUP: "bicep-deployment-dev-rg" with whatever Resource Group name you have created in above steps under env section in the pipeline.

  3. Also change below environment variable values as per your requirements

    BICEP_TEMPLATE_FILE_PATH: "main.bicep" BICEP_TEMPLATE_FILE_PARAMETERS_PATH: "main.parameters.json" ENVIRONMENT: "dev"

  4. Modify push & pull triggers as per your requirements.

  5. Push the code and pipeline should trigger automatically based on the branch to which your code is pushed.

  6. Based on push triggers the workflow will run automatically.

# This is a basic workflow to help you get started with Actions

name: azure_bicep_github_action_pipeline

env:
  AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
  AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
  AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
  AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
  AZURE_RESOURCE_GROUP: "bicep-deployment-dev-rg"
  BICEP_TEMPLATE_FILE_PATH: "main.bicep"
  BICEP_TEMPLATE_FILE_PARAMETERS_PATH: "main.parameters.json"
  ENVIRONMENT: "dev"

# Controls when the workflow will run
on:
  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:
  push:
    branches:
      - main

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # This workflow contains a single job called "build"
  build:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest
    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v4

      # Install AZ CLI
      - name: Install AZ CLI
        run: |
          curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash

      # Authenticate to Az CLI using OIDC
      # - name: "Az CLI login"
      #   uses: azure/login@v1
      #   with:
      #     client-id: ${{ secrets.AZURE_CLIENT_ID }}
      #     tenant-id: ${{ secrets.AZURE_TENANT_ID }}
      #     subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

      - name: "Login via Azure CLI"
        uses: azure/login@v1
        with:
          creds: ${{ secrets.AZURE_CREDENTIALS }}

      # Bicep Lint
      - name: Bicep Lint
        run: |
          az bicep build --file ${{env.BICEP_TEMPLATE_FILE_PATH}}

      # Bicep Validate at Resource Group Level
      - name: Bicep Validate at Resource Group Level
        run: |
          az deployment group validate --name validate-group-deployment-${{ github.run_id }}-${{github.run_attempt}} \
          --resource-group ${{ env.AZURE_RESOURCE_GROUP }} \
          --template-file ${{env.BICEP_TEMPLATE_FILE_PATH}} \
          --parameters @${{env.BICEP_TEMPLATE_FILE_PARAMETERS_PATH}}

      # Bicep Validate at Subscription Level
      # - name: Bicep Validate at Subscription Level
      #   run: |
      #     az deployment sub validate \
      #     --name validate-subscription-deployment-${{ github.run_id }}-${{github.run_attempt}} \
      #     --template-file main.bicep \
      #     --location $LOCATION

      # Preview changes
      - name: "What-If"
        run: |
          az deployment group what-if \
          --name whatif-group-deployment-${{ github.run_id }}-${{github.run_attempt}} \
          --resource-group ${{ env.AZURE_RESOURCE_GROUP }} \
          --template-file ${{env.BICEP_TEMPLATE_FILE_PATH}} \
          --parameters @${{env.BICEP_TEMPLATE_FILE_PARAMETERS_PATH}} > whatif

      # Create string output of Whatif
      - name: Create String Output
        id: whatif-string
        run: |
          WHATIF=$(cat whatif)

          delimiter="$(openssl rand -hex 8)"
          echo "summary<<${delimiter}" >> $GITHUB_OUTPUT
          echo "## Whatif Output" >> $GITHUB_OUTPUT
          echo "<details><summary>Click to expand</summary>" >> $GITHUB_OUTPUT
          echo "" >> $GITHUB_OUTPUT
          echo '```' >> $GITHUB_OUTPUT
          echo "$WHATIF" >> $GITHUB_OUTPUT
          echo '```' >> $GITHUB_OUTPUT
          echo "</details>" >> $GITHUB_OUTPUT
          echo "${delimiter}" >> $GITHUB_OUTPUT

      # Publish Bicep Whatif Plan as task summary
      - name: Publish Whatif to Task Summary
        env:
          SUMMARY: ${{ steps.whatif-string.outputs.summary }}
        run: |
          echo "$SUMMARY" >> $GITHUB_STEP_SUMMARY

      # Deploy Bicep Code using Git Action
      # - name: Deploy Bicep Code using Git Action
      #   uses: azure/arm-deploy@v1
      #   with:
      #     scope: "resourcegroup"
      #     subscriptionId: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
      #     resourceGroupName: ${{ env.AZURE_RESOURCE_GROUP }}
      #     deploymentName: "${{env.ENVIRONMENT}}-deployment-${{ github.run_id }}-${{github.run_attempt}}"
      #     template: ${{env.BICEP_TEMPLATE_FILE_PATH}}
      #     parameters: ${{env.BICEP_TEMPLATE_FILE_PARAMETERS_PATH}}
      #     failOnStdErr: false

      # Deploy Bicep Code using AZ CLI command
      - name: Deploy Bicep Code using AZ CLI command
        run: |
          az deployment group create --resource-group ${{ env.AZURE_RESOURCE_GROUP }} \
          --name "${{env.ENVIRONMENT}}-deployment-${{ github.run_id }}-${{github.run_attempt}}" \
          --template-file ${{env.BICEP_TEMPLATE_FILE_PATH}} \
          --parameters @${{env.BICEP_TEMPLATE_FILE_PARAMETERS_PATH}}

Conclusion

I hope you liked this article and learned how to create GitHub Actions Pipeline to execute Azure Bicep Templates to provision Azure Resources

Follow me for more such interesting and useful articles ๐Ÿ˜Š

0
Subscribe to my newsletter

Read articles from Prasad Reddy directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Prasad Reddy
Prasad Reddy

Cloud & DevOps Engineer