Important
2024-04: I changed my mind and use proper semver now. See martinbonnin/library-guidelines
I recently had an interesting discussion about semantic versioning for Maven artifacts. While there seem to be a consensus for versions in the form of MAJOR.MINOR.PATCH
, things become more complex and interesting when pre-release are involved and multiple forms are found in the wild. For example:
3.0.0-alpha1
3.0.0-alpha01
3.0.0-alpha.1
Which one is used depends on the projects. Ultimately, I chose 3.0.0-alpha01
because this is what other popular libaries do and this will most likely be the least surprising choice for consumers.
This page is an attempt at formalizing a versioning scheme for artifacts consumed with Gradle. It's unfortunately not compatible with SemVer but there's so much muscle memory around these that changing them seems counterproductive at the time of writing. Maybe one day...
I'll use this page as a reminder when I will have lost all context in 6 months from now. Also, I'm hoping others can find it useful or amend it. Feedback is very welcome!
From smaller to bigger (using Gradle rules):
3.0.0-dev01
3.0.0-alpha01
3.0.0-beta01
3.0.0-rc01
3.0.0-SNAPSHOT
3.0.0
While the above works well with Gradle, it is incompatible with SemVer:
- Gradle has a special rule for
"dev"
where dev is always before anything else, even"alpha"
- Gradle also has a special rule for
"SNAPSHOT"
where the comparison is case-insensitive."SNAPSHOT"
will come after"alpha"
even though it shouldn't be in pure ASCII sort order.
All in all, SemVer would sort versions in the following order:
3.0.0-SNAPSHOT
3.0.0-alpha01
3.0.0-beta01
3.0.0-dev01
3.0.0-rc01
3.0.0
Note how:
- Semver doesn't have any special rule for
SNAPSHOT
ordev
- Uppercase
SNAPSHOT
will come beforealpha01
dev
will come afterbeta
Maybe not! It seems the incompatibilities are not important as long as no library transitively depends on a pre-release version. Which sounds like a relatively bad idea in the first place since pre-releases could have breaking API changes. So in most cases, I would expect the PragmaVer scheme to not break any build.
There might still be some impact for some tools. I'm thinking of tools like dependabot, ben-manes/gradle-versions-plugin or jmfayard/refreshVersions. Depending what ordering rules they use, these tools might suggest a -dev
version while an -alpha
is already released.
To some extent, the Maven Central HTML listings at https://repo1.maven.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/ are also somewhat affected because they always sort in ASCII order and don't know about numeric parts. These listings are a 3rd ordering on top of the Gradle order and the SemVer order.
In the future it would be nice to use a versioning scheme and ordering rules that works the same for all tools. I think the following would work with both Gradle and SemVer:
3.0.0-1
(developer preview only use a single numerical part so they come before everything else)3.0.0-alpha.1
(no leading zero)3.0.0-beta.1
3.0.0-rc.1
3.0.0-snapshot
(lowerspace so that it comes after the rest)3.0.0
That would not work in Maven Central HTML listings but maybe Sonatype can make it work! 🙏
Q: Why not start at 3.0.0-alpha00
?
Good question! Because no one else does I guess...
Q: What happens if you need 100 alphas or more?
Well, at this point you'll have to go beta!
- Semver: https://semver.org/
- Npm rules: https://docs.npmjs.com/cli/v6/using-npm/semver
- Gradle rules: https://docs.gradle.org/current/userguide/single_versions.html#version_ordering
PS: Many Thanks to Javier, LouisCAD, AndroidHamilton, Dariusz and Björn for the interesting discussion!