This post provides an intro to GitHub Actions using deploying a static website to Azure Storage as an example.

GitHub Actions

GitHub Actions is a feature of GitHub to automate the CI/CD workflow of a GitHub repository. They are similar to the Build and Release Pipelines of Azure DevOps. An action can vary from steps dealing with building, testing, packaging, releasing and deploying the GitHub project. These actions are combined into workflows. The workflows are described in YAML files and are stored as part of the project in the repository. 

Please see Learn YAML in five minutes for background on YAML.


A workflow combines one or more actions to build an automated process in a repository and can be made up of one or more jobs. A defined workflow is saved to the .github/workflows folder as shown below:

A trigger is used to define a GitHub event or events that causes a workflow to execute. This could be a push or pull_request for example and is similar to a DevOps Trigger. In the YAML file this is defined with the on keyword as shown below:
on: [push, pull_request]

Please see Events that trigger workflows for more information.


A runner is a machine used to execute the defined workflow. This can be a GitHub-hosted machine or it can be self-hosted. The GitHub-hosted machines offers Linus, macOS, and Windows operating systems. An example of specifying a runner can be seen in the following YAML snipped from a workflow:
runs-on: ubuntu-latest

The supported runners and additional information are listed on the GitHub Actions Virtual Environments.


Actions can be sourced from GitHub public repositories or actions defined in the GitHub repository where the workflow is running. Actions are organized into jobs comprising one or more steps. An example of a action is shown below:
- name: 'Deploy to Azure WebApp'
  uses: azure/webapps-deploy@v2
    app-name: ${{ env.AZURE_WEBAPP_NAME }}
    publish-profile: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE }}
    package: ${{ env.AZURE_WEBAPP_PACKAGE_PATH }}

This action is used to deploy a package, which has already been built, to an Azure WebApp. The action to be run is specified in the uses statement and parameters are supplied with the with statement.

There is a large number available in the marketplace and when a new workflow is being created a set of sample actions are provided:


The GitHub Free plan offers 2,000 Action minutes/month for private repositories. This increases based on the plan, for example, Pro plan increases this to 3,000 Action minutes/month while Team increases this to 10,000 Action minutes/month. The following provides a summary of the pricing plans:


The following example uses Azure commands to publish a static website to an Azure Storage container. The container has had a static website enabled. This means that the files located in the $web container will be hosted as a website by storage. This YAML workflow will then perform the following steps:
  • Checkout the repository source to the runner
  •  Login to the Azure subscription
  • Publish the source to the $web container in an Azure Storage Account
Before we look at the YAML, we need to store the credentials for logging into Azure. In Azure Cloud Shell, the following command can be used to create a client secret that can be used to contribute to a storage account.
az ad sp create-for-rbac --name "[contributor name]" --role contributor --scopes /subscriptions/[your subscription]/resourceGroups/[ResourceGroup] --sdk-auth

When the command completes, copy the entire json response.

This will create a roll assignment on the specified resource group.

The credentials are then stored in the GitHub secrets located in the Settings tab:

The YAML is shown below: Publish static website to Azure Storage
03.on: push
06.  build_and_publish:
07.    runs-on: ubuntu-latest
09.    steps:
10.    - name: Checkout the repo
11.      uses: actions/checkout@v1
13.    - name: Login to Azure
14.      uses: Azure/login@v1
15.      with:
16.        creds: ${{ secrets.AZURE_CREDENTIALS }}
18.    - name: Publish app
19.      uses: Azure/cli@v1.0.0
20.      with:
21.        azcliversion: latest
22.        inlineScript: |
23.          az storage blob upload-batch -s $GITHUB_WORKSPACE/web -d \$web --account-name [target storage account name]

The trigger is a push which will execute the workflow whenever a file is pushed to the repo (line 3). The workflow will be run on a Linux runner (line 7). The source will be retrieved on line 11 and the credentials stored in secrets (line 16) will be used to login to the Azure environment. Publishing the source is done in the Publish app job (line 18). Notice that the target storage account is specified on line 23 as well as the sub-folder, web, is published and not the entire repository.


GitHub Actions provide a very comprehensive framework for building CI/CD workflows. This post covers some basics to get started and the GitHub documentation would be the next place to visit to get more information on this feature.