CircleCI 2.0 Workflows Simplified
At Flickswitch we use CircleCI to build, test and deploy our products. We ran over 1740 builds this year, and deployed over 200 times to production. For the price we pay for CircleCI this is great value.
When you are building that many times a day you notice things like build times. Build times with CircleCI 1 are slow. Some contributing factors are that every time a build is run all of the external dependencies are reinstalled.
In CircleCI 2.0 the ability to cache dependencies via the save_cache option in build steps was the biggest factor for pushing for the update from version 1. However one of the biggest things holding us back from moving to CircleCI 2.0 was the change to how build steps are handled. Notably the concept of workflows to chain together and filter build steps based on conditions.
We’ve spent some time on understanding the issue and in the last month decided to take the plunge. Below is a short summary of how we adapted our build process to deal with CircleCI 2.0’s workflows.
In the original CircleCI config it was simple, define a build step and some conditions:
test:
pre:
- yarn run jshint .
- flake8 .
override:
- py.test --create-db -n=2
post:
- <slack notify>deployment:
staging:
branch: master
commands:
- chmod +x staging_deploy.sh
- ./staging_deploy.sh
release:
tag: /release-v[0-9]+(\.[0-9]+)*/
owner: $REPO_OWNER
commands:
- chmod +x prod_deploy.sh
- ./prod_deploy.sh
The basic idea of our CI pipeline in version 1.0 is as follows:
A build is kicked off when ever someone creates or changes a Pull Request. This builds and runs all the tests on the codebase.
CircleCI releases to Staging whenever a Pull Request is merged into master.
CircleCI releases to Production when a release tag in Github is created.
CircleCi 2.0 workflow config
To get CircleCI 2.0 to behave in the same way as our original pipeline we had to figure out how workflows work. They are slightly more complex than the basic build steps in version 1.
workflows:
version: 2
build-test:
jobs:
- build:
filters:
branches:
ignore: master
build-deploy-staging:
jobs:
- build:
filters:
tags:
ignore: /.*/
branches:
only: master
- deploy-staging:
requires:
- build
filters:
tags:
ignore: /.*/
branches:
only: master
build-deploy-production:
jobs:
- build:
filters:
tags:
only: /release-v[0-9]+(\.[0-9]+)*/
branches:
ignore: /.*/
- deploy-production:
requires:
- build
filters:
tags:
only: /release-v[0-9]+(\.[0-9]+)*/
branches:
ignore: /.*/
The new CircleCI 2.0 build pipeline looks like this:
Build-test
Runs the build job on any branch but master.
The build job builds and runs tests on the code. It also handles dependency caching.
Deploy-staging
Is only trigged when the branch is master.
Runs the build job. If the build job is successful then runs the deploy-staging job.
Deploy-production
Is only trigged when the a tag matches the pattern release-*.*.*
The workflow runs the build job. If the build job is successful then runs the deploy-production job.
Conclusion
Our builds have sped up, shortening our feedback cycles. This is important as our test suite grows daily.
We hope this helps, look out for our other articles about speeding up build times and deploying to Kubernetes with CircleCI. In the meantime get the basic build steps and workflows here: https://github.com/Flickswitch/circle_ci