Deployment readiness for iOS — Trunk Based Development
TLDR: Trunk Based Development has enabled the iOS team at Monese to be always ready for deployment. It has minimised the time overhead in preparing builds for release and significantly reduced the occurrences of merge conflicts. Read on to find out how we achieved this.
Here at Monese on the iOS team we follow agile methodologies and as such are continually looking to improve tools and processes in order to maximise efficiencies and productivity. Recently it had come to the attention of the team that our branching model, although was working well on some measures, in others it was not and causing us overhead everytime we had to make a deployment to TestFlight.
The branching model I am talking about is of course the widely used and loved GitFlow. In a nutshell, Gitflow is an extension of the Feature Branch workflow where you have a master, develop and feature branches. Features are branched off of develop and merged back in when ready. When all your features are complete for a version, develop is merged back onto master where a deployment is made. Things start to get a little tricky when there is parallel development of multiple versions and your version branches effectively become your development branches.
Things we liked about GitFlow are: -
- Fine control of feature code — assisted with code reviews and pull requests, we could ensure code quality and in turn app quality
- Parallel feature development support — with multiple version branches, unidirectional flow of merging commits (version 1.0.0 -> version 1.1.0 -> master) meant that we had a consistent way of handling branches
Things we didn’t like:
- Difficult to share code — long lived feature branches meant that it was difficult to share code from an upstream branch to a downstream branch without resorting to either good old copy and paste into <insert communication tool>.
- Overhead in merging — unless your team are militant in managing the up merging process, your version branches will often encounter merge conflicts and subsequent “Merge Hell” will ensue.
- Lack of deployment readiness — since version branches are effectively develop branches, your code will only really be deployable at certain small windowed time frames.
As Monese’s service offering continues to expand, ever changing business requirements and priorities all coupled with a growing team. It was obvious that an alternative branching model would be needed.
TBD to the rescue!
Trunk Based Development or TBD is a branching model that still uses feature branches however the crucial difference is that there is no development branch. Features are merged directly back onto master or in TBD lingo, the trunk.
Benefits of TBD:
- Short lived branches — as code is merged back into the trunk and shared much earlier, it promotes reuse and decreases duplication.
- Fewer merge conflicts — since branches are merged onto the trunk much faster, the likelihood of merge conflicts are reduced and in turn productivity increased.
- Deployment readiness — since the code base is in an always releasable state, engineering can respond much better and faster to changing business needs. No more hours of resolving merge conflicts if other features are prioritised at the last minute.
- QAs only need to test the latest build — a relatively small improvement but your QA team will thank you I’m sure. As there is only one branch, there is only one version to test.
That sounds great! What do I need to do?
In order to adopt TBD there are a few things I would recommend:
- CI and CD infrastructure — TBD is based on obtaining feedback as early as possible and so these need be in place. Obvious candidates are jenkins and fastlane but there are many other alternatives.
- Separate features using feature flags — rather than controlling your features using branches, your features can be managed using feature flags, which are essentially a set of boolean values that show and hide functionality. How this is achieved is another post in itself and maybe one we may cover in future.
- Wider team buy in — TBD requires tweaks to existing workflows so it’s important to get Product and QA onboard. Even though the new process doesn’t need it we haven’t managed to completely shift away from SemVer numbering.
- Minimising Xcode build time — the shorter the build time the less wasted time from all the developer and build machines, which results in higher productivity, this goes back to the principal of early feedback.
- Small pull requests — get into the habit of splitting your dev stories into as small tasks as possible as this will help in getting code merged back into the trunk faster. This is beneficial regardless of branching model but I thought it would be worth mentioning as it’s especially pertinent for TBD.
Final thoughts
It hasn’t been so long since we adopted TBD but in keeping with the TBD thinking the early feedback has been overwhelmingly positive. In that past, Product have had strong direction into the order in which features should be released. However recently we have had multiple non time sensitive features in development and the question was posed back to us into which feature should be released next. As previously it would have been already decided by the feature branching, it was nice to reply back and say ‘it doesn’t matter, it’s up to you’.
For me, the biggest thing to adjust to was the change in mindset that comes with TBD. Rather than being afraid of committing to master/trunk, it is actively embraced and ties back to the concept of early feedback and code sharing. This has had a consequence of improving my code quality as I take the extra precaution to justify every line being committed.
More information about TBD can be found at https://trunkbaseddevelopment.com/
This article was written by Hobart Wong, iOS Team Lead @Monese. This post is part of a recurring regular series from the Product & Engineering Team @Monese.