Continuous Integration, Continuous Deployment

Emma Van Oss
Makers — Greenbook
4 min readDec 8, 2019

This week, our Greenbook project team is working on our own version of a social media platform, where users can create, edit and delete their own posts, and comment on each other’s. It’s our first ever Rails project, and what’s more, our first attempt to follow a complete development process, from testing to implementation to deployment.

Together with my pair partner Robert, I took on the ‘large’ task of setting up the project to meet one of our key requirements:

Any merge to the master branch should run the tests. Assuming these pass, the branch should automatically deploy to Heroku or AWS.

Card from the Greenbook project Trello board, showing the task ‘add CI/CD’
From the Greenbook project Trello board

For a seasoned developer this would take minutes. As first-timers we found it… a continuous learning experience. Here are some of our main takeaways.

1. Travis

We chose Travis CI as our continuous integration tool. Our main experience with Travis before this project was a set of angry emails when we tried to submit student projects with failing tests. But no longer.

  • Travis integrated beautifully with GitHub and wasn’t too difficult to set up, with a little research. We were soon at a point where a build was running every time we pushed to our chosen branch (‘travis-setup’).
# in .travis.ymllanguage: ruby

before_script:
- cp config/database.yml.travis config/datbase.yml
- psql -c 'create database travis_ci_test;' -U postgres

branches:
only:
- travis-setup

script:
- bundle exec rails db:migrate RAILS_ENV=test
- bundle exec rspec

services:
- postgresql
  • Our initial builds failed due to a bug with installing dependencies. With the help of the Travis docs we resolved this by adding the following to our .travis.yml, to make sure Travis used bundler 2.0 (rather than the default bundler 1).
# in .travis.ymlbefore_install:
- gem install bundler
  • We also told Travis to cache bundler, to avoid slowing down our builds.
# in .travis.ymlcache: bundler
  • We were already using Code Climate on our repo, and we wanted to integrate it with Travis. First we tried to encrypt our Code Climate token, inspired by this blog post, but it proved difficult. We could generate a secure token to include in .travis.yml, but repeatedly faced variations on this error:
Screenshot showing error from Code Climate API — ‘You are not authorized for this action’
From our Travis CI build report
  • After lots of head scratching, googling and failed builds, we decided we’d enough of our time & our limited build budget, so we switched to a less secure approach. Here’s what we used:
# in .travis.ymlenv:
global:
- CC_TEST_REPORTER_ID=[our Code Climate test reporter ID]

before_script:
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
- chmod +x ./cc-test-reporter
- ./cc-test-reporter before-build
after_script:
- ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
  • And this was our reward:
Screenshot showing message ‘Test report uploaded successfully to Code Climate‘
From another Travis CI build report
  • This meant that our Code Climate checks could now include coverage data from the simplecov gem that we ran with our rspec tests. Cool!
  • Finally, we updated our file to trigger builds on the master branch, and submitted our PR.

2. Heroku

We already had our Greenbook app running on Heroku, but we needed to get it to continuously deploy from the master branch (once all checks had passed), through GitHub integration.

Like other setup tasks, this was more complicated than it needed to be because we needed admin permissions on our GitHub repo to integrate with Heroku. Unfortunately, in repos in personal GitHub accounts, only the owner can have full permissions, and collaborators are always restricted.

See this page on Heroku

On the other hand, limited permissions helped us in other ways, when it came to enforcing good practice in the team…

3. GitHub

Our final task for setting up CI/CD was to limit our own potential to mess it all up. With the master branch automatically deploying to Heroku, it became essential to protect the master branch and enforce some good practice in our team workflow.

We followed this guidance from GitHub to prevent anyone from pushing directly to the master branch, or merging a PR without approval from at least one other reviewer.

No offence team.

--

--