Github Actions: deploy to multiple environments from single workflow

Reading time: 2 min

Last updated

_,.-'~'-.,__,.-'~'-.,__,.-'~'-.,__,.-'~'-.,__,.-'~'-.,_

Github Actions is awesome and you can automate so much with it. One lacking feature though is support for code reuse in workflow yaml files.

One particular use case where it would be useful is continuous deployment workflow that publishes latest code to the remote system. Deployment target is dictated by the git branch that receives the update.

E.g. pushes to dev branch should deploy to the staging environment and pushes to master should publish the code to prod.

Here's a workaround to deploy to multiple environments from a single workflow yaml file.

Example workflow file #

As an example, I'll take a Github Action that deploys an Azure Function app.

In order to publish code to Azure, it expects 2 variables: function app name and publish profile (deployment key).

Each environment has its own publish profile defined in an individual Github Repository Secret.

github repository secrets

Below is the relevant parts of the workflow yaml. You can see it in full here.

First, we want to trigger the workflow only on branches that should be deployed on commit:

on:
push:
branches:
- dev
- master

Next, in the very beginning of the workflow definition, we add conditional steps to set correct environment variables, depending on the current branch:

  • Function app name
  • Publish profile secret name
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Set env vars (dev)
if: endsWith(github.ref, '/dev')
run: |
echo "AZURE_FUNCTIONAPP_NAME=azfunccdgh-dev-function-app" >> $GITHUB_ENV
echo "PUBLISH_PROFILE_VAR_NAME=AZURE_FUNCTIONAPP_PUBLISH_PROFILE_DEV" >> $GITHUB_ENV

- name: Set env vars (prod)
if: endsWith(github.ref, '/master')
run: |
echo "AZURE_FUNCTIONAPP_NAME=azfunccdgh-prod-function-app" >> $GITHUB_ENV
echo "PUBLISH_PROFILE_VAR_NAME=AZURE_FUNCTIONAPP_PUBLISH_PROFILE_PROD" >> $GITHUB_ENV

Following would be the steps that are shared between environments. These are not relevant to the multi-env deployment and are not listed here. In my case it's checking out the code, caching, installing dependencies and building the project.

Finally, the deployment step uses the environment variables set above to publish the code to the correct target environment.


- name: Run Azure Functions action
uses: Azure/functions-action@v1
id: fa
with:
app-name: ${{ env.AZURE_FUNCTIONAPP_NAME }}
package: ${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }}
publish-profile: ${{ secrets[env.PUBLISH_PROFILE_VAR_NAME] }}
respect-funcignore: true

References #

... #

Still, this is a hack I'm not very happy about but I feel like it's better than having copies of the entire workflow file per environment.

If you know a better way to deploy to multiple environments from Github Actions, let me know!

If you like this type of content you can follow me on Twitter for the latest updates.

_,.-'~'-.,__,.-'~'-.,__,.-'~'-.,__,.-'~'-.,__,.-'~'-.,_

Next: Publish Azure Functions code with Terraform

Previous: How to make a copy of AWS IAM role