With Continuous Delivery (CD) every commit is a potential release candidate and all pushes are to a single central trunk. For people new to CD it an be very hard to reconcile frequent commits with this concept; How can I commit twice a day when this feature is going to take several days to be in a state that I want it to be public?
A good example we had of this recently was a full reworking the registration pages for the https://www.your-loop.com energy monitoring website.The registration process requires the installation of hardware to do meter readings, ensuring that radio communications are working and serial numbers etc. have to be entered and the flow can vary depending on the type of meter a user has. The rework involved changes of page flow and content. The nature of the changes meant we didn’t see a clear way to break it down into smaller sizes that made sense to the user. It was also clear this is not something that could be completed in a single commit.
Why commit to trunk?
The key things we are trying to ensure by committing frequently to trunk are;
– New automated acceptance tests are developed as we go and run on the new feature in every CI build .
– Existing acceptance tests continue to run on the existing code in every CI build.
– Ease of manual testing so the changes can be viewed (without redeployment to switch for example) .
– Continuous integration and merging into all developers work .
Feature branching – just say no.
Its common for people to revert to what they know when presented with a challenge and some of the team were immediately reverting to suggesting a feature branch. The problem with this of course is that feature branches make all of the above desired objectives difficult, expensive or simply impossible. Every time you feature branch, a release fairy dies, just say no!
Feature Toggles were not ideal.
One option discussed was to use a feature toggle. The problem with toggles is how to toggle them on and off. Feature toggles often take the form of a singleton property, perhaps in a configuration file or dependency injection that switches between different implementations at build time. The problem with this approach is test isolation, I want all my regression tests to run whether the feature is currently on or off, and this is an awkward thing to do in your CI environment unless you run tests sequentially, even then it requires duplicated toggles in test code that you must keep in synch.
There are other approaches to feature toggling that can happen at runtime which I will talk about in another post but this wouldn’t have been much help here as we needed a global new/old switch.
The approach we used is to “build alongside” by building the new registration pages with a different URL which is not linked to from the site;
So if the existing registration page entry point is;
Whilst the new feature is being developed all buttons/links etc. point to the existing registration pages entry point. We can write selenium tests that drive the new registration pages and leave all of the existing tests in place. QA and the product owner can access the new pages without any configuration (by simply going direct to the URL), but they are sufficiently hidden from the public to not get seen. In practice we called it a slightly more obscure name and there was really no risk beyond seeing a “work in progress” should a customer have guessed the URL which was unlikely.
Once all are happy with the new pages the new URL is renamed to the existing one and the old code is deleted.
It’s a simple approach that everyone understood and met all of the desired objectives regarding frequent commits, CI, manual testing and frequent merging with everyone’s code.