A Continuous Integration and Deployment Setup with CircleCI and Coveralls
Continuous Integration (CI) and Continuous Deployment (CD) are crucial development practices, especially for teams. Every project is prone to error, regardless of the size. But when there is a CI/CD process set up with well-written tests, those errors are a lot easier to find and fix.
In this article, let’s go through how to check test coverage, set up a CI/CD process that uses CircleCI and Coveralls, and deploys a Vue application to Heroku. Even if that exact cocktail of tooling isn’t your cup of tea, the concepts we cover will still be helpful for whatever is included in your setup. For example, Vue can be swapped with a different JavaScript framework and the basic principles are still relevant.
Here’s a bit of terminology before we jump right in:
- Continuous integration: This is a practice where developers commit code early and often, putting the code through various test and build processes prior to merge or deployment.
- Continuous deployment: This is the practice of keeping software deployable to production at all times.
- Test Coverage: This is a measure used to describe the degree to which software is tested. A program with high coverage means a majority of the code is put through testing.
To make the most of this tutorial, you should have the following:
- CircleCI account: CircleCI is a CI/CD platform that we’ll use for automated deployment (which includes testing and building our application before deployment).
- GitHub account: We’ll store the project and its tests in a repo.
- Heroku account: Heroku is a platform used for deploying and scaling applications. We’ll use it for deployment and hosting.
- Coveralls account: Coveralls is a platform used to record and show code coverage.
- NYC: This is a package that we will use to check for code coverage.
A repo containing the example covered in this post is available on GitHub.
Let’s set things up
First, let’s install NYC in the project folder:
npm i nyc
Next, we need to edit the scripts in package.json
to check the test coverage. If we are trying to check the coverage while running unit tests, we would need to edit the test script:
"scripts": {
"test:unit": "nyc vue-cli-service test:unit",
},
This command assumes that we’re building the app with Vue, which includes a reference to cue-cli-service
. The command will need to be changed to reflect the framework used on the project.
If we are trying to check the coverage separately, we need to add another line to the scripts:
"scripts": {
"test:unit": "nyc vue-cli-service test:unit",
"coverage": "nyc npm run test:unit"
},
Now we can check the coverage by with a terminal command:
npm run coverage
Next, we’ll install Coveralls which is responsible for reporting and showing the coverage:
npm i coveralls
Now we need to add Coveralls as another script in package.json
. This script helps us save our test coverage report to Coveralls.
"scripts": {
"test:unit": "nyc vue-cli-service test:unit",
"coverage": "nyc npm run test:unit",
"coveralls": "nyc report --reporter=text-lcov | coveralls"
},
Let’s go to our Heroku dashboard and register our app there. Heroku is what we’ll use to host it.
We’ll use CircleCI to automate our CI/CD process. Proceed to the CircleCI dashboard to set up our project.
We can navigate to our projects through the Projects tab in the CircleCI sidebar, where we should see the list of our projects in our GitHub organization. Click the “Set Up Project” button. That takes us to a new page where we’re asked if we want to use an existing config. We do indeed have our own configuration, so let’s select the “Use an existing config” option.
After that, we’re taken to the selected project’s pipeline. Great! We are done connecting our repository to CircleCI. Now, let’s add our environment variables to our CircleCI project.
To add variables, we need to navigate into the project settings.
The project settings has an Environment Variables tab in the sidebar. This is where we want to store our variables.
Variables needed for this tutorial are:
- The Heroku app name:
HEROKU_APP_NAME
- Our Heroku API key:
HEROKU_API_KEY
- The Coveralls repository token:
COVERALLS_REPO_TOKEN
The Heroku API key can be found in the account section of the Heroku dashboard.
The Coveralls repository token is on the repository’s Coveralls account. First, we need to add the repo to Coveralls, which we do by selecting the GitHub repository from the list of available repositories.
Now that we’ve added the repo to Coveralls. we can get the repository token by clicking on the repo.
Integrating CircleCI
We’ve already connected Circle CI to our GitHub repository. That means CircleCI will be informed whenever a change or action occurs in the GitHub repository. What we want to do now is run through the steps to inform CircleCI of the operations we want it to run after it detects change to the repo.
In the root folder of our project locally, let’s create a folder named .circleci
and, in it, a file called config.yml
. This is where all of CircleCI’s operations will be.
Here’s the code that goes in that file:
version: 2.1
orbs:
node: circleci/node@1.1 // node orb
heroku: circleci/heroku@0.0.10 // heroku orb
coveralls: coveralls/coveralls@1.0.6 // coveralls orb
workflows:
heroku_deploy:
jobs:
- build
- heroku/deploy-via-git: # Use the pre-configured job
requires:
- build
filters:
branches:
only: master
jobs:
build:
docker:
- image: circleci/node:10.16.0
steps:
- checkout
- restore_cache:
key: dependency-cache-{{ checksum "package.json" }}
- run:
name: install-npm-dependencies
command: npm install
- save_cache:
key: dependency-cache-{{ checksum "package.json" }}
paths:
- ./node_modules
- run: # run tests
name: test
command: npm run test:unit
- run: # run code coverage report
name: code-coverage
command: npm run coveralls
- run: # run build
name: Build
command: npm run build
# - coveralls/upload
That’s a big chunk of code. Let’s break it down so we know what it’s doing.
Orbs
orbs:
node: circleci/node@1.1 // node orb
heroku: circleci/heroku@0.0.10 // heroku orb
coveralls: coveralls/coveralls@1.0.6 // coveralls orb
Orbs are open source packages used to simplify the integration of software and packages across projects. In our code, we indicate orbs we are using for the CI/CD process. We referenced the node
orb because we are making use of JavaScript. We reference heroku
because we are using a Heroku workflow for automated deployment. And, finally, we reference the coveralls
orb because we plan to send the coverage results to Coveralls.
The Heroku and Coverall orbs are external orbs. So, if we run the app through testing now, those will trigger an error. To get rid of the error, we need to navigate to the “Organization Settings” page in the CircleCI account.
Then, let’s navigate to the Security tab and allow uncertified orbs:
Workflows
workflows:
heroku_deploy:
jobs:
- build
- heroku/deploy-via-git: # Use the pre-configured job
requires:
- build
filters:
branches:
only: master
A workflow is used to define a collection of jobs and run them in order. This section of the code is responsible for the automated hosting. It tells CircleCI to build the project, then deploy. requires
signifies that the heroku/deploy-via-git
job requires the build to be complete — that means it will wait for the build to complete before deployment.
Jobs
jobs:
build:
docker:
- image: circleci/node:10.16.0
steps:
- checkout
- restore_cache:
key: dependency-cache-{{ checksum "package.json" }}
- run:
name: install-npm-dependencies
command: npm install
- save_cache:
key: dependency-cache-{{ checksum "package.json" }}
paths:
- ./node_modules
A job is a collection of steps. In this section of the code, we restore the dependencies that were installed during the previous builds through the restore_cache
job.
After that, we install the uncached dependencies, then save them so they don’t need to be re-installed during the next build.
Then we’re telling CircleCI to run the tests we wrote for the project and check the test coverage of the project. Note that caching dependencies make subsequent builds faster because we store the dependencies hence removing the need to install those dependencies during the next build.
Uploading our code coverage to coveralls
- run: # run tests
name: test
command: npm run test:unit
- run: # run code coverage report
name: code-coverage
command: npm run coveralls
# - coveralls/upload
This is where the Coveralls magic happens because it’s where we are actually running our unit tests. Remember when we added the nyc
command to the test:unit
script in our package.json
file? Thanks to that, unit tests now provide code coverage.
Unit tests also provide code coverage so we’ll those included in the coverage report. That’s why we’re calling that command here.
And last, the code runs the Coveralls script we added in package.json
. This script sends our coverage report to coveralls.
You may have noticed that the coveralls/upload
line is commented out. This was meant to be the finishing character of the process, but at the end became more of a blocker or a bug in developer terms. I commented it out as it may be another developer’s trump card.
Putting everything together
Behold our app, complete with continuous integration and deployment!
Continuous integration and deployment helps in so many cases. A common example would be when the software is in a testing stage. In this stage, there are lots of commits happening for lots of corrections. The last thing I would want to do as a developer would be to manually run tests and manually deploy my application after every minor change made. Ughhh. I hate repetition!
I don’t know about you, but CI and CD are things I’ve been aware of for some time, but I always found ways to push them aside because they either sounded too hard or time-consuming. But now that you’ve seen how relatively little setup there is and the benefits that comes with them, hopefully you feel encouraged and ready to give them a shot on a project of your own.
The post A Continuous Integration and Deployment Setup with CircleCI and Coveralls appeared first on CSS-Tricks.
You can support CSS-Tricks by being an MVP Supporter.