The arm-deploy GitHub Action was recently released by Microsoft ( This action supports ARM Template deployments using GitHub Actions (surprise! and yay!). I decided to spend some time playing around with this and no disappointments here! It takes surprisingly little effort to get this up and running, even if you're not that great in complying with the YAML standards like me.

The scenario

In this scenario we will deploy a SQL server and a database using an ARM Template. I used the quick start example for Azure SQL with Transparent Data Encryption enabled for databases (template can be found here).

Because Azure SQL requires an administrator password, the goal is to pass the administrator password as a parameter coming from the GitHub repository secrets. In this example we won't be using a separate parameter file. But note that using parameter files or URIs is supported.

Configuring your repository

The actions we're using require some variables that we don't want to necessarily expose to the outside world. Reason enough to store them as secrets in our repository. We need the following secrets:

  • AZURE_CREDENTIALS (for use with the Azure Login action)
  • SUBSCRIPTION_ID (for use with the ARM deploy action)
  • SQLADMINISTRATORLOGIN (to parse as a parameter to the ARM Template)
  • SQLADMINISTRATORLOGINPASSWORD (to parse as a parameter to the ARM Template)

Remember that you can only see your secret during the configuration, it's not possible to request these afterwards :) If you're unfamiliar in dealing with secrets in GitHub actions check the documentation here.

For the "SUBSCRIPTION_ID", "SQLADMINISTRATORLOGIN" and "SQLADMINISTRATORLOGINPASSWORD" you can simply input the desired value when creating the secret. For the "AZURE_CREDENTIALS" please check the documentation here if you're not sure on how to configure the service principal and retrieve the required values. Note that you your service principal requires permissions on the scope that you are deploying (the action supports the resource group, subscription and management group scope).

In the end my secrets configurations looks as follows.

One could argue to store the "SUBSCRIPTION_ID" and the "SQLADMINISTRATORLOGINPASSWORD" as environment variables in the workflow but I personally prefer to store them as secrets. Either way works :)

The workflow

The workflow itself leverages 3 actions:

  • Azure Login to login to Azure
  • Checkout to grab the contents of the repository
  • arm-deploy to deploy the ARM Template

We're going to run the workflow on every push to the repository. In production scenarios you might want to only do this for specific branches but for demo purposes the current configuration illustrates well.

name: Deploy ARM Template
on: [push]

    runs-on: ubuntu-latest
      - name: Azure Login
        uses: azure/login@v1
          creds: ${{ secrets.AZURE_CREDENTIALS }}
      - name: Checkout
        uses: actions/checkout@v2
      - name: Depoy ARM Template
        uses: azure/arm-deploy@v1
          subscriptionId: ${{ secrets.SUBSCRIPTION_ID }}
          resourceGroupName: gh-actions-arm-deployment
          template: ./azuredeploy.json
            sqlAdministratorLogin=${{ secrets.SQLADMINISTRATORLOGIN }}
            sqlAdministratorLoginPassword=${{ secrets.SQLADMINISTRATORLOGINPASSWORD }}

It's a pretty straight forward workflow leveraging all three functions. Things get interesting in the last action where we actually use the arm-deploy action.

Basically we're grabbing the Subscription ID and we'll see that the action uses that to set the subscription context (below image). We're then requesting both secrets for the SQL server configuration and pass them as parameters.

The result

The result is a SQL Server and database configured according to the parameters we we used in our deployment.

To Wrap-up. A configuration that can be set-up relatively fast and works like a charm! Hopefully there's an action for Bicep in the making! :)