Deploy to Azure with lolite and GitHub Actions

What is lolite

lolite is an orchestration tool for deploy Azure Bicep templates into Azure. lolite makes it easy to re-use bicep templates across Subscriptions and Resource Groups. lolite also makes it easy to use deployment outputs as inputs for other deployments.

In this post we will look at how to deploy to Azure using GitHub actions and lolite. This is based off the lolite-sample-project

For a more general into to lolite see my post here

GitHub Project Setup

There are a few things we need to configure in the GitHub project to allow authentication into Azure.

Create Azure AD Application Registration

For authentication into Azure we will be using a Service Principal via an Azure AD App Registration. This allows us to have a specific identity and associated permissions assigned to the GitHub Project. To create an Azure AD App Registration:

  • Go to the Subscriptions service and take note of the Subscription ID for your primary subscription
  • Browse to App registrations in the Azure Active Directory service and select New registration
  • Set the name to something like GitHubActions
  • Leave the Supported account types as the default Single tenant option
  • We can ignore the Redirect URI
  • Hit Register to create the App Registration

Once you have registered the application there will be a few values to take note of from the App Registration Overview:

  • Application (client) ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  • Directory (tenant) ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

You will then need to go to Certificates & secrets section of your app registration and create a new client secret. Take note of this value also.

Configure GitHub Secrets

Once you have the required values the next step is to add them to the secret store in your GitHub project. You will need to format your credentials as a block of JSON:

{
  "clientId": "<GUID>",
  "clientSecret": "<GUID>",
  "subscriptionId": "<GUID>",
  "tenantId": "<GUID>"
}

This block of JSON will be added as a single secret: AZURE_CREDENTIALS

You will also need to add the Subscription ID as a separate credential as well

Assign Permissions to Azure Ad App Registration

Lastly you will need to assign appropriate permissions to the Azure App Registration. Do this from the Azure portal for each subscription you will be deploying into:

  • Select Subscription -> IAM -> Role Assignments
  • Add -> Add Role Assignment

Note that you will need to search specifically for the name of your App Registration as they are not shown in the list by default.

In this instance I have given Contributor access each subscription. In most cases this is what you will want to do.

Setting up the project

As with all lolite projects we need a configuration and bicep folder. If you are not familiar with this I suggest you check out the orchestrate-azure-bicep-deploys-with-lolite post.

For this instance lets say we have a small project just like the lolite-sample-project, which is structured like the following:

lolite-sample-project
├── README.md
├── bicep
│   ├── automation
│   │   └── automation_account.bicep
│   └── storage_account.bicep
├── configuration
│   ├── Sandbox
│   │   ├── rg-lolite-test-01
│   │   │   ├── dummy_storage.yaml
│   │   │   └── location.yaml
│   │   └── rg-lolite-test-02
│   │       ├── dummy_storage.yaml
│   │       └── location.yaml
│   └── lolite-test
│       ├── rg-lolite-test-01
│       │   ├── location.yaml
│       │   ├── lolite_automation_account.yaml
│       │   └── lolite_automation_storage.yaml
│       └── rg-lolite-test-02
│           ├── dummy_storage.yaml
│           └── location.yaml
├── requirements.txt
└── scripts
    └── SlackNotify.py

From this structure we can see the project is deployed across multiple subscriptions:

  • Sandbox
  • lolite-test

Deploying with a GitHub Action

Create deploy.yml in ./github/workflows that looks like the following:

name: lolite deploy-account

on:
  push:
    branches:
      - master

jobs:
  deploy:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: [3.8.5]

    steps:
    - uses: actions/checkout@v2

    - uses: azure/login@v1
      with:
        creds: $

    - name: Set up Python $
      uses: actions/setup-python@v2
      with:
        python-version: $

    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        if [ -f requirements.txt ]; then pip install -r requirements.txt; fi

    - name: Install lolite
      run: |
        pip install lolite

    - name: Deploy
      run: |
        lolite deploy-account

This workflow will run when code is pushed to the master branch. When run it will use the credentials we setup earlier to authenticate to Azure before setting up python and installing lolite. Once lolite is installed it will then run lolite deploy-account, this will deploy the entire project across all subscritpions.

Worth noting here you could have an action that runs on a push to a dev branch that rune lolite deploy-subscription <dev-subscription> along with the push to master running lolite deploy-subscription <prod-subscription>. This would give you control over promotion of new code between environments.

Thats it, your lolite project will now deploy out to Azure when you push the code updates to GitHub. This is of course a super minimal example and could be expanded on in every direction.