CircleCI 2.0

I have a handful of apps that I have been messing with recently to help sharpen my skills. One of the apps that I setup is the Angular Tour of Heroes Tutorial with a Material 2 reskin hosted on Firebase Hosting. All of this is setup with the unit and e2e tests with pretty decent coverage (around 90% at last check). I wanted to get this entire app setup on CircleCI so I could get some practice at setting up an app in CI. CircleCI’s documentation is really good and setting up the service with version 1 was super slick. When I heard that CircleCI was updating their CI service with beter docker support, I got kind of excited. The promise of being able to use containers in a build system yields some awesome results when it comes to getting the build executors setup (damn you Jenkins!) and speed, since the service will cache the container image. Below is the app configuration and my experience with CircleCI 2.0.

The App

The appliation follows the Angular Tour of Heroes Tutorial pretty closely. Most of the upgrades to the basic tutorial involve adding in the Material 2 library and enhancing the testing.

I have a testing background, and I really enjoy when a platform dedicates time to explain the best way to test. Unfortunately, when a platform gets big, it seems like there isn’t a real obvious way to test things. This is the case with the Angular platform. Good news is they have great documentation to help bridge this gap. A word of note though, there are a lot of blog posts out there about RC versions of Angular, but they are not totally applicable to the fully released version. Overall, the testing was fairly pleasant, even with the trial and error involved in getting everything running well.

The CircleCi 2.0 setup

First and foremost, CircleCI 2.0 is fast, really fast. It also uses a container based system, which makes swapping environments in and out super trivial. As expected, the docs are good and continually getting better. There are a couple non-obvious items with my config that I think are pretty neat.

Deploying

Deployment was a bit of a pain. Gone (for now) is the tag. I was originally deploying my app to production by having CircleCI run when it detected a new tag in Github. A workaround was required and I found a handy script using bash to deploy when the output of git log contains a tag in the commit message created by running npm version patch.

Testing

This one took a bit to figure out too. Protractor was easy to configure, all I had to do is grab the official selenium docker image, and point my protractor.conf.js file to seleniumAddress to ‘http://localhost:4444/wd/hub'. Boom, e2e tests configured!

Karma was tougher to configure, the old CircleCI build had a version of chrome that the karma test runner could plug into. The new docker container I used did not have any version of a chrome, and loading one in there (or overriding as a custom docker container) seemed like it was going to be a pain in the ass. What I did instead was use the Karma Webdriver Launcher to use the chrome container to do my testing. This was surprising easy to do, but doesn’t work outside of a docker type environment, meaning it wasn’t possible to test locally. Though I might be able to work something out with a docker-compose type setup (tbd).

Below is my full CircleCI 2.0 config, and a link to the repo is below the config.

version: 2
jobs:
  build:
    working_directory: ~/app
    docker:
      - image: node:boron
      - image: selenium/standalone-chrome:3.4.0
    steps:
      - checkout
      - restore_cache:
          key: heroes-{{ .Branch }}-{{ checksum "package.json" }}
      - run:
          name: Install Dependencies
          command: yarn
      - save_cache:
          key: heroes-{{ .Branch }}-{{ checksum "package.json" }}
          paths:
            - "./node_modules"
      - run:
          name: Run Unit Tests
          command: yarn test -- --single-run --code-coverage --browsers=chrome-ci
      - store_artifacts:
          path: ~/app/coverage
      - run:
          name: Run e2e Tests
          command: yarn run e2e -- --config config/protractor.ci.conf.js --webdriver-update false
      - store_test_results:
          path: ~/app/artifacts
      - deploy:
          name: Deploy
          command: |
            if [ "${CIRCLE_BRANCH}" == "master" ] || git log -1 --pretty=%s | grep -E "[0-9]+(.[0-9]+)+"; then

              echo "Building for Deployment"
              yarn run build

              echo "Installing firebase-tools"
              npm install -g firebase-tools
            fi

            if [ "${CIRCLE_BRANCH}" == "master" ]; then
              echo "Deploying to staging environment."
              firebase use staging
              firebase deploy --token "$FIREBASE_TOKEN"
            fi

            if git log -1 --pretty=%s | grep -E "[0-9]+(.[0-9]+)+"; then
              echo "Deploying to production environment."
              firebase use production
              firebase deploy --token "$FIREBASE_TOKEN"
            fi

Here is the repo for the app referenced in the article.


Thoughts, opinions, or tips on the setup? Feel free to send me a note via the social links.