Continuous integration (CI) is the process of automating and testing code every tine a developer pushes code to a source code repository. In a perfect world, this means that every time a developer changes or adds some code, the full suite of regression tests will run, including any new tests, and if they all pass, there’s a good level of confidence that no obvious new bugs have been introduced. Extreme examples of CI lead to Continuous Deployment, where CI processes can kick off further steps to promote the code through environments to get to production without any more action by a developer or release engineer.
In reality, many organizations are not equipped for this level of Continuous Deployment, and so an interim level of automation is implemented.
In this post I’ll cover a branching model that we have used to great effect at my current company, and how this ties into our CI tool to provide us fast feedback and lower development effort.
The branching model
We use a slight variation on the popular Git Flow model – why not pure Git Flow? Because of our historical use of SVN and the pain of merging that existed within it. Since then we haven’t had a need to really fold back into pure Git Flow, and the differences are generally minimal.
At its core, our model has the following branches:
- master – this is always the current state of live code. If we need to do a hotfix in a pinch, this is the branch we cut from.
- develop – this is our integration branch – individual features are merged into this branch, and this branch is used to compile code to deploy to our integration environment
- release – this is the code that is ready, to deploy to pre-production and production
- n feature branches – there can be any number of these branches, cut from the release branch that can be merged into develop and release
While we take some shortcuts with this model when doing a greenfield site build, we shift to this model close to launch, and maintain it post-launch as we continue to deliver features and fixes for our clients.
One of the great things about this model is that it allows us a large amount of flexibility to continue to deliver work to the integration environment, while still being choosy about what gets to production. Typically the feature branches are merged into develop when they are pushed to source control, but are only merged into release when we are due to do a production deploy.
TeamCity and Automated Merges
As I’ve mentioned before, TeamCity is a wonderful tool for implementing a CI pipeline – there are other commercial offerings such as Bamboo, as well as open source tools such as Jenkins, that do much of the same work, however TeamCity is the tool I’m most familiar with.
One of the nicest features of TeamCity is the ability, when using Git or Mercurial, is to attempt and automatic merge of one branch into another under certain conditions. We use this feature to merge a feature branch into our integration branch, which in turn triggers a build to deploy to the integration environment. This means that a developer is not required to manually merge in their changes, so they are able to focus more on development, and less about managing branches of code.
It is also possible to configure rules around which branches will be merged, and when. For example, we can configure TeamCity not to merge any branches if it matches the pattern /incomplete-feature/*, therefore if a developer creates a new branch called /incomplete-feature/helloworld, they can get the benefits of getting the code off of their machine, but not have to worry about it being complete enough to maintain the stability of the integration environment. If there are unit tests within the solution, it is also possible to run those as a precursor to the merge, which can be configured not to happen if some tests fail, thus maintaining the integrity of the integration branch.
Takeaways
Continuous integration is a great way to speed up the development cycle, get faster feedback on failed tests and increase overall productivity. However with Sitecore, this level of continual deployment can come with some disadvantages. Sitecore can be notoriously slow at starting up after a change to the /bin directory – and if you have an active development team, this problem can be exacerbated to the point where it is impossible for the dev or QA teams to verify anything on the integration environment.
Due to this, we have trialed two different ideologies that have had similar levels of success;
- Do not build to your integration environment after every commit, but time them for every 2 hours or so. This gives enough time for most features to be tested without the site slowing to a crawl, but also provides the developers several opportunities during the day to validate their new code
- Do builds more often to your integration environment to enable developers to validate their work, but set up a separate environment to read from the same branch of code, that deploys less often for the QA team to use. This allows developers to move faster – as they are generally doing high level “happy path” testing – but allows the QA team stability to do their more in depth testing.
We have also found that, as the release and develop branches drift further apart, more merge conflicts are likely to happen. While these conflicts are not a show stopper, they can interrupt a developers flow if they need to go back to a task to merge it manually, thus reducing productivity. The best way to prevent those merge conflicts from happening is to keep develop and release (or master) more in sync by merging and deploying to production more often. If you have embraced automated regression testing in your organization, there are few reasons to hold back on deploying changes more often – more deploys = smaller change sets, so it is easier to identify where a bug crept in, it also means faster ROI for your client on their change.


