Is trunk-based development (TBD) viable for development of software where versioning, compatibility, long term support and service level agreements (SLA) play a big role for business (e.g. libraries, frameworks, drivers, SDKs)?
Some context
I'm interested in TBD in context of different types of software projects. The practice is considered valuable by many. There is some research on positive impact on speed and reliability of the software delivery - I'm thinking of DORA and DevOps Reports - but I think it's biased towards web development. The Internet is full of articles praising the practice, but it mostly from web developers with little to no case studies about other types of software.
SDK development is a different beast. Customers are often other developers. They expect that after the integration, there will be little to no effort to maintain it. This leads to conservative update policies and a long tail of software versions that are in use. Versions, that are expected to be updated with new functionality and fixes. Breaking changes are not welcome, bad abstractions can stay in codebase like this for years. It's very hard to keep releasability of the trunk while working on multiple API changes.
Is TBD viable for environment I have described? If so, what are other practices that a team should implement to reap the rewards (low integration cost, fast feedback loop, releasability) while satisfying needs of the business (stability, long term support of APIs, as little breaking changes as possible)?
2 Answers 2
Yes. In fact, the branch for release strategy is specifically designed for this case. For as long as your application, library, framework, SDK, package, etc. needs to be supported, you have a long-lived release branch that you can use for patches. You would create a release branch for each release that contains features or deprecations. In Semantic Versioning terms, major or minor releases. If any supported releases need a patch, you would have a branch to apply it. The ideal state is to cherry pick from trunk, but if the branch has deviated far enough, you may not be able to use that approach.
I don't agree with the assessment that it's "hard to keep releasability of the trunk while working on multiple API changes". There are plenty of examples of SDKs that offer "nightly" builds that are essential previews of what the next release might be. In Trunk Based Development, this would be the trunk.
The one case where this might be an issue is if you are working on changes for Version+2 or Version+3 of the SDK. In these cases, you would need to follow something more like the branch by abstraction strategy or otherwise have feature flags to keep far-future changes out. Otherwise, the change would end up in a long-lived feature branch.
In theory there is no difference, all changes are fully tested and signed off before release in any model.
However, as I have written about previously, I do think there is a difference in philosophy between TBD, which has an emphasis on releasing every small change, and other flows that aggregate sets of functionality into larger increments with more gateways to "done".
However, I don't think SDK or library development should be pigeon holed into the aggregate category as you suggest.
For example you are working on a feature and need some small, non-breaking, updates to several different libraries to make it work. Here TBD is ideal, you can quickly do several tiny point releases, pull the new versions and release your feature.
However, if you do have the limitations you describe, a strict definition of done, an intensive testing regime, or some sort of regulatory sign off etc. Then yes, TBD probably isnt the way to go, its more productive to wrap up multiple changes and send them through that process as a feature set, rather than send each one individually.