NuGet Package Analysis: Encouraging Semantic Versioning
If you've been in one of my recent talks or follow my blog or Twitter ramblings, you might have noticed I'm quite a fan of adhering to the Semantic Versioning specification. I find it particularly useful as a means to communicate changes in your API towards your package consumers who in turn will be able to set proper expectations about what they'll get when updating a certain package. It also enables NuGet to be smarter about package updates (e.g. Update-Package –Safe). So in short, I don't see any reason to deviate from SemVer.
However, not everyone knows about SemVer and definitely not all of us are applying the SemVer scheme to the packages they produce. Simply take a look at the NuGet Gallery and look for a package that has a non-SemVer version, it will take you less than a page scroll to find one (e.g. a version in the MSDN format major.minor.build.revision).
There are two major impediments at the moment when it comes to SemVer and NuGet:
- Not everyone applies SemVer to their packages
- NuGet doesn't (yet) fully support the SemVer specification
Not everyone produces SemVer packages
I recently noticed this tweet from Steve Bohlen:
posited: the fact that #nuget tooling respects #semver but many pkg authors do not is a continued threat to its efficacy and success
— Steve Bohlen (@sbohlen) January 24, 2013
I agree with the statement in the sense that different versioning schemes on the same repository can cause trouble and are an impediment. The NuGet Gallery is a single public repository, currently hosting a mix of packages with different versioning schemes. It's really hard to support both SemVer and legacy schemes and come up with a generic algorithm to define version precedence! Just take a look at this discussion on GitHub (home of the SemVer spec).
Only package producers can control what type of versioning they'll use, but in my opinion it is up to the repository owner to validate packages before accepting them on the repository. That's why I built an extension that hooks into the NuGet commandline, which does have package validation logic applied during package creation. You can find it on my GitHub repository (check the readme for details): https://github.com/xavierdecoster/NuGet.PackageAnalysis. For now it will only throw warnings (this is a limitation by the current version of the NuGet CLI which treats errors as warnings), but your build log should show something similar to this when violating SemVer:
Don't be surprised to see this feature pop-up in a next version of MyGet as a feed-setting.
NuGet & SemVer are not aligned
I know this is on the roadmap and I'm sure it will get priority once the SemVer specification hits RTM (it's an RC at the moment). But until then, try to stick to SemVer as good as you can. Maybe the following table can help:
SemVer | NuGet | ||
v | x | SemVer Versioning Scheme | major.minor.patch[-prerelease][+build] |
v | v | NuGet pre-release package | major.minor.patch-prerelease |
v | v | NuGet release package | major.minor.patch |
x | v | Legacy Versioning Scheme | major.minor.build.revision |
Basically, it comes down to this:
- Avoid 3 dots in your package version
- Avoid build numbers in your package version (unless you use the leading-zeros-prerelease-suffix trick, e.g. 1.0.0-alpha0001 – as explained in my MSDN Article "Top 10 NuGet (anti-)patterns")
The NuGet Package Analysis SemanticVersionRule extension I built might help you in avoiding this trap. Good luck!
Leave a Comment