Codeship and DeployHQ

Photo by Simon Boxus on Unsplash

In the ongoing refinement of my CI pipeline for my projects, I’ve been working on triggering automated deployments when my tests pass. A fairly standard thing to do, but not one that is supported out of the box by my current set up of using CodeShip Pro for my test suite, and DeployHQ for deployments.

To resolve this, I would need to create a new step at the end of the Codeship CI process that would be able to trigger the webhook on DeployHQ environment. This would require the following:

  1. A Webhook script to call as part of the CI process.
  2. An environment setup to support the required parameters for the webhook script.
  3. The configuration of a new step in Codeship to be triggered at the end of successful testing.

Winter Olympic Webhooks

Image by Caitlin Greer from Pixabay

Setting up a webhook in your DeployHQ project is very straightforward, but I did wrestle a little with setting up the correct format for the POST data. It turns out that it needs a single JSON object with a payload key, containing the various parameters:

{
"payload": {
"new_ref": [commit sha],
"branch": [git branch],
"email": [email address to notify of failures],
"clone_url": [git clone url],
}
}

The trick is to ensure that you can get all that data into a simple shell script that can send that over to the webhook URL. CodeShip provides detailed instructions for setting up a slack notification, which I was able to piggy back off to build out my solution. The first thing was to complete the full shell script that would trigger the webhook:

#!/bin/sh

DEPLOYHQ_WEBHOOK=${DEPLOYHQ_WEBHOOK:?'You need to configure the DEPLOYHQ_WEBHOOK in your codeship env'}
DEPLOYHQ_BRANCH=$CI_BRANCH
DEPLOYHQ_REF=$CI_COMMIT_ID
DEPLOYHQ_CLONE_URL=$(git config --get remote.origin.url)
DEPLOYHQ_EMAIL=$CI_COMMITTER_EMAIL

curl -X POST \
-H "Content-Type: application/json" \
-d '{"payload": {"new_ref": "'"${DEPLOYHQ_REF}"'",
"branch": "'"${DEPLOYHQ_BRANCH}"'",
"email": "'"${DEPLOYHQ_EMAIL}"'",
"clone_url": "'"${DEPLOYHQ_CLONE_URL}"'"}}' \
$DEPLOYHQ_WEBHOOK

The CI* environment variables are provided automatically by CodeShip, but there are two variables that have more complex dependencies:

  1. DEPLOYHQ_WEBHOOK this is a property that needs to be kept secure, as you don’t want to expose to enable people to trigger builds without your say so.
  2. DEPLOYHQ_CLONE_URL this requires the availability of git (and of course the project to be checked out).

Secret Environment

Photo by Kristina Flour on Unsplash

Codeship supports encrypted environment variables using its command line tool jet. The details of installing jet are provided here. The process for sorting this out was pretty straightforward though:

  1. Added my aes key to the root of my project as codeship.aes
  2. Created a codeship-env file in the root of my project:
DEPLOYHQ_WEBHOOK=[my ever-so secret webhook url]

3. Ran the command jet encrypt codeship-env codeship-env.encrypted.

4. Updated my .gitignore to ensure that I didn’t accidentally commit anything important:

codeship.aes
codeship-env

Docker Update

Because my webhook command was now going to need access to git, I needed to update the image to include it:

FROM php:7.2-fpm-alpine3.7
...
RUN apk update && apk upgrade && \
apk add --no-cache git

[It’s worth noting this is not exactly how I am installing it as I have a setup to loop through a whole bunch of packages when building the docker image]

The codeship-services.yml needed to be updated to include a reference to the encrypted environment variables:

app-codeship:
build: .
dockerfile: app.dockerfile.codeship
depends_on:
- postgres-codeship
encrypted_env_file: codeship-env.encrypted
environment:
- DB_HOST=postgres-codeship
cached: true

Codeship Webhook Step

I already had the following steps setup in codeship-steps.yaml:

- name: tests
type: serial
steps:
- name: db setup
service: app-codeship
command: ./ci_cmds/db_setup.sh
- name: standard tests
service: app-codeship
command: ./ci_cmds/run_tests.sh

My webhook command script was added to ./ci_cmds/ so I simply needed to add the following to the end of the steps list:

- name: deployhq notify
service: app-codeship
command: ./ci_cmds/deploy_webhook.sh

All over bar the development

Photo by Christin Hume on Unsplash

Whilst it was a little bit fiddly to sort out, the main barrier was re-familiarising myself with the Codeship setup I had, and sorting out the details of the json structure in the webhook.

Now all I have to do is actually write the application itself … rather than distracting myself by writing about it instead!