CI/CD

Implementing continuous deployment on Divio with GitHub Actions

Mebrahtu Zemui TesfazghiMebrahtu Zemui Tesfazghi
24. February, 2021

How to set up a continuous deployment service on a Divio project, using the Divio API and GitHub Actions.

Continuous deployment is a process of automatic deployment of any code that is deemed ready for production having passed its testing stage. It is generally triggered by an event such as a merge or commit.

Continuous deployment is valuable for a developer - it helps you focus on writing your code, without having to be distracted by the process of deployment. It's especially useful when you’re making frequent small fixes.

In this article, we will:

  • create a GitHub repository for a Divio project
  • create a Divio project connected to the GitHub repository
  • use the Divio API to obtain project-related data and perform deployments
  • configure GitHub Actions workflow for continuous deployment

Prerequisites

This article assumes the user is familiar with Git, GitHub and the basics of the Divio platform. You'll need to have a GitHub account configured with an SSH key, and have a Divio account.

Create a GitHub repository

Start by creating a new repository on GitHub. This will hold the codebase of the Divio project and is where we will configure the GitHub Actions continuous deployment workflow. The Divio Control Panel has two strict conditions for this repository:

  • it must have a branch called master
  • the branch should contain only a README.md file

If the new repository on GitHub does not have a branch called master, create one now. This new repository can be adapted to any real project later on.

Create a Divio project

In the Divio Control Panel, create a new project, selecting your GitHub repository rather than the default Divio Git server.

You can use continuous deployment with any stack, but for convenience and to keep things simple for now, we’ll use one of our pre-built project types, Django with Aldryn Python.

  • on the Divio Control Panel create a New Project, selecting Aldryn Python and Django as options
  • select Custom for your Git Repository, and provide your GitHub repository's SSH URL for the Repository URL field
  • Add the Divio Public Key provided to the GitHub repository, at Settings > Deploy keys > Add deploy key. You need to ensure that you select Allow write access
  • back on Divio control panel, hit Continue

When you hit Continue, the Divio control panel checks if the repository has a master branch with a README.md file, that it can write to.

Continue by subscribing to a free developer plan for your Divio project. Once the project has been set up, we should set up a webhook for it.

Set up a webhook

A webhook allows GitHub to send a signal to the Divio Control Panel when commits land on a particular branch.

In your Divio project's Repository view, go to Webhook and choose GitHub

Copy the Webhook URL and the Webhook shared secret - these will need to be added to the GitHub repository.

In your GitHub repository, go to the repository's Settings > Webhooks > Add webhook, and:

  • Add the Webhook URL to the Payload URL field
  • Leave the Content type field as is
  • Add the Webhook shared secret to the Secret field
  • Select Just the Push event and hit Add webhook.

The GitHub repository is now properly configured to communicate with the Divio Control Panel.

Collect the necessary information from the project

In this step, we will gather some data related to the Divio project, so that GitHub Actions can use the Divio API to communicate with it.

The Divio API is a powerful tool for interacting with your projects. We'll be using the API manually to obtain some values we need. Then, we'll configure a GitHub Action to interact with the project automatically.

First, you'll need your Divio Access Token. It can be obtained from your account settings on the Divio Control Panel. The other thing you need is your project's slug, which you can get from the Control Panel.

We need to export both of these as local environment variables, for example:

export API_TOKEN=F2EloH1wccbzdxZbZLssQOOW9F2EloGl9Mmw3Ep35U8kyDTZuZTgumxD5bWfK
export PROJECT_SLUG=cd-test

Now we can query the API to get the application UUID:

curl https://api.divio.com/apps/v3/applications/\?slug\=$PROJECT_SLUG -H "Authorization: Token $API_TOKEN"

This will return a JSON dictionary of values, listing the applications that match the slug. It should include your application; look for its UUID, as in the example below (formatted and truncated for readability).

{
    "count": 1,
    "next": null,
    "previous": null,
    "results": [{
        "uuid": "lqt3nqf6ufblletko36vgwmmti",
        "slug": "cd-test",
        [...]
    }]
}

In this case, we need to export that value too, for example:

export APPLICATION_UUID=lqt3nqf6ufblletko36vgwmmti

Using the APPLICATION_UUID, we can get all the environments that belong to it:

curl https://api.divio.com/apps/v3/environments/\?application\=$APPLICATION_UUID -H "Authorization: Token $API_TOKEN"

Once again we get back a JSON dictionary, listing the two environments and their UUIDS:

{
    "count": 2,
    "next": null,
    "previous": null,
    "results": [{
        "uuid": "fwwk5i3acnao5mfq6263ennkfe",
        "application": "lqt3nqf6ufblletko36vgwmmti",
        "app_name": "cdtest-test-58284ca388d44510b3399ec2e672990f",
        "slug": "test",
        [...]
    }, {
        "uuid": "baln7mifvnci3eaoddqwihz7jm",
        "application": "lqt3nqf6ufblletko36vgwmmti",
        "app_name": "cdtest-live-b35e467f5ec24ced94d2d5c3d82a6a18",
        "slug": "live",
        [...]
    }]
}

Configure the workflow

Now that we have the environment UUIDs, we can use all these details to configure the workflow.

Set the secret credentials

Note: the Divio Access Token is a key to your whole account. It should never be exposed in your code or saved in a file. GitHub offers a secure way of storing credentials in the repository settings.

It's also good practice to store the other details, such as environment UUIDs, as repository secrets.

In the GitHub repository, find Settings > Secrets > New repository secrets.

Add the three values you obtained above:

  • API_TOKEN (the Divio access token)
  • TEST_ENVIRONMENT_UUID
  • LIVE_ENVIRONMENT_UUID

Create the workflow

In the GitHub project, select Actions > Set up a workflow yourself.

Configure the YAML file

GitHub will provide a default set of instructions in the file, but we can delete them and create our own. We'll name this file develop.yml, and use it to deploy the Test environment when commits land on the develop branch.

First, we give the workflow a name.

name: develop branch, Test environment deployment

Next, we read the environment variables that we set in the repository secrets:

env:
  API_TOKEN: ${{ secrets.API_TOKEN }}
  TEST_ENVIRONMENT_UUID:  ${{ secrets.TEST_ENVIRONMENT_UUID }}

Now we specify the condition that triggers the workflow - a push event to the develop branch.

on:
 push:
  branches: [ develop ]

Then, we define a job called deploy. It runs on an Ubuntu image and performs the specified steps:

jobs:
 deploy:
  runs-on: ubuntu-latest
  steps:
  - uses: actions/checkout@v2
  - name: Deploy
    run: |
     curl -X POST --data "environment=$TEST_ENVIRONMENT_UUID" --header Authorization: Token $API_TOKEN" https://api.divio.com/apps/v3/deployments/

The first step above checks out the repository/branch.

We give it a name - Deploy so we can track it more easily in the logs.

Finally, the run action is a curl command that once again uses the Divio API, this time to issue a POST request that actually triggers a deployment on Divio.

Note that YAML files are sensitive to indentation. In case you run into any problems, the complete develop.yml file should look like this:

name: Develop branch, Test environment deployment
env:
  API_TOKEN: ${{ secrets.API_TOKEN }}
  TEST_ENVIRONMENT_UUID: ${{ secrets.TEST_ENVIRONMENT_UUID }}
on:
 push:
  branches: [ develop ]

jobs:
 deploy:
  runs-on: ubuntu-latest
  steps:
  - uses: actions/checkout@v2
  - name: Deploy
    run: |
     curl -X POST --data "environment=$TEST_ENVIRONMENT_UUID" --header "Authorization: Token $API_TOKEN" https://api.divio.com/apps/v3/deployments/

Commit the file.

Create the develop branch

Now we have a workflow that will trigger a deployment on the Divio Test environment when there's a push event to the develop branch. Let's make sure that branch actually exists in the repository.

If you haven't already done so, clone the repository to your own computer (or do a git pull to bring it all up to date). Create a new develop branch:

git branch develop

When you push this branch to GitHub, it will trigger the workflow:

git push origin develop

You can monitor it on GitHub: switch to the develop branch there, and check its status.

Configure the Test environment to use develop

Your Divio project might not yet be configured to use the develop branch on the Test environment. Check this in the Control Panel, and adjust it if necessary.

renaming branch

Now all the parts of the workflow are complete, from Git to your Divio project.

Make a new commit to the develop branch and push it; you should see the workflow triggered on GitHub, and in turn, the deployment triggered on Divio.

Congratulations, that completes our simple CD workflow. If it doesn't work as expected, check the logs and review your steps above.

Set up the Live deployment workflow

So far, we have set up a workflow that uses the develop branch to trigger a Test deployment. We can do the same for any branch and environment. Let's go on to set up continuous deployment on Live, this time based on the master branch.

Create a new YAML file master.yml in the repository. It will be similar to the develop.yml so you can copy and paste from that, but you need to make some changes, as indicated:

name: master branch, Live environment deployment
[...]
  LIVE_ENVIRONMENT_UUID: ${{ secrets.LIVE_ENVIRONMENT_UUID }}
[...]
  branches: [ master ]
[...]
     curl -X POST --data "environment=$LIVE_ENVIRONMENT_UUID" --header "Authorization: Token $API_TOKEN" https://api.divio.com/apps/v3/deployments/

Commit the file to the master branch, and push.

Now, every commit to the master branch on GitHub will trigger the GitHub action, which in turn will trigger the deployment of the Live environment on Divio.

Summary

In this article, we worked through the complete process to create a continuous deployment service using the Divio API, configuring it with GitHub Actions.

It's a straightforward step-by-step process, that's fundamentally the same in a simple example like this one and in a real-world production application. In each case: your Divio project needs to be connected to a GitHub repository, and the repository needs a GitHub action workflow. The general configuration is contained in a YAML file, while secret configuration details are saved as environment variables.

For a developer, it's a valuable skill to have in the toolbox.

Taking it further

In this example, we kept things simple: In this GitHub Actions workflow, a commit triggers a deployment, and it succeeds regardless of the status of the deployment.

In the real world, the GitHub Actions workflow should fail if the deployment fails. More so, we'd use automated testing as part of the CI/CD workflow. For example, a commit would land on GitHub, and then the next step would be to run the application's test suite automatically. Only a passing build would then be allowed to trigger a deployment, eliminating not just manual operations but also a layer of risk from the deployment process.

This is a part of our CI/CD process. Watch out for upcoming articles.

For further reading refer to How to use the Divio API and GitHub Actions Documentation.


Back to overview

Recent posts