mirror of
https://github.com/semver/semver.git
synced 2026-07-11 03:53:53 -05:00
[GH-ISSUE #265] Prepending SemVer with core or API version #6179
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @timmillwood on GitHub (Jul 30, 2015).
Original GitHub issue: https://github.com/semver/semver/issues/265
Within the Drupal community we are looking to switch to SemVer for all contributed modules. However we really need a way to tie the module version to the core version.
Out current consensus is to prepend the SemVer number with the major version number of Drupal core (the Drupal API) that the module relates to. For example a module for Drupal 8.0.0 would have the version number 8.1.0.0, and a module for Drupal 9.0.0 would have the version number 9.1.0.0, we may find that when the module for Drupal 9 gets released all the features are back-ported to the Drupal 8 version making 8.2.0.0.
Would this format be something that SemVer would be interested in adopting, supporting or accepting?
@ergonlogic commented on GitHub (Jul 30, 2015):
Alternatively, if there are already solutions for encoding compatibility with a dependent framework, we'd be interested in hearing how it was handled.
@haacked commented on GitHub (Jul 30, 2015):
I'd be interested in hearing how other communities handle this so we can come up with something that'll work for a large variety of communities.
Just thinking out loud, this feels like a special case of SemVer and perhaps could be handled as a "sub-spec". For example, "SemVer for Modules" which would extend SemVer into the space of modules.
I have to admit, I think the 4 segment version would be confusing because some systems already have 4 segment versions (example, .NET) and the first segment is
Majorversion in all those cases. Perhaps a new delimiter would help?1.0.0x8.0-> My Module version 1.0.0 that "extends" version 8.0.@ergonlogic commented on GitHub (Jul 30, 2015):
Fwiw, the current Drupal version numbering scheme is along the lines of 7.x-1.2. Some of the other proposals to allow semver for contrib modules include 8.x-1.2.3, and 1.2.3-8.x. The latter being an attempt to remain semver-compliant, by using the build-metadata extension.
For anyone interested in all the gory details, there's a (very long) discussion over on drupal.org: https://www.drupal.org/node/1612910
@timmillwood commented on GitHub (Jul 30, 2015):
The main reason CORE.MAJOR.MINOR.PATCH has come out on top is because its works well with composer and packagist.
@FichteFoll commented on GitHub (Aug 3, 2015):
Semver by itself is pretty much complete in this regard and doesn't have to provide support for this kind of problem, but I agree that having some form of standardization (e.g. a superset of semver) is useful.
I can tell you how we solved this for Package Control, the Sublime Text package manager, where packages can support both of its versions, 2 and 3, simultaneously and multiple platforms.
We eventually decided to go for a "version prefix" approach that allows developers to filter their releases and provide disjoint "channels".
Basically, each package may provide different releases, I'll call them "channels". Each channel can target a different platform, for example OSX or Windows, and a different Sublime Text version, e.g. 2 or 3 (it's more precise actually). These channels are entirely disjoint for installation and update purposes, meaning that you will only ever receive updates for the channel that satisfies your setup.
Just like Atom, we utilize git tags for release distribution and the tag name defines the version number, as well as the channel. Channels are filtered by a custom prefix that each package developer may choose arbitrarily.
This is an example, where I initially supported both ST versions in one channel but later decided to split support and branched off the ST2 version (corresponding /tags page). The
tagskey defines the prefix that versioned tags must contain to be considered a release of the channel. Releases for ST2 are now distributed with thest2-vprefix, wherevobviously denotes that the tag is indeed a released version and not part of the semver.If I was to fix a bug in the ST2 channel, I would create a new branch from the
st2-v1.0.0tag (because there currently is none), do some changes on that branch and pushst2-v1.0.1.@haacked commented on GitHub (Aug 3, 2015):
Good point. Another question to consider is whether this information should be embedded in the version or if a new piece of metadata makes sense. For example, it occurs to me that a single number might not make sense for many modules given that a module could support a range of versions of the main product.
@davividal commented on GitHub (Jun 7, 2016):
I left Drupal community a few years ago, so I may be missing some needs. But what about composer.json to handle these dependencies?
I mean, my module/theme can require "drupal/drupal": "~8.0.0" or "drupal/drupal": ">= 8.0.0".
Wouldn't that solve this issue?
@itafroma commented on GitHub (Jun 7, 2016):
@davividal it wouldn't, because Drupal contrib development can have multiple versions of a module in active development, each differing in their core dependency.
For example:
@chx commented on GitHub (Jul 11, 2016):
@itafroma and why is that a problem? Drupal 7.0.0 is compatible with 1.y.z and 3.y.z, 8.0.0 is compatible with 2.y.z and 4.y.z . Is there any tool which requires that if x.y.z and (x+2.y.z) is compatible with 7.0.0 then (x+1.y.z) be compatible with D7 as well? Does Composer stop at (x+1.y.z) if it is incompatible or does it consider every release before picking the right one? I believe the latter but this needs testing.
Why would a user be confused when they try to upgrade within the D7 world they are offered (x+2).y.z instead of (x+1).y.z, does it even matter to them? The most important promise, increase in first number equals new BC breaking features doesn't depend on the increase being by one, does it? What if the developer attempted something, released a couple (x+1).y.z alphas and betas and realized this is a no-go and switches to (x+2).y.z. To the end user, there's no difference -- they see no (x+1).y.z release, whether because it's not D7 compatible or because there are no such at all hardly matters. Check for example how many branches vs releases Yahoo Terms had.
Isn't this a matter of simple tooling and UI presentation: this is the list of D7 compatible branches and releases, and this other list is the D8 branches and releases.
@itafroma commented on GitHub (Jul 11, 2016):
@chx Putting aside the tooling for a moment, which I agree works the way you describe, I think it's worth getting clarification on whether a major version can increment if it only contains API additions or bug fixes (and no BC breaks). I read the semver spec as allowing a major version increase if, and only if, the new version contains a BC break (it can contain other stuff, too, but it must include a BC break).
To me, one of the reported main benefits of semver is that it's clear as day whether a new version of a library will, or won't, break its public API. If I depend on v1.0.0 of a library, I can be confident that v1.0.1 will only contain bug fixes and not break or add anything, and that v1.1.0 will not break anything, only add new options. Likewise, if I see a v2.0.0 of the library, I can be confident that there's a BC break somewhere in the library from the v1.. line.
In the scenario I described (bumping the D8 version of a module to v4.0.0 because a v3.0.0 of the module exists that depends on D7, even though the new version only contains API additions to the v2.0.0 version of the module), I would argue it's not clear as day for a Drupal site builder who only really cares about their release channel (D7 or D8).
If I'm looking only at the D8 version of a module, a minor version bump from v2.0.0 to v2.1.0 is relatively benign. A major version bump from v2.0.0 to v4.0.0 is scary and communicates that at least 2 major BC breaks have occurred since I updated the module, when in reality those two major BC breaks are because of us trying to account for the D7 channel using the same versioning scheme. For a D8 user, there were no BC breaks between v2.0.0 and v4.0.0.
Getting back to the tooling, I'd argue Composer's constraints behave in the same way. By constraining a module to, say,
~2.0in mycomposer.json, I'm asserting to Composer that I am okay with it updating a library to include API additions and bug fixes, but no BC breaks. However, Composer will not, in this case, update to v4.0.0 of the module even though for me, running D8, v4.0.0 only contains API additions from v2.0.0.The only way to get Composer to understand that I'm okay with the upgrade to v4.0.0 is to manually specify each version in my
composer.json:~2.0 | ~4.0. This doesn't seem all that great from a DX perspective, as I now have to keep updating mycomposer.jsonevery time a new version of the module comes out instead of letting Composer do the work for me, at least while both the D7 and D8 versions of the module are in active development.@chx commented on GitHub (Jul 11, 2016):
I do not readily understand
this part. If there are no BC breaks then 2.1.0 would be next and not 4.0.0. Yes, there's a 3.0.0 out but so what, you are still developing the 2.y.z series -- no problem there?
Edit: your previous comment had this question:
Sure it becomes 2.1.0. How does this differ from continuing say GTK 2 or Python 2 when GTK 3 or Python 3 is out?
@itafroma commented on GitHub (Jul 11, 2016):
Right, so that's the confusion I referred to in my original comment. The spec is unclear here: if v3.0.0 is released, can I go back and update the v2.. line or do I have to bump the version to v4.0.0 because technically, I (re-)introduced a BC break when compared to v3.0.0?
To address your edit:
Neither GTK nor Python assert that they are following Semver.
@FichteFoll commented on GitHub (Jul 11, 2016):
In the 2.x.y line you only compare releases to their predecessor. There is no timing restriction on whether you must not release a version of lower precedence than your highest, so it would be allowed.
@eelkeblok commented on GitHub (Jul 11, 2016):
I don't think tooling is the primary driver for this wish. It is about clearity to human beings (one of the main drivers for semver, I believe).
I very much like the described approach for Sublime Text. It is actually very much like a proposal I did over in de drupal.org thread, where module maintainers basically decide for themselves what "flavours" (channels) they actually need.
@Crell commented on GitHub (Jul 11, 2016):
More generally, this is an issue for packages that depend on some larger platform package (Drupal, Sublime text, a Joomla plugin, a language version, etc.) that has multiple incompatible versions still in active maintenance. Think code that needs to be considerably different for different LTS versions of Ubuntu for another example.
How can Semver capture that there are multiple, independent, supported lines of work (not to be confused with "branches"), each of which may have independent need for major, minor, and patch releases?
@dumblob commented on GitHub (Oct 12, 2016):
This is just a non-linear development and a general solution to this general problem of independent versioning of (highly) related code (module, major version, etc.) is proposed e.g. in https://github.com/mojombo/semver/issues/163#issuecomment-192662245 .
@eelkeblok commented on GitHub (Oct 13, 2016):
How does that address the scenario where a new version (i.e. new functionality/architecture) of a module is introduced for an older version of the main system?
@ameenross commented on GitHub (Oct 13, 2016):
That's totally unrelated, sorry.
@eelkeblok commented on GitHub (Oct 13, 2016):
@ameenross Could you please clarify what is unrelated to what?
@ameenross commented on GitHub (Oct 13, 2016):
@eelkeblok I was referring to https://github.com/mojombo/semver/issues/265#issuecomment-253332499
@jwdonahue commented on GitHub (Dec 8, 2017):
@timmillwood
Why can't this problem be solved with a list of SemVer strings?
This seems like a simplified example of the dependency graph problem. Why can't we go off and create a standard to cover the full scope of the dependency graph, that uses package names and SemVer strings as node names? I don't think we should attempt to solve every little problem in the tool chain from within SemVer. Once we go down that road, then why not solve a bigger piece of problem X later on? What about problems A..Y? It's one of those slippery slopes.
Maybe, when we have a good description of the problem space and maybe a prototype spec to cover the graph problem, we find that SemVer needs a supporting update? That would be cool with me, but I would want to see and understand how the encompassing scope works, first.
I much prefer having a network of composable standards at my disposal. As with reusable code, small standards with limited scope are generally more composable than larger, broader scoped standards. Just look at the thousands of IETF standards documents and you'll get an idea what I am on about.
@dumblob commented on GitHub (Dec 8, 2017):
@jwdonahue just take a look at the proposal https://github.com/semver/semver/issues/163#issuecomment-192662245 .
@jwdonahue commented on GitHub (Dec 9, 2017):
@dumblob, I have already read it, responded to it and gergelypolonkai agreed that it was a matter of developer policy whether to back-port. That's not the same issue as this one, which is whether SemVer should support specifying a 1-1 relation between pairs of components, which is just an over-simplified version of the dependency graph problem, which is definitely out of scope for SemVer.
@dumblob commented on GitHub (Dec 9, 2017):
Well, it's definitely not so crystal clear as you wrote - please take (another) look at the options (1) and (2) at the end of the comment https://github.com/semver/semver/issues/163#issuecomment-262185925 .
Semver is a building block, but nowhere is written how to use it integrated into real-world issues which are significantly more complicated (therefore all the hundreds of proposals to extend Semver) than development of a single-purpose software. And that's what people are missing - an integrated solution, not just a building block (disregarding the fact, that Semver is an outstanding building block).
@jwdonahue commented on GitHub (Dec 12, 2017):
@dumblob, I have read #163, responded to it and it is now closed. No standard can cover everybody's scenario. None should even try. If you have a better idea, go write your standard, evangelize its virtues and then either adopt every exception requested, or reject some or all of them, it will then be entirely up to you. This thread is all about getting the SemVer standard to accept somebody's special snow-flake. We already seem to know of hundreds, as you claim, and there are probably tens of thousands of them out there that we haven't even heard from yet.
As far I can tell, the dependency graph problem, which this particular issue only partially addresses, is very hard. SemVer doesn't try to solve that problem. It merely defines a standard for specifying versions of things that seems to work for a very large set of solutions. There are other proposals out there that seem to me; more interesting avenues to pursue, than the single dependency problem. What about version roll-backs and substitutions? What about the rest of the graph?
Solving the single dependency relation seems fairly easy, just adopt a version of this proposal. What about the rest of the problem? It is often quite easy to find local optimizations to problems that can never be generalized. If you establish a large user base committed to the local valley in the search space, it becomes increasingly difficult to motivate them to climb the next hill that leads to a more general, possibly more optimal solution, because getting to the next valley requires a completely different tool set. If you point to too many promised lands, eventually folks stop following you.
@timmillwood's proposal may be a solution to the single dependency problem, but think through how that can be extended to two or three dependencies. It does not seem to me to be very scale-able. Perhaps in practice, this won't matter for a large enough set of implementers? Go and test your theories in the real world and present your evidence.
Apparently, the Drupal community has a solution that works for them. Should the tool makers who are committed to SemVer go to Drupal and say "this is how we do it, you should change your spec? No, but we can say that the solution would be a breaking change, that solves a problem SemVer was not ever intended to solve. Drupal has their extension of SemVer, that's wonderful, maybe eventually someone will be inspired by SemVer to solve a bigger piece of the problem. I look forward to seeing that solution. I am sure it will happen eventually.
@Haacked, I vote to close this issue if @timmillwood doesn't do so in the next few days.
@axd1967 commented on GitHub (Feb 27, 2018):
Bit late - but does this issue also apply when try to maintain a Python 2.7 and a 3.5 version of a program (by means of forked branches, so intentionally not trying to maintain one version that runs in both environments, just to be clear)?
@eelkeblok commented on GitHub (Feb 27, 2018):
Yes, that would be the same sort of issue (although I imagine the differences between Python 2.7 and 3.5 are more subtle, so it is easier to retain feature parity between the different flavours than it is with Drupal modules).
@jwdonahue commented on GitHub (Feb 27, 2018):
These are the classic A depends on B scenarios and some of the aspects that factor into exactly what is included in a particular versioned package of A:
B is a framework or operating system that end-users recognize and are accustomed to. A effectively extends or enhances B.
1.1 A has the same feature set with specialized implementations for the particular versions of B.
1.2 A has radically different feature set driven by different features sets of B.
2.3 A has just a few feature differences driven by B and its customer's expectations.
2.4 A has multiple special configurations such as debug, release, code coverage and profiling to name a few.
2.4.1 B has multiple special configurations such as debug, release, code coverage and profiling which may be combined in any combination with A's special configurations.
B is a collection of functions or data that is intended to be out of site and mind with respect to customers. B effectively enhances A. A may drop B in exchange for one or more other collections of functions or data.
2.2 A has multiple special configurations such as debug, release, code coverage and profiling to name a few.
2.2.1 B or its replacements have multiple special configurations such as debug, release, code coverage and profiling which may be combined in any combination with A's special configurations.
I am sure I've left out something, but in the case of 1, that's approximately 4 * 4 * 3 = 48 permutations, counting all the special configurations. And what if A targeted multiple OS's/frameworks? Permutation bomb!
How do we encode each of these possibilities into a version string? Should we? It is the most common practice, not to, and that's probably one reason why the SemVer spec says nothing about it. Teams deal with this complexity in a variety of ways that satisfy their particular needs with varying degrees of success over time. It is common practice for instance, to include both debug and release configurations in a single library package. I've even seen some packages/installers that deposit versions of A for all supported frameworks/OS's, for developers who do cross-platform development work. I've also seen cases where the down load page for a version of A has dozens of individually named packages, each for a different operation system, framework or configuration.
You have to consider exactly what it is you are versioning. We have API's (interface declarations), libraries (implementations), packages, applications, operating systems and data sets (collections), all of which can be versioned. In the case of a collection, SemVer applies a single version triple to the set of versions of objects contained within. If you tried to encode in that collection's version string, some clue as to the version of every element within, it would not be human readable and might be excessively long as well.
A version string by itself is meaningless noise, it isn't until we pair it with a name that it has any meaning. Are we versioning the name? No, we're versioning whatever the name refers to. In this case, it's a software product that may be atomic or might be a composite of other products. That name is usually a trademark that somebody has worked very hard to map to a set of features/content in the minds of customers. The version number is a refinement appended to the name, when it changes, customers know the features/content have changed, but it's still a recognizable A.
A's dependencies however, are a separate aspect and as I pointed out above, a complicated one. In some cases, packaging tools like Nuget and NPM provide some support for embedded dependency information and shipping multiple configurations in a single package. Other's, not so much. One good practice here is to encode some things in tags, either attached to the version string or the package name. Well in practice, the packages name includes the version string and any of tags anyway, right? So now we have:
A.1.0.0+Win10-B.4.0.0
A.1.0.0+Ubuntu17-B.4.0.1
The possibilities are endless and depend on package/release/publish tooling. Something like A.4.1.0.0 however, should not be among them. For one, it's not a recognizable semverized string and even if I suspected that the '4' referenced something else, how do I know it's B? @timmillwood, if that's the convention you want to adopt, go for it, but don't call it SemVer, call it DrupalVer and make sure you document it thoroughly.
The biggest problem I have with this scheme is that it will require its own special set of tooling. If we have a C that depends on A that is completely independent of the B version, how do I define that dependency? Now I have to produce two separate packages simply because of your versioning scheme? That's pretty rude and I don't think you've thought this through enough if you stick to this plan.
@ameenross commented on GitHub (Feb 28, 2018):
I've yet to come across a Drupal module that is independent of the Drupal major version. In fact, the metadata of the module tells Drupal for which major version it was created. So a Drupal module requiring another Drupal module, both will require the same Drupal major version. You already have to release a version per drupal core.
Let's say that changes in the future, and the supported Drupal core versions are encoded via composer version constraints. In that case, you also don't have any issue as standard dependency resolving (which is the real iteration bomb by the way, so I see no issue with that either) will be applied without any special sauce at all.
@jwdonahue commented on GitHub (Feb 28, 2018):
Ok, so I did a little research, Drupal doesn't use SemVer and SemVer is not fit for nor should it ever attempt to cover the dependency tree. @timmillwood hasn't chimed in years.
@Haacked, this thread should be closed as won't-fix.
@plach79 commented on GitHub (Feb 28, 2018):
The latest major version of Drupal (8) does use SemVer. Some of the main blockers for Drupal modules (i.e. extensions) to adopt SemVer are the problems discussed here.
@jwdonahue commented on GitHub (Feb 28, 2018):
@plach79, see their own documentation. Module version "7.x-1.2" is NOT a SemVer version string. Nor do either of it's components appear to be SemVer, which MUST be a triple.
@jwdonahue commented on GitHub (Feb 28, 2018):
So, Module 1.2.0+Drupal.7.1.0 would be a recognizable SemVer string that makes some sense, though I still argue that including dependency data at this level is unwise at best. Module 7.x.y-1.2 would be syntactically legal SemVer, but nonsensical in that every module would have to be treated as a prerelease version.
What if my module isn't just dependent on a version of Drupal? What if it has a dozen of other things it's dependent on? How do you deal with that? I argue that the solution should be the same for one and for all, not just the special Drupal case. Such a solution is outside the purview of SemVer.
@plach79 commented on GitHub (Feb 28, 2018):
@jwdonahue, the documentation you linked refers to contributed modules, which is Drupal jargon for extensions. Those in fact do not use SemVer at the moment. The main Drupal package has adopted SemVer during the latest major release development cycle. Being able to support SemVer also for extensions is something that is going to be required to implement some policy changes currently being discussed. The solutions discussed here are a possible way forward, however the Drupal contrib space will likely have to adopt SemVer (or some variation of it) regardless, so it would be good to get it right :)
@jwdonahue commented on GitHub (Feb 28, 2018):
I read the gist of @timmillwood's post as being a question of whether the the current DX.DY-EX.EY scheme was something that the SemVer spec should take on-board. I don't think it should. As I said earlier in this thread, I think you should version each of your components using SemVer rules and syntax and handle the dependency graph by other means. When everybody uses the same version format and semantics, then the graph construction problem can be solved if every node in the graph includes links to each of its immediate dependencies. Then it's a simple matter for package installers and updaters to reconstruct a valid graph or point out where that graph is broken by the expressed rules.
@jwdonahue commented on GitHub (Feb 28, 2018):
@plach79, are you stakeholder or an interested party? You might want to keep an eye on VersionSchema. Not much there at the moment, but I only just got started on it in earnest. Definitely looking for stakeholders and interested parties. Basically looking for a standard VersionMeta tag that would be URI to a VersionSchema that defines the actual semantics and syntax in a way that is both human and machine readable.
@jwdonahue commented on GitHub (Sep 25, 2018):
@timmillwood, please close this thread at your earliest possible convenience. The answer to your question is no and this thread has already been hijacked once.