Semantic Versioning Dilemma
It is not straightforward, at first glance, which semantic version number of your library you should bump when you're updating its dependencies. Is it major? Or minor? Or patch?
I've been helping to maintain the RIBs-iOS repo in my spare time lately, and there is a bit of a dilemma I'm facing with semantic versioning.
To give you a refresher, semantic versioning in software is a set of rules that dictates how software version numbers are assigned and incremented. There are 3 numbers in each semantic version: Major, Minor, Patch. This approach to versioning helps manage dependencies by having a strict set of rules on what each number means and when they can be incremented. Short version is this:
The Major version number can and should only increase when backwards-incompatible or breaking changes are made to the software
The Minor version number can and should only increase when backwards-compatible, additive new changes are made. This shouldn't contain breaking changes.
The Patch version number can and should only increase when backwards-compatible, non-breaking bug fixes are made
Simple and sweet, I've been using it for ages. All libraries in SPM, Cocoapods, or Carthage we use in iOS (or in any other software ecosystem for that matter) follow semantic versioning and have version numbers such as 1.2.5 or 2.0.0, etc., following the X.Y.Z format. The first number is the major, the second is the minor, and the last one is the patch.
Now, here's my dilemma with the library I'm maintaining: what do you do when the change you're introducing is a bump of the dependency version of the dependencies of the library itself?
Say my library A depends on library B 6.1.0 and library C 5.2.1., and now I need to have it depend on library B 7.0.0 and library C 6.0.0. I really need to bump the versions of my dependencies because I'm going to utilize new features from them in my library soon.
Should it be a patch change? No, that doesn't sound right - I'm not fixing any bugs after all!
Should it be a minor change? Nah, I'm not adding any new functionality here… at least not yet. I need those new features from my dependencies first to do so.
Should it be a major change? I don’t think so. I am not breaking any backwards compatibility here since my public API is not changing, nor is the internal behavior of my library.
Hm… a dilemma…
After thinking about it a bit, I started to analyze what the consequences would be for the consumers of my library if I bumped the version numbers of library B and C, which my own library depends on.
Well, it turns out that the users of my library are also highly likely to be using my library plus libraries B and C (which mine depends on) in their own project as well.
This means that if I bump the version number of my library’s dependencies it will have a downstream effect on the consumers of my library forcing them to also bump the version of library B and C that they depend on. This is because now the old versions of those libraries, 6.1.0 and 5.2.1 in our example, won’t be compatible with my library’s dependencies. A dependency tree is a tree after all.
So, I conclude that even though it’s seemingly not a major destructive change, the change in versions of the dependencies of my own library constitutes a major change to the consumer of my library after all because it has downstream forceful/destructive effects.
Which means I have to bump the major version number of my library!
Conclusion
This is not pretty obvious at the first glance what semantic versioning number you should be bumping in case when you update dependencies of your own library that others depend on. It was a bit of a head scratcher but as a rule of thumb - as a library maintainer you shouldn’t be destructive to your users, or at least you need to communicate it via versions. It turns out, your own dependencies are important to consider as they could be used by consumers of your library downstream as well as by your library.
Good thoughts, thank you for sharing!