Continuous Integration with Wercker

Shane Rogers
Product Engineering

--

TLDR & Show me the code?: The public repo for the project can be found here.

Whenever I start something new, side project or not, the first day begins with setting up a staging and production environment through CI. A reliable multi-environment setup is what makes the product development and feedback cycle smooth, and keeps members of any Product Manager Club happy.

Lately I’ve been using Team wercker to do this. It has a great UI, helpful developer support, and a whole directory of automation tasks called steps which you can add into your build pipelines. I think they are great 💖.

The following will walk you through setup of CI with Wercker for an SPA hosted on Heroku. This app is based on Heroku’s example node repo which can be found here. Here’s an overview of what we will discuss:

  • Heroku setup
  • Wercker setup
  • Defining the Automation

New app on Heroku

First of all we need to create a new app on Heroku. I tend to namespace my apps by environment, so here mine is called peng-ci-staging. This app will be the target destination for Wercker.

Wercker will need to know some important Heroku app details such as:

  1. App Name
  2. API Key
  3. Username

We will get these details later on when configuring the Wercker pipelines.

New App on Wercker

Wercker has 3 main levels of instruction, where the developer gets to define how Wercker should behave at different scopes of automation.

These 3 main levels are called:

  1. Workflows
  2. Pipelines
  3. Steps
Our 3 levels of instruction 📓

First is the workflow — this is the external wrapper around the chained automation instructions we will define. A workflow can have many pipelines, and manages the triggering of an end to end automation process. It can have environment variables defined within it which are available to all of its pipelines.

The second is pipelines — these are collections of work to be done for an automation purpose (i.e build or deploy). An example is our build pipeline which will contain instructions about how to “do” the build work such as installing modules or running the tests etc. It can have environment variables defined within it which are available only to itself.

The third layer is steps. These are the instruction steps which live within a Wercker pipeline. A steps can be a simple bash script or a compiled binary that takes care of an automation task. An example is triggering npm install within the build pipeline. Steps can have environment variables passed to them.

Phew, got it? 😜 Everything makes more sense by example so lets go through the flow of setting up Wercker CI for our app.

Wercker App Creation

Login to Wercker and setup a new app here. You will have to:

  1. Choose a repository
  2. Select the owner organization
  3. Configure Access
  4. Finish up

Follow along by the example screenshots here :)

Kniterate? Whats that? 🤔

Define the workflow

Our high level goal is to trigger an app deploy after our initial application build. To do this we will create a workflow which has multiple pipelines, each with an array of step instructions.

In other words: to deploy our app to our staging environment, we will create one workflow automation which has 2 pipelines —build & deploy-staging.

The build pipeline will install our modules and run the app’s tests and deploy-staging will deploy the app.

Head over to the workflow panel to get started.

Wercker Workflow Editor

Wercker has a visual editor which you can use to construct your workflows. The idea is that you can chain ⛓ pipelines together to achieve the automation you want. In our case we will chain deploy-staging pipeline to the build pipeline to deploy our app.

The build pipeline is created by default when the Wercker app is created — and is triggered when new code is committed to the master branch on you connected git source (GitHub or BitBucket etc.)

Create the deploy pipeline

Click Add New Pipeline to create a new pipeline.

By default we only have build — we need to create deploy-staging

Give it a name of deploy-staging and set the YML pipeline name to deploy. We will be chaining this pipeline so you can leave the Hook type as Default.

if you are following along, enter the same details as they will be consistent with the example repo.

Chaining Pipelines

Woot! Now we need to say that we will trigger this pipeline after the build pipeline has passed.

How do we chain these two pipelines within the workflow?

Using the Workflow editor, click on the blue plus icon, selecting the deploy-staging pipeline to be automatically executed after the build pipeline finishes on all branches.

The result are neatly chained pipelines ⛓

If you also have a production pipeline, you may not want to automatically chain it to build. However, once you have pushed to staging, and have confirmed the new features/bug fixes etc. you can manually choose to deploy a staging branch to production through the UI. This gives product managers a lot of autonomy over what gets pushed to staging and what gets to production. ✨

Environment Variables

Great! Now we need to discuss environment variables and their scope within Wercker. Environment variables are the configuration values which will be available within the scope of either the executing workflow or pipeline.

Pipeline Env Vars

For example, when we deploy our app to Heroku we need to tell Wercker what the name of our app is on Heroku. There’s no magic inference here, we have to tell Wercker what to do and give it the info it needs. For example, in our deploy-staging pipeline we will need a pipeline env variable available called $HEROKU_APP_NAME.

The handy thing is that, when you have multiple application environments (i.e. staging and production) we can just update the environment values within Wercker and the deploy pipelines will stay the same. For example, within a deploy-prod pipeline for production, $HEROKU_APP_NAME will be have a value of peng-ci-prod instead of peng-ci-staging. The pipelines will be the same, but the targeted Heroku app will be different.

Workflow Env Vars

If we have a env variable we need to share across an entire workflow, such as a Slack webhook endpoint for deployment notifications, we can specify them in the Environment panel of the Wercker app. Env variables within here are available to the global workflow scope, as opposed to the local pipeline scoped of env vars defined within the pipelines themselves.

Create Pipeline Env Vars

Navigate to your workflows deploy-staging pipeline, and set your Heroku app name as the value for a key called HEROKU_APP_NAME.

Heroku <- — -> Wercker Communication

For successful deploys, we need to establish a secure means of communication between Wercker and Heroku. To do that we need to do two things.

  1. Create an SSH key within Wercker and add it to Heroku
  2. Get a Heroku API key and username and add them as Workflow env variables within Wercker.

SSH Key

Within your deploy-staging pipeline menu look out for the Generate SSHKeys option underneath the pipeline env variables table. Click that and create a new SSH Key called DEPLOY_KEY.

Click this!
Enter these details!
Now your menu will look like this!

Got it? Woot! 🙌.

Ok you can now see that Wercker has created both a public and private SSH key for your application. The DEPLOY_KEY_PUBLIC is the value which will be set in Heroku. Copy the DEPLOY_KEY_PUBLIC value, and head over to your Heroku application settings.

Click and CMD+C duh 🙃

Go to your Heroku account menu and scroll down to the SSH keys section. It looks like this:

Click the add button

Click that shiny Add button, and up will pop the New SSH Key menu! ✨ Now paste that Wercker SSH key in here.

Copy and past your SSH key from Wercker in here!

Good work 👍. While on this page, scroll down to the API Key section. Click on reveal, then copy your API key to the clipboard. This is the value which we will set in Wercker.

Click Reveal, then copy the API Key ✏️

Before we go back to Wercker, take a note of your Heroku user name at the top of your account (i.e. the email on your heroku account). We will need this too.

Head back to Wercker with both your:

  1. Heroku API Key
  2. Heroku email username

and navigate to the Environment tab of your application.

Head to the 🌲Environment Tab🌲

We are going to add both your Heroku API key and email in here under the key names of HEROKU_KEY and HEROKU_USER. Once these are added here, the Wercker steps we define within our deploy-pipeline will have access to them at runtime

Wercker Steps

Now we have both a Heroku app and Wercker app, with the required env variables to enable Wercker to do its job. But we still have to tell Wercker where to use these variables, and what actions to perform within each pipeline step. Thats where Wercker steps and the wercker.yml at the root of your application will come in. This configuration file will tell Wercker exactly what to do with the variables available to it.

Our wercker.yml looks like this, and lives at the root of your app directory. Let’s take a look and discuss the components.

box: node:6.9.1
build:
steps:
- npm-install
- script:
name: Run unit tests
code: |
npm run unit-test
deploy:
steps:
- heroku-deploy:
key: $HEROKU_KEY
key-name: DEPLOY_KEY
user: $HEROKU_USER
app-name: $HEROKU_APP_NAME
  • Box — this is the base Docker image used to build the pipeline from. Wercker pulls this image so that it has a node environment within which to run our app. We specify the use of node:6.9.1. All Docker containers used can be found on Docker Hub. Not on node? There will be one to fit your app use case 🌈. Our wercker.yml here is a bit node specific, but, at a high level, the process will be the same across other platforms.
  • Build & Deploy — Now we can see where our previous Wercker configuration aligns with our wercker.yml The pipelines we created called build and deploy-staging each match up with the named pipelines of build and deploy within the wercker.yml.

Each pipeline is an array of steps to be executed sequentially. These steps can be short bash commands or they can be more verbose instructions, which have keys for both name and code.

The build step takes care of module installs from npm and running the tests. Once these two actions are performed without any errors, the deploy-staging pipeline is started.

The deploy step tells Wercker to push the app to Heroku.

Once the built deploy step finishes without error your app should be live ⚡️. Any errors will be output to the Wercker console, so check in there if for debug output in case anything goes wrong.

Product Manager Autonomy

Wercker gives your team total control over your application deploy pipelines. You get fine grained control over which feature branches get pushed to staging with just the click of a button. This is super helpful within the feature testing and feedback loop. Product managers wont have to ask a developer to push a feature branch to the staging environment, they can just do it themselves from within the pipeline menu. Autonomy FTW

Green build on a branch? SHIP IT 😜

Summary

I think Wercker is great option for CI, but there are other options out there which do the job too. Wercker has a free tier that works with private repos which will let you experiment. CI makes everything better. Just. Do. It.

Show me the code

The full app for this discussion can be found here. Clone it, use it, break it and comment if you need help with anything 🙂.

Want to hear about how to configure Webpack, distributing you built assets to a CDN, or how to configure environment variables across builds in React Native? Subscribe to hear about em!

🚨Click Click Click Click Click Click Click Click 🚨

Im Shane, a web developer. Check me out here.

Or my Github 🚀

--

--