After a year of internal use, we’re excited to open-source our deployment tool, Shipit.
With dozens of teams pushing code multiple times a day to a variety of different targets, fast and easy deploys are key to developer productivity (and happiness) at Shopify. Along with key improvements to our infrastructure, Shipit plays a central role in making this happen.
Coordinating frequent deployments in a large development team poses a number of challenges. You need to ensure that no one else is currently deploying, that the revision you are about to deploy has been successfully tested on CI, and even that there is no ongoing maintenance operation. With smaller teams, it’s easy to give developers deployment access via something like Capistrano, but giving production credentials to many people can become a problem. Additionally, keeping an audit trail of when specific commits were deployed is indispensable when debugging production issues.
The first version of Shipit was built in early 2013 using an open source project by Rackspace called Dreadnot. It allowed our developers to deploy their code without needing to request credentials, understand the production hardware, or involve the Operations team. While this worked well initially, we hit some limitations. Configuring new projects was difficult, which meant few projects were using it. We also hit performance limitations.
During Hack Days, we undertook a complete rewrite to address these problems. Here are some of the improvements we've made:
To ensure code isn’t deployed during incidents like system maintenance, there needs to be safety mechanisms in place. Shipit allows developers to set a lock to prevent other developers from deploying when it’s unsafe to do so.
To make configuration easier, we adopted a model similar to Travis CI and introduced the notion of a
shipit.yml file. This allows deployment recipes to be maintained within each project and kept under version control. Here's the one used to ship Shipit:
We don't need to specify a deployment command - Shipit will infer the necessary steps to deploy to Pypi, Rubygems, and anything using Capistrano.
Shipit keeps logs and metadata of all the deploys and rollbacks performed.
We were able to make gains in performance and simplicity by adopting GitHub as the source of truth. Instead of constantly updating a local copy of the repository and polling for CI status, Shipit relies on GitHub's
status webhook events. This has the added benefit of playing well with the plethora of third-party services that use the Statuses API (including our Docker image builder).
Before deployments, Shipit allows you to display key metrics, or add a checklist that should be followed. We’ve also made it possible to write visualizations shown during deployments, that make it easy to monitor progress and abort the deployment if needs be.
Shipit and You
We've put together a detailed README to get you started. Please report any issues you might run into, and feel free to submit bug fixes and improvements via pull request.
At Shopify, Shipit deploys over 200 projects (including itself) at the press of a button - something we do several hundred times daily. It handles a broad set of general purpose tasks ranging from updating DNS configurations to publishing new versions of Python eggs, and deploys our applications to Heroku, EC2 and our datacenters. Over time, we've learned from it and improved it, and we’re excited to share it with the community.