At my previous company, I’d experienced release cycles of 1 to 3 months, and release day was usually pretty stressful, especially when a big change was going in! We had various branching strategies to make sure only the code we expected to be released would go in. (Whilst in theory it should be fairly simple because no new code should be committed after taking the release cut, in practice, there was always last minute changes going in and I remember keeping these branches up to date, or merging code between master and the release branch sometimes turned into an absolute nightmare.)
My usual workflow in my Java role was this:
- Pick up a bite-sized story
- Create a branch off master to house my code for that story
- Test drive the change, committing frequently to the branch
- Once the story was complete, push to a remote branch
- Allow CI builds to run on the new code
- Once builds go green, merge code to master
- Every quarter, code in master is deployed to production
There’s an obvious cost when releasing infrequently – code that is not in production is not providing any value to our clients, and so for the time being it’s a cost that is deriving no benefit, even though it could be. If a client wants a feature added to the application, they know they have to wait at least 3 months to get it, even if it’s technically a half day job to change. It also makes prioritisation quite difficult – from a client’s point of view they don’t actually care which incremental story you pick up first because they won’t see the results until release day!
At my new company, every change is committed straight to master (mind boggling in its own way) and deployed straight to production. Initially, I couldn’t imagine how CD could even be possible – what if you commit something wrong! What happens if you make a false assumption! How can all developers have the potential to break production! Is that even safe?! Having worked in this way for a few weeks now, I feel I’m starting to work out the answers to some of these questions in my head.
The new order of events is:
- Pick up a bite-sized story
- Update your local copy of master
- Test drive the change. Each time tests go green, commit and push directly to master
- Allow CI builds to run, on master
- Once builds go green, merge code to production
We see instantly that we’ve skipped a couple of steps entirely. There are many other benefits to working in this way:
- As mentioned before, clients see results much faster
- There are fewer merge conflicts to deal with, where people have made different changes to the same code
- There’s no need to keep track of which changes should/shouldn’t be released
- Master is always in a releasable state
- It’s incredibly easy to get a change to production. Even if something did accidentally get committed, and bypassed all of the checks, as soon as the problem was noticed a fix could be developed and deployed within minutes.
Of course, in order for it to be viable, we need to completely trust the tests we have in place to do our checks for us, as this approach allows no time for manual testing. Once we are happy with our test coverage though, continuously deploying to production is easier, cheaper and removes the stress associated with releases!