Chrome Caching in CircleCI

I’ll just come right out and say it: CircleCI is an excellent continuous integration platform, and you should probably consider using it (or at least be aware of it). CircleCI is extremely flexible, yet it works very well out of the box. You can configure it as much or as little as needed, and you get quite a bit of functionality with just a simple YAML file and a GitHub repo.

I have been using CircleCI on a recent project, and it’s been used in many other Atomic projects over the past couple of years. Here are some of the useful features I’ve found.

Caching in CircleCI

One great feature of CircleCI is its ability to cache dependencies across builds. Caching is great because it can both decrease the time it takes to run your tests and also make the tests less dependent on external sources.

For example, if your tests require a lot of external dependencies to be downloaded on every test run, then the status of your build (and therefore the status of your deployment) lies in the hands of external sources that are out of your control, which is terrifying. Any opportunity to cache external dependencies between builds is a huge win for your project!

Chrome Caching

On my current project, we use Chrome for our acceptance/browser tests. Initially, we just wanted to keep our version of Chrome up to date. But, over time, we observed that the Chrome download would sporadically fail, and therefore, the entire build would fail.

This got really annoying, so I decided to update our CircleCI config to keep the Chrome version cached. There are two parts to this solution:

  1. Add a cache directory to the CircleCI YAML file.
  2. Invoke a script to download and install the latest version of Chrome if it’s not already cached.

The first part is pretty easy–simply add a directory (you can name it anything) under the cache_directories tag nested inside dependencies. This is where we are going to install the google-chrome deb file.


dependencies:
  cache_directories:
    - "~/.google-chrome"

Next, we get to write a simple script to download and install the latest version of Chrome:


#!/bin/bash
DIRECTORY=${HOME}/$1
FILE=google-chrome.deb
FILE_PATH=$DIRECTORY/$FILE

mkdir -p $DIRECTORY

if [ ! -e $FILE_PATH ]; then
  curl -L -o $FILE https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb;
  mv $FILE $DIRECTORY
fi

sudo dpkg -i $FILE_PATH
echo "Using chrome `google-chrome --version`"

This script takes an argument specifying where you want to cache the installer deb file and checks to see if the file exists. If not, it downloads the latest stable version and moves it to your cache directory. Then it uses dpkg to install Chrome on the CircleCI container.

Finally, we can simply add a step to the pre hook under dependencies to invoke our new script:


dependencies:
  pre:
    - ${HOME}/${CIRCLE_PROJECT_REPONAME}/get-chrome.sh .google-chrome

And voila–the Chrome version is cached! This has helped us remove seconds of download time from our build, and more importantly, it has removed those sporadic test failures.