Strava mobile app users may have noticed that earlier this year Strava’s mobile app versions started increasing rapidly. It went from
5.14.0 on March 6th to
6.0.0 on March 20th, then
7.0.0, and then a major version for each public release after that. Each version number is composed of three parts,
major.minor.patch which looks a lot like semantic versioning. We’re up from version
6.0.0 to version
14.0.0 just between mid-March and mid-July. That’s a lot of major versions.
What’s with all the major versions?
For the last couple of years, Strava has been developing a release process we call Cadence. We release a new update to both our apps every two weeks. At the beginning of those two weeks, we cut a release branch and bump the major version number of our main development branch. One side effect of releasing every other week is that we sometimes don’t have many (or any!) big user-facing changes to talk about in announcements and release notes. Sometimes we choose not to announce changes in release notes because they are A/B tested or rolled out dynamically after the actual app update. That doesn’t mean that each update isn’t a big deal.
6.0.0, the release branch name was entirely decoupled from the app’s version number. Until then we updated the minor version number with each app update and the major version based on what we felt were major milestones. Each release branch was named after the year it occurred and the order in which it was cut. For example the fifth release in 2017, version
5.14.0, was based on the branch
train/2017/5. When version
6.0.0 came around, we had just begun some more work on automating the release process and we were presented with an interesting problem: what happens when we get to the end of the year and we need to reset the branch number? We build pretty complicated software, we could figure this problem out, but it’s a little messy and probably unnecessary.
We were about to cut the the sixth release in 2017 and we had the opportunity to bump the app versions to
5.14.0. We decided to couple the release branch number with the app version number and remove the year number from the branch name entirely. Doing so made automating the process of cutting the release branches and bumping the version numbers more straightforward. We avoided the complexity of having to associate a release branch number that resets annually with a version number that only ever increases.
Coupling the branch name and app version number also made it easier to tell what release branch was tied to each public version. When you have multiple teams across engineering, marketing, and support all talking about certain versions of the application in a different way it turns out to make a pretty big difference if you can just refer to a single number.
What do these versions mean!?
In the world of semantic versioning, each update we do with a major version change would mean that each release would have changes to a public API that are incompatible with the last. Strava mobile apps don’t publish a public API in the classical sense. Our mobile apps are not a framework or an API you would consume in code, so the concepts of semantic versioning don’t quite apply (though some would argue that it should).
Although we don’t use semantic versioning to spec, we did leave the major, minor, and patch version specifiers in place. This leaves us with the flexibility to do minor and patch updates within a major version release. Historically, we haven’t had to do this very much, but having the flexibility is nice. We could simplify the versioning scheme to just allow for a minor or patch update. Maybe in the future you will see an app update with the version