How to deploy Azure Resource Manager (ARM) templates with GitHub Actions

In my previous post, I showed you how to connect a GitHub Action workflow to your Azure Subscription using the Azure login (azure/login) action. This article will show you how to deploy Azure Resource Manager (ARM) templates using GitHub Actions.

Our demo will implement the Azure infrastructure deployment of the whiteducksoftware/sample-mvc application using a GitHub Action workflow. The demo application is based on .NET Core 3.1 and runs on an Azure Web App. Here is how the website looks like:

Adding the ARM Template

The whiteducksoftware/sample-mvc application requires the following two Azure resources:

  • Azure App Service Plan
  • Azure Web App

Here is the corresponding ARM Template:

{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "appServicePlanName": {
            "type": "string",
            "metadata": {
                "description": "App Service Plan Name"
            }
        },
        "webAppName": {
            "type": "string",
            "metadata": {
                "description": "Web app name"
            }
        }
    },
    "variables": {
        "servicePlanSKU": "f1"
    },
    "resources": [

        {
            "name": "[parameters('appServicePlanName')]",
            "type": "Microsoft.Web/serverfarms",
            "apiVersion": "2018-02-01",
            "location": "[resourceGroup().location]",
            "sku": {
                "name": "[variables('servicePlanSKU')]",
                "capacity": 1
            },
            "tags": {
                "displayName": "[parameters('appServicePlanName')]"
            },
            "properties": {
                "name": "[parameters('appServicePlanName')]"
            }
        },
        {
            "name": "[parameters('webAppName')]",
            "type": "Microsoft.Web/sites",
            "apiVersion": "2016-08-01",
            "location": "[resourceGroup().location]",
            "dependsOn": [
                "[resourceId('Microsoft.Web/serverfarms', parameters('appServicePlanName'))]"
            ],
            "properties": {
                "name": "[parameters('webAppName')]",
                "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', parameters('appServicePlanName'))]"
            }
        }

    ],
    "outputs": {
    },
    "functions": [
    ]
}

The template is located at .azure/infrastructure/azuredeploy.json and is also available on GitHub.

Creating the GitHub Action workflow

We start with a GitHub Action workflow that performs a login to Azure. I already configured the deployment credentials (see Configure deployment credentials). The workflow is located under .github/workflows/infrastructure.yml:

on:
  push:
    branches:
      - master

name: Infrastructure

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Login to Azure
        uses: azure/login@v1
        with:
          creds: ${{ secrets.AZURE_CREDENTIALS }}

Here is a screenshot from the GitHub Action pipeline output. The “Login successful” output at line 29 confirms that we are able to establish a connection to Azure:

Right now the GitHub Action doesn’t have access to our files. We can change this by adding the GitHub checkout action:

- name: Checkout Sourcecode
        uses: actions/checkout@master

The action will check out our repository under $GITHUB_WORKSPACE.

Now we are able to deploy our ARM template. At the time of writing this, we can either do this using the az group deployment create Azure CLI task or using a GitHub Action from the Marketplace that is called Azure Resource Manager (ARM) Template Deployment:

The Action can be referenced using the whiteducksoftware/azure-arm-action-js@v1 repository and requires the following two parameters:

  • resourceGroupName: The name of the Resource Group
  • templateLocation: Path to the Azure Resource Manager template.

We will also pass the name of the Azure App Service plan and Azure Web App to the action using the optional parameters argument. This is how the deployment looks like:

- name: Deploy ARM Template
  uses: whiteducksoftware/azure-arm-action-js@v1
  with:
    resourceGroupName: github-action-rg
    templateLocation: .azure/infrastructure/azuredeploy.json
    parameters: |
      appServicePlanName=github-action-asp 
      webAppName=github-action-demo

That is all. Here are the complete Actions we are using for the infrastructure deployment:

on:
  push:
    branches:
      - master
    paths:
      - ".github/workflows/infrastructure.yml"
      - ".azure/infrastructure/azuredeploy.json"

name: Infrastructure

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Login to Azure
        uses: azure/login@v1
        with:
          creds: ${{ secrets.AZURE_CREDENTIALS }}

      - name: Checkout Sourcecode
        uses: actions/checkout@master

      - name: Deploy ARM Template
        uses: whiteducksoftware/azure-arm-action-js@v1
        with:
          resourceGroupName: github-action-rg
          templateLocation: .azure/infrastructure/azuredeploy.json
          parameters: |
            appServicePlanName=github-action-asp 
            webAppName=github-action-demo

And the corresponding output of the GitHub Action:

Conclusion

GitHub Actions are extensible by the community and easy to use. This is an example of how we can use an Action from the Marketplace to simplify Azure Resource Group deployments. Looking forward to seeing more Azure convenient Actions!