Implement Gated Commit Using TeamCity Automatic Merge Feature
Having a site automatically deployed from a Git branch can be convenient, but I don't feel all that comfortable comfortable deploying a commit before successfully running all the tests. Of course, this can easily be achieved by first committing to a different branch, running all the tests next and only then merging the commit to the branch, the deployment is done from. Being lazy, I don't want to do the merging manually - that's what I have my continuous integration server for. If it's already running the tests, it should do the merging, as well.
TeamCity has built-in support for gated commit build pattern in the form of pre-tested commits. Unfortunately, to make them work, you need to use a supported IDE or a command line tool. That's why I decided in favor of an alternative approach: automatic merge feature. It took some experimentation to configure it correctly, but I like how it turned out in the end. I'm writing down the steps I had to make, in case I ever want use it in another project.
For the automatic merge feature to work at all, TeamCity must monitor both the source and the destination branch. I decided to deploy from the
deploy branch and keep committing my work to
master branch. Relevant settings are parts of VCS Root configuration (you need to Show advanced features for Branch specification field to show up):
Failing to have your destination branch watched, makes TeamCity unaware of it and results in the following error:
Automatic merge failed: Cannot find destination branch to merge into: no VCS branch maps to the 'deploy' logical branch name according to the VCS root branch specification.
Since TeamCity will now start committing to your source control, you might also want to change the username it does it with. For Git, it uses the following default value:
username <username@hostname>. This can be configured with another advanced VCS root feature: Username for tags/merge.
With all that configured, it's time to add the Automatic merge build feature:
Most of the configuration is pretty straightforward:
- Watch builds in branches must contain source branch(es) filter:
+:masterin my case
- Merge into branch must contain the destination branch:
deployin my case
- You only want to Perform merge if: build is successful
- Merge policy is up to you; I decided to Always create merge commit
I had problems with the default Merge commit message: parameter references failed to resolve properly (e.g.
%teamcity.build.branch% always resolved to
<default> instead to the source branch as one would expect, and
%build.number% always resolved to
1). I can live with a fixed message, though. Git's merge tracking works good enough for my needs.