> In Semantic Versioning, there is no way to release or communicate a LTS/"long term support" version of a package. In Pragmatic Versioning, this is solved with a BIGRELEASE version, which has meaning that can be controlled by the package author.
That doesn't make sense to me.
With semantic versioning the way you communicate a LTS version of a package is you declare that in your documentation. Django (which doesn't fully use SemVer, but is still a good example here) does that on this page: https://www.djangoproject.com/download/#supported-versions
"In Pragmatic Versioning, this is solved with a BIGRELEASE version, which has meaning that can be controlled by the package author" - that doesn't appear to address the need for LTS communication at all. It feels like the situation is exactly the same as SemVer: if you want to do LTS you have to represent that outside of the version number.
At first I was confused because of how similar this sounds to semver, but it's really just changing the granularity from (major, minor, patch) to (release, major, minor), where "major" versions break compatibility in both schemes.
(release, major, minor) is honestly how versions often get used in the wild. Especially in CD contexts where every change is versioned and deployed and the meaning between patch and minor gets a little lost.
At Bond we’ve used pragmatic versioning with the names:
vMAJOR.MINOR.PATCH[.TWEAK]
Indeed the TWEAK is only for hotfixes, though due to pushback from other devs using semver parsers, we've had to hold back on the tweaks. (Though it’s awkward in a hot fix situation.)
“There’s no way to…” is maybe imprecise phrasing but this is a real problem.
Marketing departments really want to use that first number for Big Important Releases and only Big Important Releases.
I have seen products get their version incremented from 2.x.x 3.0.0 to indicate that an entirely different product (that could be deployed alongside the first but was otherwise unrelated) was being launched.
So just tack on a number - marketing.breaking.feature.patch - or market on the feature number (Solaris 11 uname will happily tell you its real version is 5.11)
I've also seen too much of marketing is watching the project iterate too closely, it's a Ship of Theseus, and they never know when to declare a "Big Release" anyway. In six months all of the planks are different, but it happened so slowly for marketing they still think it is the same ship. Projects just get stuck in 1.x marketing version because marketing has no idea where major releases should go. They want always up to date SaaS but then are confused they can't market it like the big Waterfall adventures of yesterday.
At least with semver they might be forced to say something. I've done that a few times where the marketing version number displayed in the app is effectively just 1.{semver major}.{semver minor} and "just tell us when you want to bump that 1 to a 2 or something" getting the response "well, it hasn't really changed all that much from 1.0, has it?" and then pulling out the receipts of something like 30+ semver breaking differences in X months.
I am not sure we are talking about the same project. However, the one I am thinking of had a interesting challenge where a security issue required making the default configuration requiring a allow-list for a certain long-existing feature. This ended up going out in a patch, even though it's a breaking change. I am still uncertain what the ideal solution would have been. Following SemVer 100% would required this to be a major. However, all supported versions needed this change. Forcing users from really old majors and minors to jump to a new major with all kinds of new stuff is less than ideal. The alternative would have been to ship multiple new majors that are really just upgrades to the old minor that they are patching. WHile technically correct, also crazy.
That doesn't sound like an issue with semver (or pragmatic). There is no versioning convention that will prevent people from being people. A rigid, automated (magical) versioning _system_ might do that, but not a convention/standard.
I find semver extremely helpful, both as an author and consumer. It may make me think a little for some packages about where I want to pin things, but at least it makes the mechanics of pinning them sensible.
Server is very helpful in many contexts, especially libraries and packages, and that don’t have associated commercial support obligation.
It has real drawbacks for on-premise software with commercial support obligations, and shouldn’t be used automatically just because it works well for libraries.
>That doesn't make sense to me. With semantic versioning the way you communicate a LTS version of a package is you declare that in your documentation
So, TFA's statement that "In Semantic Versioning, there is no way to release or communicate a LTS/"long term support" version of a package" does make sense to you after all.
You can't do it in the versioning, you need to do it in the docuementation.
What didn't make sense to me is that it says "there's no way to indicate LTS in SemVer" (which I agree with)... and then fails to make the case that this new versioning system solves that problem.
Yea I think more specificity is needed, SemVer is an actual spec with well-defined terms and this is more of an early concept. The tricky thing to maneuver is many package authors will not want to commit to an LTS, so what do you do? In pragmatic versioning, there's an available mechanism in the versioning scheme available to package authors, but not a guarantee to package consumers.
> SemVer is an actual spec with well-defined terms [...]
I dissent, it is a pseudo-specification that looks like a proper specification but isn't. Many proper specification starts with a glossary because you can't get everyone to agree on common words that don't need a definition. Let me give some examples.
• SemVer never defines what the "increment" means---is an increment by more than one allowed or not? Can one release a minor version of given major version (say, 1.2.0) when a higher major version (say, 2.0.0) has been already released? If it's allowed, how should later versions (say, 2.1.0) be related to aforementioned versions?
• SemVer says the "contents" of once released version must not be modified, but unlike "API" which is a variable at the software's choice, it is never mentioned elsewhere---does the contents include a documentation or not, say?
• SemVer explains how to compare pre-release and build identifiers separated by dots, by dividing them into "identifiers consisting of only digits" and "identifiers with letters or hyphens". And then it mentions "numeric identifiers" and "non-numeric identifiers"---which one is which? The former should be numeric, okay, but the latter may still contain digits so is it "non-numeric" after all?
Agreed - and just to drive home a point you touched on: the foundation of SemVer is an arbitrarily defined 'public API'.
Imagine a project which consists of a library, a CLI tool, and perhaps a GUI.
* Is the library API part of the public API? That's for you to decide according to SemVer.
* Is removing/renaming a CLI flag a breaking change? Also for you to decide.
* Is removing major functionality from the GUI a breaking change?
..you get the picture. Every project defines 'their public API' for themselves.
This isn't a made-up example, many projects have a library and a CLI, with one considered to be 'the main project' while the other is something most people are not expected to use.
Heck, even following SemVer to the exact letter often doesn't communicate information how people expect. For example, say your library exposes a piece of metadata from the underlying OS: a function returning a `string`. But in Windows 10 -> Windows 11, they changed the API to return an `[]string` instead of a single `string`. If you want your software to run on Windows 11, you have no choice but to change your public API in a breaking, non-backwards-compatible way.
Cool, no problem, according to SemVer we bump our public API version from v1.0 to v2.0 now, right? But wait! 99% of our users do not even make use of this one-off weird function! In fact, we think we could remove it without anyone complaining but it's technically part of our public API..
SemVer has no way to express 'we had to make a breaking change that doesn't affect 99% of users', it just has a way to express 'breaking change'. If you follow SemVer, then that means your project needs to go from v1.0 -> v2.0 in that case, yes - and now you get to explain to your users why v1.0 -> v2.0 is not, in fact, a 'major change' despite it being defined as such semantically.
What most people think of as SemVer, in practice, is often _romantic versioning_ or _sentimental versioning_ and not _semantic versioning_.
Don't expect too much from version numbering schemes; they can follow sufficiently objective conventions (breaking changes for typical usage or not, worth announcing according to the authors or not) but not convey complex information.
There is no way to tell which ones in a set of equally major versions are LTS or not using version numbers because there are often too many; for example Java has major version numbers for major language features and standard library additions and removals, with reasonably relevant versions currently spanning from 8 (1.8 in the old numbering) to 21, three or four of them LTS and the others transitional.
There is also no way to tell obsolete LTS versions from current ones using version numbers, without explicit documentation committing to dates or making EOL announcement.
This is a great critique, and something important to address if "pragmatic versioning" actually becomes a thing. I think one solution is to have "LTS Pragmatic Versioning" as a subtype e.g. LTS.ANNOUNCE.INCREMENT could be "LTS Pragmatic Versioning", if you're not committing to LTS you can just use the more vague base "Pragmatic Versioning" until/unless you're willing to commit to more as a package author. The main tension here is some package authors will want to indicate LTS, and others won't (I might only commit to LTS for 10-20% of my packages, since every change needs a tiny bit of extra evaluation)
Package A is SemVer 1.2.3, package B is PragVer 1.2.3. both A and B have big release with breaking changes and marketing hype, so now they're both at 2.0.0. It is later found that in version 1 of both packages there is a bug requiring a breaking change in order to fix. B (pragmatic) can apply the fix to version 1 branch and release it as 1.3.0. How does A (semantic) make a breaking change on version 1 and version it correctly?
TL;DR Pragmatic Versioning enables breaking changes on LTS versions.
Not all breaking changes require consumers to make changes. For example, in react-router v6, the useSearchParams hook returns a setter which lacks referential stability (for no good reason). There is an open PR to fix this, but the maintainers haven't addressed it. My theory is that it would technically be a breaking change since it would cause fewer rerenders. Theoretically an app might rely on this, but in practice that would be an extremely brittle and unusual behavior to rely on, and the vast majority of users would prefer the reduced rerenders. Under pragmatic versioning they could bump v6.x, and note that the change should be tested but likely doesn't require any code changes. With SemVer they'd be forced to bump to 7.0.0, but this is not a marketable change for a major release.
That doesn't make sense to me.
With semantic versioning the way you communicate a LTS version of a package is you declare that in your documentation. Django (which doesn't fully use SemVer, but is still a good example here) does that on this page: https://www.djangoproject.com/download/#supported-versions
"In Pragmatic Versioning, this is solved with a BIGRELEASE version, which has meaning that can be controlled by the package author" - that doesn't appear to address the need for LTS communication at all. It feels like the situation is exactly the same as SemVer: if you want to do LTS you have to represent that outside of the version number.