merge-conflict:~/continuous-integration$

Continuous Integration

I gave a presentation on what continuous integration (CI) is to a group of apprentices during my final week working at Derivco and I was shocked by how little I actually knew about continuous integration. I think continuous integration is one of these things that most teams assume they’re practicing because they happen to be using a tool like TeamCity or Jenkins that screams about its wonderful CI features.

CI is actually much more than merely creating an automatic build with some automated tests attached, but a culture of committing small changes to the mainline everyday. Typically, ‘mainline’ with Git is the master branch, or perhaps some other branch like ‘develop’ depending on how a particular team organises its work.

A popular workflow when using Git is to work on features in separate branches and once they’re ‘good enough’ (I would love to say ‘done’) they get merged down into the mainline. The problem with this kind of workflow is that there’s only one integration point - there’s nothing ‘continuous’ about it.

I’ve been at IJYI for about a month now and one of the first things I’ve tried within the team I’m in is to move away from using feature branches so we could use CI to see what it would be like. The rest of this post shares some of my experiences working in this way so far.

Developing With CI

So, how do you develop a feature while practicing CI? Instead of features growing independently of each other in separate branches, all of the features grow together in the main branch. Commits are made at least daily to the main branch which integrates everyone’s code on the team daily. Assuming you have automated tests from your pipeline this should raise issues up very quickly; it also reduces the pain of merge conflicts significantly.

If you’re used to working in feature branches then you’ll likely see this way of working as risky because the main branch will be in a state where it has incomplete features inside of it. What if a feature isn’t finished by the end of a sprint? How could we stick to a release schedule if we need to wait for all the features to be done?

We can solve this is by using feature toggles. Instead of driving features from which branches happen to be merged in, they’re driven by configuration instead. This does add the slight overhead of having to test the feature toggle works though. Ideally, these feature toggles would be a core part of the architecture of your application to make it as easy as possible to turn a feature off and to reduce the ’noise’ of any logic that decides whether a feature should be enabled or not. Nobody wants to code the same boiler plate code for every feature toggle again and again.

Another benefit: code reviews. A code review everyday is way better than a code review at the end of a feature. Code reviews that happen too late can either be painful in terms of the number of changes required or criticisms are just written off because there isn’t enough time to fix them. Doing code reviews more often means discussion around the software design happen earlier and more often.

For the full story around CI I recommend reading Martin Fowler’s post on it.