Gated checkin for Git: Using Branch Policies to run a build in VSTS and TFS
Let’s start with what gated checkin is, which is a feature we shipped as part of TFS 2010. Gated checkin enforces that a change in a branch builds and optionally passes tests (and anything else you want to do as part of your build) before it is checked in and available to everyone else in the branch. The gated checkin process we shipped ensures that changes are evaluated sequentially: changeset N+1 has been built after and includes changeset N. We found internally that literally processing one changeset at a time was too slow for the volume of people we have in a branch, so we introduced batching to allow M changesets at a time (with a fallback to sequential if it failed). The whole process is automated by automatically queuing a build when someone attempts to check in – the build is queued with a shelveset instead of the code being checked in. If the build completes successfully, the build checks in the changeset that the user would have checked in.
Gated checkin is really a pessimistic continuous integration (CI) build. Whereas traditional CI is optimistic and verifies a change after it is checked in, gated checkin performs validation on the change prior to it being committed to version control. Why would you want to use gated checkin? Let’s assume that every person on your team working in a branch breaks the build four times per year – just once a quarter. If you have five people on the team, the build breaks 20 times a year, which is less than every other week. If you have 50 people working in a branch, you have 200 breaks per year, which is about once per business day. Disrupting 50 people every day quickly becomes unproductive. Gated checkin is a way to enforce that a change in a branch builds and optionally passes tests (and anything else you want to do as part of your build) before it is checked in and available to everyone else in the branch.
When we added support for Git in TFS, there was no gated checkin support. Additionally, we built a brand-new build system that debuted on VSTS and shipped in TFS 2015. The new build system did not have gated checkin for either Team Foundation Version Control (TFVC) or Git. Only the old XAML-based build system supported gated checkin and only for TFVC. We’ve now added TFVC gated checkin support in TFS 2015 Update 2.
We decided to take a new approach with Git and introduced the notion of branch policies for Git as a replacement for gated checkin with Git. Branch policies allow you to set requirements for the changes that go into a branch via pull requests, including requiring builds, a minimum number of code reviewers, specific code reviewers for portions of a branch, etc. We’ve been steadily adding features to the required builds for pull requests to the point that they make a nice gated checkin solution for Git. You can look at the docs for the steps to configure branch policies, and the core is the following page. Here you can see the types of rules you can specify, including blocking the pull request from completion if the build is not successful. Since a build can include tests, static analysis, code coverage, and anything else you want, you can ensure a minimum level of quality for what gets committed.
One difference with branch policies is that there is not a sequential queue of builds the way there is for gated checkin. In practice, we have found this to be much better at scale with the whole team working in master (a few hundred people). The reason is that with gated checkin with TFVC we found that even with batching that the queue would back up at times like the end of a sprint. We don’t have that problem with branch policies because the builds are not sequential. We use a number of build machines in parallel in order to get greater throughput. The risk is that two changes are built independently that when committed and built together break the build and/or the tests. What we have found in practice is that it does not happen very often – maybe a couple of times per month. The much faster turnaround time on getting changes into master is well worth the risk tradeoff.
In summary, here are the options available for a gated checkin workflow.
- TFVC: supported by XAML-based builds and now supported in the new 2015 build system with TFS 2015 Update 2 (or newer)
- Git: branch policies using the new 2015 build system (not be available for XAML-based builds)
If you use Git and have a significant number of people working in the same branch, I encourage you to try out branch policies.
Follow me at twitter.com/tfsbuck