- GitHub
- GitHub Actions
When you set up your continuous integration and continious delivery you always have multiples environments to target. For instance:
Your application will be deployed in each environment with the same scripts. The only thing that change are the workflows
parameters. So you will probably end up with duplication. So how to mutualize your actions to save some time?
You have a web application that you build and then deploy to each environment. Your GitHub workflow
located at .github/workflows/main.yml
will look like this:
First, you build the project and package it to produce an artifact:
name: Reusable templates
on:
push:
branches: [main]
jobs:
build_and_package:
steps:
- name: checkout branch
uses: actions/checkout@v2
- run: echo Your build commands here
shell: bash
- run: echo Then your package commands here
shell: bash
Next, you put all the jobs to deploy your application after:
deploy_dev:
runs-on: ubuntu-latest
name: Deploy to dev
needs: build_and_package
steps:
- name: Checkout the code
uses: actions/checkout@v2
- run: |
echo Run on env : Dev
shell: bash
# Other steps here...
- run: |
echo Add your actions to deploy to the correct environment using ${{ secrets.DEV_DEPLOYMENT_TOKEN }}
shell: bash
deploy_staging:
runs-on: ubuntu-latest
name: Deploy to staging
needs: deploy_staging
steps:
- name: Checkout the code
uses: actions/checkout@v2
- run: |
echo Run on env : Staging
shell: bash
# Other steps here...
- run: |
echo Add your actions to deploy to the correct environment using ${{ secrets.STAGING_DEPLOYMENT_TOKEN }}
shell: bash
# Same process for production, eluded for clarity
As you can see, we copy paste the job and replace the secrets to match the specific environment. How can we improve this?
To avoid duplication of the deployment jobs we can use the GitHub Action concept called composite
. The idea is that you can create generic part of your workflow
so that you can save time and thus avoid errors.
So let’s create one for the deployment section. In our workflows
let’s create a folder called templates
and inside it another one called deploy_to_cloud
. Then inside this last folder let’s add a file called action.yml
.
The name of the file is important if you don’t specify it like this your
composite
will not be found. That’s why it’s important to put this file in a folder with an explicite name.
So you will have this file tree:
|- .github
|- workflows
|- templates
|- deploy_to_cloud
|- action.yml
|- main.yml
Here is our action.yml
file:
name: "Deploy to the cloud"
description: "Reusable actions to deploy to the cloud"
inputs:
name:
description: 'Name'
required: true
deployment-token:
description: 'Deployment token'
required: true
runs:
using: "composite"
steps:
- run: |
echo Run on env : ${{ inputs.name }}
shell: bash
# Other steps here...
- run: |
echo Add your actions to deploy to the correct environment using ${{ inputs.deployment-token }}
shell: bash
As you can see we have two inputs
variables, one for the name of the environment and one for a deployment token. Then we define this file as a composite
before defining the different steps. Finally, we put the exact same actions but we use the inputs variables so it is totally generic.
Now, it’s time to apply the composite
to the workflow!
deploy_dev:
runs-on: ubuntu-latest
name: Deploy to staging
needs: build_and_package
steps:
- name: Checkout the code
uses: actions/checkout@v2
- name: Deploy to cloud
uses: ./.github/workflows/templates/deploy_to_cloud
with:
name: 'Dev'
deployment-token: ${{ secrets.DEV_DEPLOYMENT_TOKEN }}
deploy_staging:
runs-on: ubuntu-latest
name: Deploy to staging
needs: deploy_dev
steps:
- name: Checkout the code
uses: actions/checkout@v2
- name: Deploy to cloud
uses: ./.github/workflows/templates/deploy_to_cloud
with:
name: 'Staging'
deployment-token: ${{ secrets.STAGING_DEPLOYMENT_TOKEN }}
# Same process for production, eluded for clarity
As you can see above, the first important step we do is actions/checkout@v2
to be able to access this composite
and then we can use it directly with the specific environment values as parameters.
With this technique you can now capitalize on your project and start creating your own bank of templates for all your projects. To see more, checkout my previous tutorial about it.
Happy coding !