The idea of Continuous Integration (CI) stems from the principle that developers should push code more frequently to a shared repository like GitHub.

With that in place, tests can be written by the developers to verify the integrity of the code. Then a CI service can pick up the code, build it and run tests on it and notify the required personnel if issues arise.

Continuous Delivery takes this a step further and automatically deploys the code changes to testing and/or a production environment after a successful build.

In this tutorial, we’ll see how to set up continuous integration/delivery with GitHub, Travis CI, and Heroku but you can do the same for other services like AWS or Digital Ocean.

Prerequisites

For this tutorial, you’ll need:

A basic understanding on HTML, CSS, JavaScript, Node/express

A text editor

A Web browser

Travis CI account

Heroku account

GitHub account

Setup Node Server Application

We’ll be working on a simple server that responds with Hello world to any request. We’ll use a node server to build the server.

To start off, let’s initialize the project. From your terminal, run:

npm init

It would ask you a few questions that would be needed to setup the project:

Once done, you would see a package.json file in the project directory. Next, we’ll install a few packages that the application

npm install --save express npm install --save-dev jest supertest

express – for handling routes

– for handling routes jest and supertest – for running tests on our node app

Create a new file app.js in the route of your project and add the following snippet:

const express = require('express') const app = express() app.get('/', (req, res) => { res.status(200).json('Hello world') }) module.exports = app.listen(4000, () => console.log(`Running on http://localhost:4000`))

It’s a simple express server that returns Hello world when the route http://localhost:4000 is requested. Navigate to the URL in your browser and you will see the text in your browser.

For the next step, we’ll write a test to verify the integrity of our code. Generally, you will write tests before you write the code to pass the test but since this is a small application, we’ll be writing the tests after.

Create a new file tests/routes.test.js and add the following snippet:

const request = require('supertest') const app = require('../app') describe('Get route', () => { it('page should return hello world', async (done) => { const res = await request(app).get('/') expect(res.statusCode).toEqual(200) expect(res.body).toEqual('Hello world') done() }) }) afterAll(async () => { await app.close() })

It’s a simple test that checks the response status code is 200 and checks that we get the text “Hello world.” To run the test, add the following to the “scripts” section of package.json .

"test": "jest"

Also, add the following key to the object:

"jest": { "testEnvironment": "node", "coveragePathIgnorePatterns": [ "/node_modules/" ] }

In your terminal, run the tests:

yarn test // or npm run test

If the server was setup correctly, the tests should pass.

Setting up Continuous Integration

As mentioned earlier, the idea behind continuous integration is that code is pushed to a central repository frequently. Now that we have our code setup, let’s push the code to GitHub.

Create a new project on GitHub

Follow the instructions to push your code to GitHub

Once done, your code will be available on GitHub



Now that we have the code available on GitHub, we’ll connect Travis CI to our repository so it will monitor the repository and automatically test and deploy our code.

To get started with Travis CI using GitHub

Go to Travis CI website and Sign up with GitHub. Accept the authorization of Travis CI. You’ll be redirected to GitHub. Select your profile picture in the top right of your Travis Dashboard and click Settings.

Select manage repositories button which would take you to GitHub On GitHub, you can choose to either install Travis CI for all repositories (including future repositories) or only a select few. If you choose only select repositories, be sure to select the repository you created earlier before you click Approve and Install.

Add a new file travis.yml to the root directory of the project and add the following:

language: node_js node_js: - 10.13.0 install: - npm install script: - npm run test branches: only: - master

language – specifies the language of choice (Node.js)

We specify the version of node.js (you can get your version by running node -v in the terminal)

in the terminal) install – specifies commands needed to install any required packages

script – specifies scripts to be run after the installation phase

branches – indicates the branches Travis should monitor

Save, commit the changes and push to GitHub. On Travis CI, you will see a new build start:

If the script fails, the color becomes red to indicate a failure. Else, it lights up green like this:

Continuous Delivery with Heroku

At the moment, we’ve set up continuous integration with GitHub and Travis CI but it still requires human interaction to deploy to a production server. We can automate this step with Travis CI or better still, we can tell Travis to deploy to different environments (staging, test, production, etc) depending on the branch pushed to GitHub.

Most teams work with at least 2 branches: master and dev/develop. master branch is reserved for the well-reviewed and tested code while dev branch contains code for the next version of the project. Developers create feature branches from the dev branch and create pull requests to the dev branch when they are done.

For this demo, we’ll have two environments: staging and production. staging is where we’ll deploy code while testing and production will be the final approved version will be deployed. We’ll also have 2 branches: master and dev.

dev -> staging

master -> production

Our dev branch would deploy to the staging environment and the master deploys to the production environment. Let’s create an account on Heroku.

To get started with Heroku

Create an account on Heroku From the dashboard, create a new app:

We’ll create two apps: one for staging and one for production (take note of the app names)

For this demo, we’ll use:

node-hello-world99 for production

node-hello-world-staging for staging



For the next step, you’ll need two things:

Download and install both CLI. Once installed, login on both services.

// for heroku heroku login // for travis travis login --pro

Then create dev branch from the master branch

git checkout -b dev

Update .travis.yml like so:

language: node_js node_js: - 10.13.0 install: - npm install script: - npm run test branches: only: - master - dev deploy: provider: heroku api_key: secure: ADD_API_KEY_HERE app: master: node-hello-world99 dev: node-hello-world-staging

There are new steps we’ve added to .travis.yml . We’ve added a new branch (dev) for Travis CI to track. We’ve also included a new step to our build: deploy. This is where we add instructions for deployment. We specify our provider (heroku), api_key (we’ll get to this in a moment), and our app. The app is where we specify the app name and branch to deploy. So the master branch is deployed to node-hello-world99 and dev is deployed to node-hello-world-staging.

To get your API key, run this command from the terminal inside your project directory:

travis encrypt $(heroku auth:token) –add deploy.api_key –pro

It will automatically generate an API key and automatically add the key to api_key.secure. Now, you can commit your code and push to GitHub. On Travis CI, a new build will start but this time a deploy step is included which will push the application to Heroku. At the end of it, you would get a link which can be used to view the app.

Or from your Heroku dashboard, you can select the app and click “open app.”

Since we just pushed the dev branch, it gets deployed to the staging environment. Once you are happy with the project and it’s passed all reviews, it can then be merged to the master branch which will automatically deploy it to the production environment. With this set up in place, you can keep working and deploying to a staging environment without disrupting your production environment.

Conclusion

To recap, we’ve looked at Continuous Integration and Delivery (CI/CD). We’ve looked at Travis CI and Heroku and how both platforms can be used to automate builds, tests, and deploys.

There are other use cases for these two beyond the scope of this tutorial. Hopefully, this tutorial is a good introduction to the concept of CI/CD which you can build on.