Please add a FAQ entry about platform support #487

Open
opened 2026-02-17 12:09:01 -06:00 by GiteaMirror · 73 comments
Owner

Originally created by @mvz on GitHub (Jun 25, 2021).

I've been in several discussions about what to do about supported platforms (i.e., for Ruby gems, versions of Ruby, for npm packages, versions of node).

Here's a recent example: https://github.com/semver/semver/issues/708

I see two possible positions:

  1. Semver is only about the documented API, so similar to updating dependencies, dropping supported platforms could even happen in a patch release.
  2. Dropping a supported platform is a breaking change so that should only happen in a major release.

(I have a preference but that is not really relevant to this ticket!)

There is already an entry in the FAQ section about updating dependencies. Having one for platform support would help projects a lot in adhering to semver.

Originally created by @mvz on GitHub (Jun 25, 2021). I've been in several discussions about what to do about supported platforms (i.e., for Ruby gems, versions of Ruby, for npm packages, versions of node). Here's a recent example: https://github.com/semver/semver/issues/708 I see two possible positions: 1. Semver is only about the documented API, so similar to updating dependencies, dropping supported platforms could even happen in a patch release. 2. Dropping a supported platform is a breaking change so that should only happen in a major release. (I have a preference but that is not really relevant to this ticket!) There is already an entry in the FAQ section about updating dependencies. Having one for platform support would help projects a lot in adhering to semver.
Author
Owner

@ljharb commented on GitHub (Jun 25, 2021):

Supported platforms are always part of the documented API. A FAQ entry would be nice but it doesn't change that that's how it works.

@ljharb commented on GitHub (Jun 25, 2021): Supported platforms are always part of the documented API. A FAQ entry would be nice but it doesn't change that that's how it works.
Author
Owner

@mvz commented on GitHub (Jun 25, 2021):

@ljharb this ticket is explicitly about a FAQ entry. I have not heard from anyone but you on this, and you have already indicated you can't make a FAQ entry happen. I'd like te see a response from someone who can.

@mvz commented on GitHub (Jun 25, 2021): @ljharb this ticket is explicitly about a FAQ entry. I have not heard from anyone but you on this, and you have already indicated you can't make a FAQ entry happen. I'd like te see a response from someone who can.
Author
Owner

@krader1961 commented on GitHub (Jun 28, 2021):

It seems to me pretty obvious that semantic versioning only applies to the public API. Dropping support for a platform does not change the public API. Doing so should not result in a bump of the major version. I don't think this warrants a FAQ entry but I have no objection to adding such a FAQ clarification.

@krader1961 commented on GitHub (Jun 28, 2021): It seems to me pretty obvious that semantic versioning only applies to the public API. Dropping support for a platform does not change the public API. Doing so **should not** result in a bump of the major version. I don't think this warrants a FAQ entry but I have no objection to adding such a FAQ clarification.
Author
Owner

@ljharb commented on GitHub (Jun 28, 2021):

A breaking change is something that requires the consumer to make changes to their application after updating. Upgrading the platform version is included in this - dropping support for a platform is both obviously and objectively a breaking change.

@ljharb commented on GitHub (Jun 28, 2021): A breaking change is something that requires the consumer to make changes to their application after updating. Upgrading the platform version is included in this - dropping support for a platform is both obviously and objectively a breaking change.
Author
Owner

@krader1961 commented on GitHub (Jun 28, 2021):

A breaking change is something that requires the consumer to make changes to their application after updating.

Obviously adding a platform is not a breaking change that warrants bumping the major number. Which is why removing a platform is not a breaking change. Anyone using a module on a platform that is no longer supported can simply pin their use to the last supported version. The project should ensure that if they do not do so their builds will fail. I don't think dropping support for a platform warrants bumping the major number.

@krader1961 commented on GitHub (Jun 28, 2021): > A breaking change is something that requires the consumer to make changes to their application after updating. Obviously adding a platform is not a breaking change that warrants bumping the major number. Which is why removing a platform is not a breaking change. Anyone using a module on a platform that is no longer supported can simply pin their use to the last supported version. The project should ensure that if they do not do so their builds will fail. I don't think dropping support for a platform warrants bumping the major number.
Author
Owner

@ljharb commented on GitHub (Jun 28, 2021):

@krader1961 no, adding a platform is adding stuff, so it's a minor version. removal is typically major, addition is typically minor.

The platform's support status is irrelevant.

@ljharb commented on GitHub (Jun 28, 2021): @krader1961 no, adding a platform is adding stuff, so it's a minor version. *removal* is typically major, *addition* is typically minor. The platform's support status is irrelevant.
Author
Owner

@krader1961 commented on GitHub (Jun 29, 2021):

@ljharb, I am ambivalent with respect to your argument. Please point us to where "Supported platforms are always part of the documented API" is itself documented. Even for a different project. A platform might be dropped for many reasons. Such as the platform no longer being actively maintained. Dropping support for that platform is not a breaking change for every other platform.

I understand why you are making your argument. If a project drops support for a platform its public API for that platform has, technically, changed. But no other platform is affected and the affected users of the, now unsupported, platform can simply pin their dependency. It is not at all obvious that dropping support for a platform warrants changing the major version since the reason for dropping support has nothing to do with changing the public API other than for that platform.

@krader1961 commented on GitHub (Jun 29, 2021): @ljharb, I am ambivalent with respect to your argument. Please point us to where "Supported platforms are always part of the documented API" is itself documented. Even for a different project. A platform might be dropped for many reasons. Such as the platform no longer being actively maintained. Dropping support for that platform is not a breaking change for every other platform. I understand why you are making your argument. If a project drops support for a platform its public API for that platform has, technically, changed. But no other platform is affected and the affected users of the, now unsupported, platform can simply pin their dependency. It is not at all obvious that dropping support for a platform warrants changing the major version since the reason for dropping support has nothing to do with changing the public API other than for that platform.
Author
Owner

@ljharb commented on GitHub (Jun 29, 2021):

“changing the API other than <changing the API for nonzero users>“

@ljharb commented on GitHub (Jun 29, 2021): “changing the API other than \<changing the API for nonzero users\>“
Author
Owner

@07831968138 commented on GitHub (Jul 23, 2021):

F

@07831968138 commented on GitHub (Jul 23, 2021): F
Author
Owner

@jwdonahue commented on GitHub (Sep 5, 2021):

This is a perennial issue that arises out of the fact that the spec talks about API's more than packages AND it has a broad definition of what an API is:

1 Software using Semantic Versioning MUST declare a public API. This API could be declared in the code itself or exist strictly in documentation. However it is done, it SHOULD be precise and comprehensive.

It turns out that in practice, we rarely ever actually version our Programming Interfaces (classic API's). Most of the SemVer implementing tools are in fact packaging tools, where the version string applies to an entire collection of interface/implementation code, data, binaries and metadata. The later normally includes something like a package manifest. The package manifests have come to be considered part of the public API, in many of these tool chains.

It's all about what exactly are you versioning? If it's a core set of function/method signatures in a header file, then implementation details regarding supported platforms would not be included, as literally specified by the SemVer spec. But the cases where arguments arise over breaking changes around supported platforms never arise in such pure API cases. They arise out of environments/tool-chains where the version string is applied to a package and its manifest, which tend to reference implementation details and dependencies.

@jwdonahue commented on GitHub (Sep 5, 2021): This is a perennial issue that arises out of the fact that the spec talks about API's more than packages AND it has a broad definition of what an API is: > [1](https://semver.org/#spec-item-1) Software using Semantic Versioning MUST declare a public API. This API could be declared in the code itself or exist strictly in documentation. However it is done, it SHOULD be precise and comprehensive. It turns out that in practice, we rarely ever actually version our Programming Interfaces (classic API's). Most of the SemVer implementing tools are in fact packaging tools, where the version string applies to an entire collection of interface/implementation code, data, binaries and metadata. The later normally includes something like a package manifest. The package manifests have come to be considered part of the public API, in many of these tool chains. It's all about what exactly are you versioning? If it's a core set of function/method signatures in a header file, then implementation details regarding supported platforms would not be included, as literally specified by the SemVer spec. But the cases where arguments arise over breaking changes around supported platforms never arise in such pure API cases. They arise out of environments/tool-chains where the version string is applied to a package and its manifest, which tend to reference implementation details and dependencies.
Author
Owner

@nVitius commented on GitHub (Nov 1, 2021):

It sounds like the maintainers of semver have strong opinions on this one; I don't think discussing it further is really going to take us anywhere. This issue has gotten off-track though. To avoid further questions about how this should or should not work, can we please add an entry into the FAQ regarding this point of discussion?

@nVitius commented on GitHub (Nov 1, 2021): It sounds like the maintainers of semver have strong opinions on this one; I don't think discussing it further is really going to take us anywhere. This issue has gotten off-track though. To avoid further questions about how this should or should not work, can we please add an entry into the FAQ regarding this point of discussion?
Author
Owner

@broofa commented on GitHub (Dec 4, 2021):

Stirring the pot...

We (the uuid module maintainers) are dropping support for node 8 and IE 11 after uuid@8.3.2. Specifically, we're dropping those platforms from our CI testing matrix and, moving forward, will be closing issues specific to those platforms as "WON'T FIX". So how should this be reflected in the release version?

The answer is self-evident: It has to be a major release. The fact we no longer test legacy platforms means that when a legacy-breaking change gets introduced (probably in the form of some otherwise minor change), we are unlikely to know about it.

Thus, the only responsible option is to do a major version bump now, even if everything else in the API remains unchanged.

@broofa commented on GitHub (Dec 4, 2021): Stirring the pot... We (the `uuid` module maintainers) are dropping support for node 8 and IE 11 after `uuid@8.3.2`. Specifically, we're dropping those platforms from our CI testing matrix and, moving forward, will be closing issues specific to those platforms as "WON'T FIX". So how should this be reflected in the release version? The answer is self-evident: It has to be a major release. The fact we no longer test legacy platforms means that when a legacy-breaking change gets introduced (probably in the form of some otherwise minor change), we are unlikely to know about it. Thus, the only responsible option is to do a major version bump now, even if everything else in the API remains unchanged.
Author
Owner

@ljharb commented on GitHub (Dec 4, 2021):

@broofa indeed, that's a breaking change, so you'd need to bump to v9 (altho i'm sad about that decision)

@ljharb commented on GitHub (Dec 4, 2021): @broofa indeed, that's a breaking change, so you'd need to bump to v9 (altho i'm sad about that decision)
Author
Owner

@mvz commented on GitHub (Dec 4, 2021):

@broofa you can certainly do that if you want, but semver as defined does not force you to do so.

@mvz commented on GitHub (Dec 4, 2021): @broofa you can certainly do that if you want, but semver as defined does not force you to do so.
Author
Owner

@ljharb commented on GitHub (Dec 4, 2021):

@mvz yes it does, because users on node 8 will see their code no longer work when they install the update, which the spec forces you to mark as a breaking change.

@ljharb commented on GitHub (Dec 4, 2021): @mvz yes it does, because users on node 8 will see their code no longer work when they install the update, which the spec forces you to mark as a breaking change.
Author
Owner

@mvz commented on GitHub (Dec 4, 2021):

@ljharb feel free to continue to ignore the meaning of the term 'API'.

@mvz commented on GitHub (Dec 4, 2021): @ljharb feel free to continue to ignore the meaning of the term 'API'.
Author
Owner

@ljharb commented on GitHub (Dec 4, 2021):

The platform it runs on is part of the interface. When the bulk of the industry considers it included, and you don’t, then perhaps your definition of the term is the problem.

@ljharb commented on GitHub (Dec 4, 2021): The platform it runs on is part of the interface. When the bulk of the industry considers it included, and you don’t, then perhaps your definition of the term is the problem.
Author
Owner

@broofa commented on GitHub (Dec 4, 2021):

@mvz @ljharb Are we arguing? If so, why? Aren't we all saying that supported platforms should be treated as part of the API, and that this project should be more explicit about that fact (either in the FAQ or the spec)?

@broofa commented on GitHub (Dec 4, 2021): @mvz @ljharb Are we arguing? If so, why? Aren't we all saying that supported platforms should be treated as part of the API, and that this project should be more explicit about that fact (either in the FAQ or the spec)?
Author
Owner

@mvz commented on GitHub (Dec 4, 2021):

@broofa Yes, we're arguing :-). I think the fundamental problem in all these discussions is the question of what exacly 'API' means. Obiously, @ljharb and myself disagree on this. It seems your opinion is more in line with that of @ljharb, while AFAICS, @krader1961 seems to agree with me.

The main problem I have with @ljharb's position is that it seems to make the use of the word API in the semver spec pointless, i.e., you could just replace

increment the MAJOR version when you make incompatible API changes,

with:

increment the MAJOR version when you make incompatible changes,

That said, I can totally accept if the understanding of 'API' has changed over the years (as has happened for many terms). So, I think the best way forward is for inclusion in the semver spec of a definition of how semver understands the term 'API'.

@mvz commented on GitHub (Dec 4, 2021): @broofa Yes, we're arguing :-). I think the fundamental problem in all these discussions is the question of what exacly 'API' means. Obiously, @ljharb and myself disagree on this. It seems your opinion is more in line with that of @ljharb, while AFAICS, @krader1961 seems to agree with me. The main problem I have with @ljharb's position is that it seems to make the use of the word API in the semver spec pointless, i.e., you could just replace > increment the MAJOR version when you make incompatible API changes, with: > increment the MAJOR version when you make incompatible changes, That said, I can totally accept if the understanding of 'API' has changed over the years (as has happened for many terms). So, I think the best way forward is for inclusion in the semver spec of a _definition_ of how semver understands the term 'API'.
Author
Owner

@ljharb commented on GitHub (Dec 4, 2021):

I think it's a reasonable argument that if someone doesn't understand that "API" includes the platform it runs on, that the document should clarify what API does mean (and always has meant).

An incompatible API change is any change that breaks the P - the program.

@ljharb commented on GitHub (Dec 4, 2021): I think it's a reasonable argument that if someone doesn't understand that "API" includes the platform it runs on, that the document should clarify what API does mean (and always has meant). An incompatible API change is any change that breaks the P - the program.
Author
Owner

@jwdonahue commented on GitHub (Dec 4, 2021):

Let's not forget that transitive dependencies are handled differently in different environments. The spec contains a phrase or two that implies we should ignore those dependencies and focus on the interface, but then it also mentions packages. It does not contain sufficient language to delineate between versioning a package vs versioning an interface, and how the nuances of specific environments drives how dependencies should be handled in those two major use cases. Doing so would probably qualify as a breaking change.

The spec mentions solving the dependency hell problem, and then goes on to say in the FAQ that dependencies should not be considered. It implies that most of the causes of dependency hell should be ignored when versioning your API.

The spec has a dual personality that cannot be resolved without sufficient churn that it would require a major version bump. Something the maintainers seem loathe to do.

@jwdonahue commented on GitHub (Dec 4, 2021): Let's not forget that transitive dependencies are handled differently in different environments. The spec contains a phrase or two that implies we should ignore those dependencies and focus on the interface, but then it also mentions packages. It does not contain sufficient language to delineate between versioning a package vs versioning an interface, and how the nuances of specific environments drives how dependencies should be handled in those two major use cases. Doing so would probably qualify as a breaking change. The spec mentions solving the [dependency hell](https://en.wikipedia.org/wiki/Dependency_hell) problem, and then goes on to say in the [FAQ that dependencies should not be considered](https://semver.org/#what-should-i-do-if-i-update-my-own-dependencies-without-changing-the-public-api). It implies that most of the causes of dependency hell should be ignored when versioning your API. The spec has a dual personality that cannot be resolved without sufficient churn that it would require a major version bump. Something the maintainers seem loathe to do.
Author
Owner

@jwdonahue commented on GitHub (Dec 4, 2021):

I would add that in an environment where the entire dependency sub-graph of any node is easily constructed from available data, it is sufficient to limit the scope of versioning decisions, for any one node, to reflect the type of changes for that node alone, without regard to dependencies. You would be saying "my changes may be breaking relative to my previous version of my own code" or "my changes should not be breaking relative to the previous version of my own code", and it is up to the environment to prevent consumers of that node from taking it, if any node in that sub-graph would break that consumer.

I think that was probably the original dream wrt to SemVer:

In systems with many dependencies, releasing new package versions can quickly become a nightmare. If the dependency specifications are too tight, you are in danger of version lock (the inability to upgrade a package without having to release new versions of every dependent package). If dependencies are specified too loosely, you will inevitably be bitten by version promiscuity (assuming compatibility with more future versions than is reasonable). Dependency hell is where you are when version lock and/or version promiscuity prevent you from easily and safely moving your project forward.

Try to visualize the sub-graph where green nodes are safe and red nodes contain breaking changes. If you apply the SemVer rules as @ljharb argues, then the whole sub-graph goes red and you lose the information you need to make informed decisions or even how to get unblocked. If you just apply them to your local changes, then the sub-graph distinguishes exactly which nodes are potentially breaking and you can more easily address them. As always, it's more complicated than that in reality.

The key is that it's not just that the top node in the sub-graph took a major version bump on an immediate dependency. Whether that sub-graph will break a particular consumer depends on the rest of that consumer's dependency sub-graph. No package owner can know the full superpositions of all their customer's dependency graphs, over their own dependency graph, so why not just say "hey, my node change is breaking relative to my previous state" and let their consumers resolve their own dependency graphs?

The answer to that question is the tooling we use to decide whether to take a package update isn't smart enough. We generally define our nearest dependencies in terms of version ranges. We say that we'll take P X.y.z where X==N. We don't say we'll take any P greater than N.y.z whose sub-graph will not break me with regard to the rest of my sub-graph. At least that is the general status-quo I am aware of at the moment.

Resolving the dependency graph is a provably hard problem, but might be tamable today.

The main difference between when the spec was first written and today, is the DevOps trend has exploded exponentially in the interim. To make that happen with the available tooling, we had to realize that the purist approach to interpreting SemVer wasn't practical, and encourage developers to reflect their immediate transitive dependency changes in their own versions. We broke SemVer's potential to help us get unstuck, because we didn't have the resources to resolve the entire dependency graph on the fly. So we're a little bit better off than a decade ago, but there is a lot of potential going forward.

That is why I have opposed making any spec changes that lock in the way we currently handle transitive dependencies on most systems. It would be better to establish that there is the ideal of communicating the effect of changes made to your own node's code, but that in practice, we have less than adequate packaging schemes that require us to manually communicate the status of our sub-graph in our own version numbers.

@jwdonahue commented on GitHub (Dec 4, 2021): I would add that in an environment where the entire dependency sub-graph of any node is easily constructed from available data, it is sufficient to limit the scope of versioning decisions, for any one node, to reflect the type of changes for that node alone, without regard to dependencies. You would be saying "my changes may be breaking relative to my previous version of my own code" or "my changes should not be breaking relative to the previous version of my own code", and it is up to the environment to prevent consumers of that node from taking it, if any node in that sub-graph would break that consumer. I think that was probably the original dream wrt to SemVer: > In systems with many dependencies, releasing new package versions can quickly become a nightmare. If the dependency specifications are too tight, you are in danger of version lock (the inability to upgrade a package without having to release new versions of every dependent package). If dependencies are specified too loosely, you will inevitably be bitten by version promiscuity (assuming compatibility with more future versions than is reasonable). Dependency hell is where you are when version lock and/or version promiscuity prevent you from easily and safely moving your project forward. Try to visualize the sub-graph where green nodes are safe and red nodes contain breaking changes. If you apply the SemVer rules as @ljharb argues, then the whole sub-graph goes red and you lose the information you need to make informed decisions or even how to get unblocked. If you just apply them to your local changes, then the sub-graph distinguishes exactly which nodes are potentially breaking and you can more easily address them. As always, it's more complicated than that in reality. The key is that it's not just that the top node in the sub-graph took a major version bump on an immediate dependency. Whether that sub-graph will break a particular consumer depends on the rest of that consumer's dependency sub-graph. No package owner can know the full superpositions of all their customer's dependency graphs, over their own dependency graph, so why not just say "hey, my node change is breaking relative to my previous state" and let their consumers resolve their own dependency graphs? The answer to that question is the tooling we use to decide whether to take a package update isn't smart enough. We generally define our nearest dependencies in terms of version ranges. We say that we'll take P X.y.z where X==N. We don't say we'll take any P greater than N.y.z whose sub-graph will not break me with regard to the rest of my sub-graph. At least that is the general status-quo I am aware of at the moment. Resolving the dependency graph is a provably hard problem, but might be tamable today. The main difference between when the spec was first written and today, is the DevOps trend has exploded exponentially in the interim. To make that happen with the available tooling, we had to realize that the purist approach to interpreting SemVer wasn't practical, and encourage developers to reflect their immediate transitive dependency changes in their own versions. We broke SemVer's potential to help us get unstuck, because we didn't have the resources to resolve the entire dependency graph on the fly. So we're a little bit better off than a decade ago, but there is a lot of potential going forward. That is why I have opposed making any spec changes that lock in the way we currently handle transitive dependencies on most systems. It would be better to establish that there is the ideal of communicating the effect of changes made to your own node's code, but that in practice, we have less than adequate packaging schemes that require us to manually communicate the status of our sub-graph in our own version numbers.
Author
Owner

@ljharb commented on GitHub (Dec 4, 2021):

@jwdonahue it's impossible not to make the entire subgraph red, because "my code" directly uses the transitive dependency, so if it breaks, my code does too.

@ljharb commented on GitHub (Dec 4, 2021): @jwdonahue it's impossible not to make the entire subgraph red, because "my code" *directly uses* the transitive dependency, so if it breaks, my code does too.
Author
Owner

@jwdonahue commented on GitHub (Dec 4, 2021):

First, when I say node here, I am not talking about Node or referencing any particular environment.

Consider Pa depends on Pb N.y.z. The owner of Pa might consider the effort of making their code compatible with Pb N+1.y.z is reasonable and it doesn't involve them modifying their own interfaces (ignoring packaging and environmental details for now).

Now consider Pz => Pa where Pz has no other node in its dependency graph that takes a dependency on Pb. When that is the case, Pa's internal changes will not break Pz because Pz's own interface hasn't changed. The owner of Pa might have many more customers who's only dependence on Pb is through Pa (no diamond dependency problem here), than customers who have other direct or indirect dependencies on Pb (diamond dependency issue). It may in fact be the case that many of Pa's customers have already adopted Pb N+1 and wouldn't be broken by the transitive update through Pa.

It is only necessary for Pa to communicate whether they broke their own interface, not that they took a breaking change from a dependency. Provided the consumer can see Pa's full dependency graph, they can decide whether Pa's changes are breaking for them or not. Whether a node in the graph is breaking for you, depends on whether you take a direct dependency on its interface. If a node's interface is hidden from view, you should not care if one or more of your dependencies absorbed breaking changes from their dependencies.

There are also some environments where side by side execution of different versions of a component is possible and their build ingestion process doesn't halt on Pa's transition from Pb N to N+1. Whether this holds true depends on the tool chain and environment.

The spec should remain neutral wrt to tool chains and environments.

@jwdonahue commented on GitHub (Dec 4, 2021): First, when I say node here, I am not talking about Node or referencing any particular environment. Consider Pa depends on Pb N.y.z. The owner of Pa might consider the effort of making their code compatible with Pb N+1.y.z is reasonable and it doesn't involve them modifying their own interfaces (ignoring packaging and environmental details for now). Now consider Pz => Pa where Pz has no other node in its dependency graph that takes a dependency on Pb. When that is the case, Pa's internal changes will not break Pz because Pz's own interface hasn't changed. The owner of Pa might have many more customers who's only dependence on Pb is through Pa (no diamond dependency problem here), than customers who have other direct or indirect dependencies on Pb (diamond dependency issue). It may in fact be the case that many of Pa's customers have already adopted Pb N+1 and wouldn't be broken by the transitive update through Pa. It is only necessary for Pa to communicate whether they broke their own interface, not that they took a breaking change from a dependency. Provided the consumer can see Pa's full dependency graph, they can decide whether Pa's changes are breaking for them or not. Whether a node in the graph is breaking for you, depends on whether you take a direct dependency on its interface. If a node's interface is hidden from view, you should not care if one or more of your dependencies absorbed breaking changes from their dependencies. There are also some environments where side by side execution of different versions of a component is possible and their build ingestion process doesn't halt on Pa's transition from Pb N to N+1. Whether this holds true depends on the tool chain and environment. The spec should remain neutral wrt to tool chains and environments.
Author
Owner

@broofa commented on GitHub (Dec 5, 2021):

@jwdonahue: I don't see how your comments help answer the question, "Are supported platforms part of the API". E.g. How does your Pa/Pb/Pz example map to my real-world uuid problem? If uuid is "Pa", where does the dependency on node, as a supported platform, manifest?

It seems like there are three options here:

  1. uuid is Pa, platforms aren't part of the public API, so the version doesn't change
  2. uuid is Pa, platforms are part of the public API but are internal, and so are reflected in the Pa version string (i.e. no Pb)... somehow?
  3. uuid is Pa, and platforms are subordinate nodes (Pb = node)

It is only necessary for Pa to communicate whether they broke their own interface, not that they took a breaking change from a dependency.

If we go with option 3, above, which I think is what you (and @mvz and @krader1961) are suggesting (???) then I read this as saying we needn't concern ourselves with informing users of platforms changes. But that's simply not an option in practice. Users on dropped platforms would crucify us for that.

So what am I missing here?

@broofa commented on GitHub (Dec 5, 2021): @jwdonahue: I don't see how your comments help answer the question, "Are supported platforms part of the API". E.g. How does your Pa/Pb/Pz example map to my real-world `uuid` problem? If `uuid` is "Pa", where does the dependency on `node`, as a supported platform, manifest? It seems like there are three options here: 1. `uuid` is Pa, platforms aren't part of the public API, so the version doesn't change 2. `uuid` is Pa, platforms _are_ part of the public API but are internal, and so are reflected in the Pa version string (i.e. no Pb)... somehow? 3. `uuid` is Pa, and platforms are subordinate nodes (Pb = `node`) > It is only necessary for Pa to communicate whether they broke their own interface, not that they took a breaking change from a dependency. If we go with option 3, above, which I think is what you (and @mvz and @krader1961) are suggesting (???) then I read this as saying we needn't concern ourselves with informing users of platforms changes. But that's simply not an option in practice. Users on dropped platforms would crucify us for that. So what am I missing here?
Author
Owner

@jwdonahue commented on GitHub (Dec 5, 2021):

@broofa I wasn't even trying to answer your question or referring to uuid in any way. I was engaging with @ljharb and merely pointing out why I think we should be very careful about changing the spec or the FAQ around this issue. To some, the spec says "version your interface and implementation, ignore your dependencies" and to others it says "when you upgrade a dependency to the next major version, your major version must get a bump". I was trying to explain why that is and why we should be cautious. The spec is loose and there's these purist and pragmatist view points that are in conflict.

Not that it's remotely within my sphere of influence, but I would object if the spec did not allow for the purist's view. I really do think the real problem here is the lack of adequate tooling, not the spec. Well, when the tooling improves we could tighten the spec.

I really don't know enough about Node, NPM or Ruby to weigh-in on what is the appropriate convention. The issue had to do with transitive dependencies, and that is something I know a little bit about. If uuid is built in an environment where tooling or the environment is inadequate, and dropping support for a platform breaks your consumers, then by all means, bump your major version. That's just not universally the case, so we should be very careful about modifying the spec to cover it.

I recall related PR's in the past, some of which I heartily supported adoption of, but I see that they haven't been committed to master after many years. I can tell you that any suggestion that isn't accompanied by a PR, has near zero chance of adoption.

@jwdonahue commented on GitHub (Dec 5, 2021): @broofa I wasn't even trying to answer your question or referring to uuid in any way. I was engaging with @ljharb and merely pointing out why I think we should be very careful about changing the spec or the FAQ around this issue. To some, the spec says "version your interface and implementation, ignore your dependencies" and to others it says "when you upgrade a dependency to the next major version, your major version must get a bump". I was trying to explain why that is and why we should be cautious. The spec is loose and there's these purist and pragmatist view points that are in conflict. Not that it's remotely within my sphere of influence, but I would object if the spec did not allow for the purist's view. I really do think the real problem here is the lack of adequate tooling, not the spec. Well, when the tooling improves we could tighten the spec. I really don't know enough about Node, NPM or Ruby to weigh-in on what is the appropriate convention. The issue had to do with transitive dependencies, and that is something I know a little bit about. If uuid is built in an environment where tooling or the environment is inadequate, and dropping support for a platform breaks your consumers, then by all means, bump your major version. That's just not universally the case, so we should be very careful about modifying the spec to cover it. I recall related PR's in the past, some of which I heartily supported adoption of, but I see that they haven't been committed to master after many years. I can tell you that any suggestion that isn't accompanied by a PR, has near zero chance of adoption.
Author
Owner

@ljharb commented on GitHub (Dec 5, 2021):

I don’t think the looseness is actually a benefit. In any ecosystem, without exception, if your users upgrade and things break, it should be a semver-major. It doesn’t matter whether the cause is first-party code change in the dep, or a transitive dep with a bug, or a transitive dep with a breaking change on that code path.

If bumping a transitive dep - even across a major - isn’t breaking for consumers, then it’s not semver-major; if it is, it is. There are no exceptions here and no room for interpretation.

@ljharb commented on GitHub (Dec 5, 2021): I don’t think the looseness is actually a benefit. In any ecosystem, without exception, if your users upgrade and things break, it should be a semver-major. It doesn’t matter whether the cause is first-party code change in the dep, or a transitive dep with a bug, or a transitive dep with a breaking change on that code path. If bumping a transitive dep - even across a major - isn’t breaking for *consumers*, then it’s not semver-major; if it is, it is. There are no exceptions here and no room for interpretation.
Author
Owner

@jwdonahue commented on GitHub (Dec 5, 2021):

I think the maintainers see it as a benefit. It allows them innovate while claiming adherence to a standard their customers are demanding. I agree that breaking your customers workflows is not acceptable, but I do not think that you can make the blanket claim that upgrading a dependency to the next major version always requires you to bump your own major version. It really does depend on your environment and tool chain. I know of at least one such proprietary environment that looks at the union of your dependency graph and its configured policies to determine whether to take an update or issue a warning or error. It detects circular and diamond dependencies and flags whether a specific forest of nodes has ever been tested before. But it's not a JavaScript environment.

@jwdonahue commented on GitHub (Dec 5, 2021): I think the maintainers see it as a benefit. It allows them innovate while claiming adherence to a standard their customers are demanding. I agree that breaking your customers workflows is not acceptable, but I do not think that you can make the blanket claim that upgrading a dependency to the next major version always requires you to bump your own major version. It really does depend on your environment and tool chain. I know of at least one such proprietary environment that looks at the union of your dependency graph and its configured policies to determine whether to take an update or issue a warning or error. It detects circular and diamond dependencies and flags whether a specific forest of nodes has ever been tested before. But it's not a JavaScript environment.
Author
Owner

@ljharb commented on GitHub (Dec 5, 2021):

Sure, I haven't made that claim. You can certainly update a dep's major and have it not be a breaking change for your consumers. However, if that dep drops support for a platform you support, it's a breaking change just the same as if you did that yourself.

@ljharb commented on GitHub (Dec 5, 2021): Sure, I haven't made that claim. You can certainly update a dep's major and have it not be a breaking change for your consumers. However, if that dep drops support for a platform you support, it's a breaking change just the same as if you did that yourself.
Author
Owner

@broofa commented on GitHub (Dec 5, 2021):

the real problem here is the lack of adequate tooling

I don't know what this means. What kind of tooling are we talking about?

Platform support isn't an issue specific to Node or NPM or Ruby. It's a universal problem for any software, whether you're writing a browser, or an OS, or a network driver or a BIOS. There's a certain "stack" of stuff on which your code sits. Communicating what that stack can and can't be is just as important as communicating the API. How is that a tooling problem?

@broofa commented on GitHub (Dec 5, 2021): > the real problem here is the lack of adequate tooling I don't know what this means. What kind of tooling are we talking about? Platform support isn't an issue specific to Node or NPM or Ruby. It's a universal problem for _any_ software, whether you're writing a browser, or an OS, or a network driver or a BIOS. There's a certain "stack" of stuff on which your code sits. Communicating what that stack can and can't be is just as important as communicating the API. How is that a tooling problem?
Author
Owner

@mvz commented on GitHub (Dec 5, 2021):

What kind of tooling are we talking about?

I think that would be tooling that refuses to upgrade Pa if the upgraded version does not work on a platform you're currently not on (signaled through platform dependency rather than the version number).

I don't know the situation with npm, but in Ruby, there were cases where tying some upgrade would end with failure to install some transient dependency because its latest version was not compatible with the current platform. Nowadays, it should just install a version that is compatible. TL;DR: Ruby will now refuse to upgrade Pa if the new version won't work on the current platform.

I read this as saying we needn't concern ourselves with informing users of platforms changes.

Of course that would be bad. The users are informed through the dependency specifications rather than through the version number.

@mvz commented on GitHub (Dec 5, 2021): > What kind of tooling are we talking about? I think that would be tooling that refuses to upgrade Pa if the upgraded version does not work on a platform you're currently not on (signaled through platform dependency rather than the version number). I don't know the situation with npm, but in Ruby, there were cases where tying some upgrade would end with failure to install some transient dependency because its latest version was not compatible with the current platform. Nowadays, it should just install a version that _is_ compatible. TL;DR: Ruby will now refuse to upgrade Pa if the new version won't work on the current platform. > I read this as saying we needn't concern ourselves with informing users of platforms changes. Of course that would be bad. The users are informed through the dependency specifications rather than through the version number.
Author
Owner

@jwdonahue commented on GitHub (Dec 5, 2021):

However, if that dep drops support for a platform you support, it's a breaking change just the same as if you did that yourself.

Yes, but it doesn't have to be communicated through your version number unless your component drops support. If your own platform dependency is entirely transitive, it depends on your tooling whether that would be a major bump for your component. There's probably a lot more platform agnostic code in the world, than platform dependent. In some environments, dropping support for a platform doesn't break anybody because either there's nobody using that platform anymore, or because the act of dropping that support, moves your product into a new development silo and it would be difficult if not impossible for customers on the older platform to even try to take your latest bits (not that they'd want to).

The spec as it is currently worded, is mute on how to handle dependencies, but the FAQ has had this since 1.0.0-beta (emphasis mine):

What should I do if I update my own dependencies without changing the public API?
That would be considered compatible since it does not affect the public API. Software that explicitly depends on the same dependencies as your package should have their own dependency specifications and the author will notice any conflicts. Determining whether the change is a patch level or minor level modification depends on whether you updated your dependencies in order to fix a bug or introduce new functionality. We would usually expect additional code for the latter instance, in which case it’s obviously a minor level increment.

Now that was written early days wrt the DevOps movement. Most development environments at the time didn't have anything like the packaging tools we have today. We would read the change log for any new component, estimate the level of effort required to upgrade, convince management to take it or leave it, then if it was decided to put forth the effort, it landed on the schedule. It was often just a matter of trial and error. If it didn't break the build, we'd test it, otherwise there was a good chance we'd never upgrade it.

I've always advised anyone who asks something like that FAQ question, that it depends on their environment and tool chain. We had to reinterpret the spec for pragmatic reasons, due to the changes in our dev tool chains and operating environments. In the DevOps world and the absence of adequate tooling, we have to carry any major version bump in our immediate dependencies to our own version number to communicate breakage in many of the most popular development environments today. I personally try to avoid working in those environments when I can.

@jwdonahue commented on GitHub (Dec 5, 2021): > However, if that dep drops support for a platform you support, it's a breaking change just the same as if you did that yourself. Yes, but it doesn't have to be communicated through your version number unless your component drops support. If your own platform dependency is entirely transitive, it depends on your tooling whether that would be a major bump for your component. There's probably a lot more platform agnostic code in the world, than platform dependent. In some environments, dropping support for a platform doesn't break anybody because either there's nobody using that platform anymore, or because the act of dropping that support, moves your product into a new development silo and it would be difficult if not impossible for customers on the older platform to even try to take your latest bits (not that they'd want to). The spec as it is currently worded, is mute on how to handle dependencies, but the FAQ has had this since 1.0.0-beta (emphasis mine): > [What should I do if I update my own dependencies without changing the public API](https://semver.org/#what-should-i-do-if-i-update-my-own-dependencies-without-changing-the-public-api)? > That would be considered compatible since it does not affect the public API. Software that explicitly depends on the same dependencies as your package should have their own dependency specifications and **the author will notice any conflicts**. Determining whether the change is a patch level or minor level modification depends on whether you updated your dependencies in order to fix a bug or introduce new functionality. We would usually expect additional code for the latter instance, in which case it’s obviously a minor level increment. Now that was written early days wrt the DevOps movement. Most development environments at the time didn't have anything like the packaging tools we have today. We would read the change log for any new component, estimate the level of effort required to upgrade, convince management to take it or leave it, then if it was decided to put forth the effort, it landed on the schedule. It was often just a matter of trial and error. If it didn't break the build, we'd test it, otherwise there was a good chance we'd never upgrade it. I've always advised anyone who asks something like that FAQ question, that it depends on their environment and tool chain. We had to reinterpret the spec for pragmatic reasons, due to the changes in our dev tool chains and operating environments. In the DevOps world and the absence of adequate tooling, we have to carry any major version bump in our immediate dependencies to our own version number to communicate breakage in many of the most popular development environments today. I personally try to avoid working in those environments when I can.
Author
Owner

@EricMCornelius commented on GitHub (Dec 15, 2021):

How about we consider a concrete example here in this discussion - instead of venturing so deep into the theoretical?

Consider this:

Package maintainer adds a new dynamic library dependency - which is resolved at runtime.

Technically, no public "API" in the sense of header code/public interface has changed.

However, the dynamic library dependency they've introduced eliminates a large swath of OS support.

Is this a breaking change and a major version upgrade or no?

The fact that semver doesn't explicitly specify said activity makes it effectively useless for its stated intent in the FAQ - which is to ensure that consumers are able to upgrade to new patches and minor versions safely - without unanticipated software failures.

This lackadaisical excuse is being used in the wild for arbitrary software breakage in very public instances - weakening semver as a concept.

@EricMCornelius commented on GitHub (Dec 15, 2021): How about we consider a concrete example here in this discussion - instead of venturing so deep into the theoretical? Consider this: Package maintainer adds a new dynamic library dependency - which is resolved at runtime. Technically, no public "API" in the sense of header code/public interface has changed. However, the dynamic library dependency they've introduced eliminates a large swath of OS support. Is this a breaking change and a major version upgrade or no? The fact that semver doesn't explicitly specify said activity makes it effectively useless for its stated intent in the FAQ - which is to ensure that consumers are able to upgrade to new patches and minor versions safely - without unanticipated software failures. This lackadaisical excuse *is* being used in the wild for arbitrary software breakage in very public instances - weakening semver as a concept.
Author
Owner

@ljharb commented on GitHub (Dec 15, 2021):

@EricMCornelius yes, it's a breaking change for the package. That the dependency is resolved at runtime is irrelevant.

@ljharb commented on GitHub (Dec 15, 2021): @EricMCornelius yes, it's a breaking change for the package. That the dependency is resolved at runtime is irrelevant.
Author
Owner

@jwdonahue commented on GitHub (Dec 15, 2021):

@EricMCornelius

Package maintainer adds a new dynamic library dependency - which is resolved at runtime.

Technically, no public "API" in the sense of header code/public interface has changed.

How exactly did the maintainer accomplish this feat?

It always comes down to exactly what is being versioned? The package or the code-defined interface? Apparently there are some in the ecosystems you are aware of, that chose to answer that question differently than you think they should. That's fine, the market will either punish or adapt to those publisher's eventually. The spec is very clear that you define an API and then you apply those rules to the defined API. It is not for SemVer to dictate the norms and best practices that should be applied in every development stack. It's up to those development communities to define those things.

This lackadaisical excuse is being used in the wild for arbitrary software breakage in very public instances - weakening semver as a concept.

Is it really "lackadaisical"? Those publishers may have put quite a lot of effort into determining exactly what the right answer was for them. Publishers are allowed to change anything for any arbitrary reasons. Nothing you write in a spec will ever change that. I fail to see how the behavior of some purported bad actors weakens the SemVer concept. If there is no strong consensus in your development community around these matters, it's that community not SemVer, which is weak.

All that is required, is for a publisher to be consistent and document exactly what it is their version applies to. Development communities should layer their own standards on top of and around SemVer and whatever other's might apply to them.

@jwdonahue commented on GitHub (Dec 15, 2021): @EricMCornelius > Package maintainer adds a new dynamic library dependency - which is resolved at runtime. > Technically, no public "API" in the sense of header code/public interface has changed. How exactly did the maintainer accomplish this feat? It always comes down to exactly what is being versioned? The package or the code-defined interface? Apparently there are some in the ecosystems you are aware of, that chose to answer that question differently than you think they should. That's fine, the market will either punish or adapt to those publisher's eventually. The spec is very clear that you define an API and then you apply those rules to the defined API. It is not for SemVer to dictate the norms and best practices that should be applied in every development stack. It's up to those development communities to define those things. > This lackadaisical excuse is being used in the wild for arbitrary software breakage in very public instances - weakening semver as a concept. Is it really "lackadaisical"? Those publishers may have put quite a lot of effort into determining exactly what the right answer was for them. Publishers are allowed to change anything for any arbitrary reasons. Nothing you write in a spec will ever change that. I fail to see how the behavior of some purported bad actors weakens the SemVer concept. If there is no strong consensus in your development community around these matters, it's that community not SemVer, which is weak. All that is required, is for a publisher to be consistent and document exactly what it is their version applies to. Development communities should layer their own standards on top of and around SemVer and whatever other's might apply to them.
Author
Owner

@EricMCornelius commented on GitHub (Dec 16, 2021):

@ljharb - that's my stance. But it needs to be officially clarified what the meaning of API is in the context - otherwise people will argue the ambiguity of the definition to justify making significant breaking changes just because the public interface code hasn't been modified in a backwards-incompatible way.

Whereas the purported semantic guarantees of non-breakage for existing use-cases w/o a major version bump are violated.

The spec is not explicit on whether breaking existing usage via new restricted dependency introductions qualifies as an API change - so you leave yourself and others open to needless bikeshedding.

@jwdonahue -

The spec is very clear that you define an API and then you apply those rules to the defined API.

That is not clear. And the semantic intent of what a major version change represents is clearly ambiguous, given this discussion is necessary to begin with. Which is definitely a problem for anything labeling itself as "semver"

So again, I ask - what's the official position on my explicit use-case?

Because if semver feels that there's no true semantic meaning behind a major version change or what represents a breaking change, it ceases to be useful as a specification.

@EricMCornelius commented on GitHub (Dec 16, 2021): @ljharb - that's my stance. But it needs to be officially clarified what the meaning of API is in the context - otherwise people will argue the ambiguity of the definition to justify making significant breaking changes just because the public interface *code* hasn't been modified in a backwards-incompatible way. Whereas the purported *semantic* guarantees of non-breakage for existing use-cases w/o a major version bump are violated. The spec is not explicit on whether breaking existing usage via new restricted dependency introductions qualifies as an API change - so you leave yourself and others open to needless bikeshedding. @jwdonahue - > The spec is very clear that you define an API and then you apply those rules to the defined API. That is not clear. And the semantic intent of what a major version change represents is clearly ambiguous, given this discussion is necessary to begin with. Which is definitely a problem for anything labeling itself as "semver" So again, I ask - what's the official position on my explicit use-case? Because if semver feels that there's no true semantic meaning behind a major version change or what represents a breaking change, it ceases to be useful as a specification.
Author
Owner

@ljharb commented on GitHub (Dec 16, 2021):

@EricMCornelius the simpler way to look at it is, "is a change going to break someone's existing usage of you in an environment where it previously worked? then it's breaking". I'm not sure how that can really be argued.

@ljharb commented on GitHub (Dec 16, 2021): @EricMCornelius the simpler way to look at it is, "is a change going to break someone's existing usage of you in an environment where it previously worked? then it's breaking". I'm not sure how that can really be argued.
Author
Owner

@EricMCornelius commented on GitHub (Dec 16, 2021):

@ljharb - is this the official position of the specification? I'm unclear who has authority here to state as such.

Because I can point you towards precisely where it's being argued that "because the public interface didn't change, platform removal due to additional dynamically linked dependencies don't constitute a need for a major version update"

It's a major project. Which proudly proclaims its use of semver. And a primary maintainer is of the belief that their interpretation of semver is in line with the official position of the spec.

So again, this is not theoretical. There is sufficient ambiguity around the "API" terminology that we've got a major breaking platform deprecation released in a minor version in a significant open source project.

@EricMCornelius commented on GitHub (Dec 16, 2021): @ljharb - is this the official position of the specification? I'm unclear who has authority here to state as such. Because I can point you towards precisely where it's being argued that "because the public interface didn't change, platform removal due to additional dynamically linked dependencies don't constitute a need for a major version update" It's a major project. Which proudly proclaims its use of semver. And a primary maintainer is of the belief that their interpretation of semver is in line with the official position of the spec. So again, this is not theoretical. There is sufficient ambiguity around the "API" terminology that we've got a major breaking platform deprecation released in a minor version in a significant open source project.
Author
Owner

@jwdonahue commented on GitHub (Dec 16, 2021):

@mvz @EricMCornelius. see "Add a note about transitive dependencies on JVM #414". Maybe if enough people support it, it won't take another 5 years to finish it?

@jwdonahue commented on GitHub (Dec 16, 2021): @mvz @EricMCornelius. see "Add a note about transitive dependencies on JVM #414". Maybe if enough people support it, it won't take another 5 years to finish it?
Author
Owner

@jwdonahue commented on GitHub (Dec 16, 2021):

@EricMCornelius, please point us to one or more specific cases.

@jwdonahue commented on GitHub (Dec 16, 2021): @EricMCornelius, please point us to one or more specific cases.
Author
Owner

@ljharb commented on GitHub (Dec 16, 2021):

@EricMCornelius please do point me to it; i'll be happy to attempt to persuade them.

@ljharb commented on GitHub (Dec 16, 2021): @EricMCornelius please do point me to it; i'll be happy to attempt to persuade them.
Author
Owner

@mvz commented on GitHub (Dec 16, 2021):

@jwdonahue I'm confused: that pull request seems to refer to a closed issue, which itself refers to a wording of the FAQ that has now changed completely.

@mvz commented on GitHub (Dec 16, 2021): @jwdonahue I'm confused: that pull request seems to refer to a closed issue, which itself refers to a wording of the FAQ that has now changed completely.
Author
Owner

@EricMCornelius commented on GitHub (Dec 16, 2021):

@ljharb - https://github.com/libuv/libuv/issues/3260#issuecomment-995201596

libuv broke support for windows 7 introducing a new dynamically linked dependency in a minor version.

The maintainer states that this is an appropriate use of semver - and even argues that the discussions on this project confirm his view.

@EricMCornelius commented on GitHub (Dec 16, 2021): @ljharb - https://github.com/libuv/libuv/issues/3260#issuecomment-995201596 libuv broke support for windows 7 introducing a new dynamically linked dependency in a minor version. The maintainer states that this is an appropriate use of semver - and even argues that the discussions on this project confirm his view.
Author
Owner

@mvz commented on GitHub (Dec 16, 2021):

@EricMCornelius is it possible to break stuff on windows 7 by attempting the upgrade? Or will it just not install?

@mvz commented on GitHub (Dec 16, 2021): @EricMCornelius is it possible to break stuff on windows 7 by attempting the upgrade? Or will it just not install?
Author
Owner

@jwdonahue commented on GitHub (Dec 16, 2021):

@mvz That's because it is old and things change. The PR was closed because we gave up hope of getting any traction out of whoever was on the maintainer list back then. Most of us have day jobs. There used to be hundreds of open PR's and threads here. We made a concerted effort to close all the old PR's and threads that weren't getting any traction.

I tried to get it down to a list of manageable PR's that the maintainers could have some hope of wading through in a week-end. That did bare some fruit, but I eventually concluded that the maintainers have their own pet projects and a low tolerance for any change in the spec.

#468 starts with a list of all the threads I could find that fell into the "what is an API?" or "what about dependencies" category at the time. If you do a little spelunking, you'll find that I identified a handful of perennial issue groups and linked each thread in a group to every other one.

One early success was the regex FAQ's, which got a big boost from one of the package maintainers when we hit upon what was essentially the same regex they used in their product (adjusting for environments). But that was an obviously low risk, high return on investment change. Anything that affects the definition of API is inherently risky, because as I have pointed out, there are some environments where dependencies are handled differently.

To get any traction on this, you're going to need a longish list of high-impact examples to prove there is a need for the change. Then you'll also need a well vetted PR/RFC with as much buy-in from the community and the maintainers as you can muster. Believe me, that's a lot of effort.

@jwdonahue commented on GitHub (Dec 16, 2021): @mvz That's because it is old and things change. The PR was closed because we gave up hope of getting any traction out of whoever was on the maintainer list back then. Most of us have day jobs. There used to be hundreds of open PR's and threads here. We made a concerted effort to close all the old PR's and threads that weren't getting any traction. I tried to get it down to a list of manageable PR's that the maintainers could have some hope of wading through in a week-end. That did bare some fruit, but I eventually concluded that the maintainers have their own pet projects and a low tolerance for any change in the spec. #468 starts with a list of all the threads I could find that fell into the "what is an API?" or "what about dependencies" category at the time. If you do a little spelunking, you'll find that I identified a handful of perennial issue groups and linked each thread in a group to every other one. One early success was the regex FAQ's, which got a big boost from one of the package maintainers when we hit upon what was essentially the same regex they used in their product (adjusting for environments). But that was an obviously low risk, high return on investment change. Anything that affects the definition of API is inherently risky, because as I have pointed out, there are some environments where dependencies are handled differently. To get any traction on this, you're going to need a longish list of high-impact examples to prove there is a need for the change. Then you'll also need a well vetted PR/RFC with as much buy-in from the community and the maintainers as you can muster. Believe me, that's a lot of effort.
Author
Owner

@mvz commented on GitHub (Dec 16, 2021):

Thanks, @jwdonahue, I'll look through the #468 thread.

@mvz commented on GitHub (Dec 16, 2021): Thanks, @jwdonahue, I'll look through the #468 thread.
Author
Owner

@ljharb commented on GitHub (Dec 16, 2021):

@mvz in this particular case, the maintainer is wrong, but they also explicitly said they don't want to debate it further so I won't sealion into that thread. Interestingly, they are a former node core developer, and my interpretation here is one node has always followed as well - as part of semver - so I'm not sure why they're taking this stance now.

@ljharb commented on GitHub (Dec 16, 2021): @mvz in this particular case, the maintainer is wrong, but they also explicitly said they don't want to debate it further so I won't sealion into that thread. Interestingly, they are a former node core developer, and my interpretation here is one node has always followed as well - as part of semver - so I'm not sure why they're taking this stance now.
Author
Owner

@jwdonahue commented on GitHub (Dec 16, 2021):

libuv/libuv #3260 does not present a compelling argument for changing anything in the spec. Publishers should not be required to continue supporting out of support platforms and should not have to take a major version bump to drop them. In this case, the publisher has made it clear they discontinue supporting OS's that are past their publisher's published EOL. They have documented the full scope of their "API" and it's up to their clients to take it or leave it.

Consumers should keep their systems up to date. Failing to do so, harms the entire ecosystem and costs the global economy hundreds of billions of dollars in lost revenue, due to malicious attacks and crashes.

And don't even try to make the argument that they are safe behind your firewalls, because hackers don't stop at the firewall and neither does security-in-depth.

@jwdonahue commented on GitHub (Dec 16, 2021): [libuv/libuv #3260](https://github.com/libuv/libuv/issues/3260) does not present a compelling argument for changing anything in the spec. Publishers should not be required to continue supporting out of support platforms and should not have to take a major version bump to drop them. In this case, the publisher has made it clear they discontinue supporting OS's that are past _their_ publisher's published EOL. They have documented the full scope of their "API" and it's up to their clients to take it or leave it. Consumers should keep their systems up to date. Failing to do so, harms the entire ecosystem and costs the global economy hundreds of billions of dollars in lost revenue, due to malicious attacks and crashes. And don't even try to make the argument that they are safe behind your firewalls, because hackers don't stop at the firewall and neither does security-in-depth.
Author
Owner

@ljharb commented on GitHub (Dec 16, 2021):

Publishers should not be required to continue supporting out of support platforms and should not have to take a major version bump to drop them

Yes, they should have to. Support status for a platform has zero relevance to "breakage" - the semver spec says nothing about support status.

@ljharb commented on GitHub (Dec 16, 2021): > Publishers should not be required to continue supporting out of support platforms and should not have to take a major version bump to drop them Yes, they should have to. Support status for a platform has zero relevance to "breakage" - the semver spec says nothing about support status.
Author
Owner

@jwdonahue commented on GitHub (Dec 17, 2021):

Nothing in the supported universe of that product was broken by the change, therefore there was no breaking change.

If we have to bump the major version of our products every time we break a few users relying on an unsupported feature, we risk having supported users get locked-in to previous versions. Lock-in is bad. Every major version bump is a barrier to automatic ingestion of bug fixes.

@jwdonahue commented on GitHub (Dec 17, 2021): Nothing in the supported universe of that product was broken by the change, therefore there was no breaking change. If we have to bump the major version of our products every time we break a few users relying on an unsupported feature, we risk having supported users get locked-in to previous versions. Lock-in is bad. Every major version bump is a barrier to automatic ingestion of bug fixes.
Author
Owner

@jwdonahue commented on GitHub (Dec 17, 2021):

@ljharb For the most part, I agree with you, but I don't think it's a Boolean choice. If someone argued that they only support P.v(LKG), I'd want to know what they are smoking. I think there's wide support for the idea that P.LatestLTS - N is far more reasonable, but there's going to be some lamenting exactly what N should be, but when P.IsEOL(v) is true, nobody should have to support it.

@jwdonahue commented on GitHub (Dec 17, 2021): @ljharb For the most part, I agree with you, but I don't think it's a Boolean choice. If someone argued that they only support `P.v(LKG)`, I'd want to know what they are smoking. I think there's wide support for the idea that `P.LatestLTS - N` is far more reasonable, but there's going to be some lamenting exactly what `N` should be, but when `P.IsEOL(v)` is true, nobody should have to support it.
Author
Owner

@ljharb commented on GitHub (Dec 17, 2021):

Nobody has to. But everyone has to do a semver-major bump when dropping it, because it breaks nonzero users.

@ljharb commented on GitHub (Dec 17, 2021): Nobody has to. But everyone has to do a semver-major bump when dropping it, because it breaks nonzero users.
Author
Owner

@jwdonahue commented on GitHub (Dec 17, 2021):

Nobody has to. But everyone has to do a semver-major bump when dropping it, because it breaks nonzero users.

So far, nobody has been able to get language committed to the spec that is anywhere near that prescriptive. There's plenty of content here that argues that we don't have to promise not to ever break anyone without a major version bump. Common sense, IMO, argues that some corner cases need not be supported. It's just a matter of how thick skinned the publisher is vs how noisy the corner cases are. That will always be the reality, no matter what the spec says.


And to use your own words:

the semver spec says nothing about support status.

@jwdonahue commented on GitHub (Dec 17, 2021): > Nobody has to. But everyone has to do a semver-major bump when dropping it, because it breaks nonzero users. So far, nobody has been able to get language committed to the spec that is anywhere near that prescriptive. There's plenty of content here that argues that we don't have to promise not to ever break anyone without a major version bump. Common sense, IMO, argues that some corner cases need not be supported. It's just a matter of how thick skinned the publisher is vs how noisy the corner cases are. That will always be the reality, no matter what the spec says. ----- And to use your own words: > the semver spec says nothing about support status.
Author
Owner

@EricMCornelius commented on GitHub (Dec 17, 2021):

Nothing in the supported universe of that product was broken by the change, therefore there was no breaking change.

Seriously incorrect. Hence all the activity on said issues. Windows 7 is still in extended support via Microsoft and used throughout huge numbers of enterprises. Eliminating the ability to build properly security-patched software for still supported OSes used in the wild is not an esoteric edge case.

That being said.

I am asking yet again: who is the actual authority on the semver spec and intent?

@EricMCornelius commented on GitHub (Dec 17, 2021): > Nothing in the supported universe of that product was broken by the change, therefore there was no breaking change. Seriously incorrect. Hence all the activity on said issues. Windows 7 is still in extended support via Microsoft and used throughout huge numbers of enterprises. Eliminating the ability to build properly security-patched software for still supported OSes used in the wild is not an esoteric edge case. That being said. I am asking yet again: who is the actual authority on the semver spec and intent?
Author
Owner

@jwdonahue commented on GitHub (Dec 17, 2021):

As I have said before, the spec is the only authority. What the spec says, is what it means. What it doesn't say is just as important. I am not saying it's right, I just spent a lot of time in this space and I know that it has a loose definition of API, and the FAQ literally states that dependencies are beyond its applicable scope.

I have also been a proponent of tightening it up a bit wrt to dependencies, at least in certain environments where it makes sense to do so.

Windows 7 is still in extended support via Microsoft and used throughout huge numbers of enterprises

Yes, and they all pay Microsoft for that support. Has anyone offered to pay the owners of libuv/libuv to continue supporting it? It is OSS, so you are welcome to fork and extend its Windows 7 support for as long you like. Apparently somebody already did that. The owner of libuv/libuv is under no obligation to do so, even if someone offers to pay them.

@jwdonahue commented on GitHub (Dec 17, 2021): As I have said before, the spec is the _only_ authority. What the spec says, is what it means. What it doesn't say is just as important. I am not saying it's right, I just spent a lot of time in this space and I know that it has a loose definition of API, and the FAQ literally states that dependencies are beyond its applicable scope. I have also been a proponent of tightening it up a bit wrt to dependencies, at least in certain environments where it makes sense to do so. > Windows 7 is still in extended support via Microsoft and used throughout huge numbers of enterprises Yes, and they _all_ pay Microsoft for that support. Has anyone offered to pay the owners of libuv/libuv to continue supporting it? It is OSS, so you are welcome to fork and extend its Windows 7 support for as long you like. Apparently somebody already did that. The owner of libuv/libuv is under no obligation to do so, even if someone offers to pay them.
Author
Owner

@Spudz76 commented on GitHub (Dec 17, 2021):

The hilarious part is I'm pretty sure the original system call still exists even in Win11, so the correct move would be to leave the API alone until the legacy system call actually is removed, at which point swap in the "new" one because it's the only way to do it anymore. Only move to new API's when forced, not when someone said something is over. Nothing is over until it's actually not working anymore. If there is some feature the new API provides that is sufficiently performance enhancing then you're maintaining both flavors until the users confirm they are no longer using whatever legacy thing and then you can remove it (monkeybars method). This way, nobody made the decision, it was forced by reality, and not a single end-user can argue with that. They (we) will however argue incessantly about a false reality decreed on high by M$ or maintainers or really anyone.

Windows is nothing but API's, this library in question is just glue with an API on each side. The API provided did not change, but its function ceased to work, because it (prematurely) changed how it uses the Windows APIs on the other side. I would consider this an API change.

And there is a perfectly fine patch but they won't merge it because it's "too many lines"... every one knows one line of work takes 40 lines when you're dealing with M$ API's because you have to call stuff twice (once for sizing, once for the real call) and other idiocy like lines being 800 chars long if you kept it on one line so then code style decrees one line must be 10 lines... so it's not that many operations and very few if any vectors for bugs (their insistence that more lines === more bugs is at a minimum childish, like refusing to eat vegetables, pure petulance if not straight up power tripping)

The rest of the ecosystem is never going to follow on to using a corrected fork because it's not the authoritative version, unless of course the fork is decreed an official spin-off "for Windows 7 use-cases" and is maintained with backports. But then you may as well just accept the patch that already works great and turns the legacy support "ON" as-needed and functions entirely just like normal on every other platform/OS. The "lines" excuse is precisely laziness combined with something between paranoia and superstition. The "lines" literally evaporate when it's "not Win7" therefore doen't really "exist"... unless someone is doing something like still using Win7 (gasp! monocles!)

@Spudz76 commented on GitHub (Dec 17, 2021): The hilarious part is I'm pretty sure the original system call still exists even in Win11, so the correct move would be to leave the API alone until the legacy system call actually is removed, at which point swap in the "new" one because it's the only way to do it anymore. Only move to new API's when forced, not when someone said something is over. Nothing is over until it's actually not working anymore. If there is some feature the new API provides that is sufficiently performance enhancing then you're maintaining both flavors until the users confirm they are no longer using whatever legacy thing and then you can remove it (monkeybars method). This way, nobody made the decision, it was forced by reality, and not a single end-user can argue with that. They (we) will however argue incessantly about a false reality decreed on high by M$ or maintainers or really anyone. Windows is nothing but API's, this library in question is just glue with an API on each side. The API provided did not change, but its function ceased to work, because it (prematurely) changed how it uses the Windows APIs on the other side. I would consider this an API change. And there is a perfectly fine patch but they won't merge it because it's "too many lines"... every one knows one line of work takes 40 lines when you're dealing with M$ API's because you have to call stuff twice (once for sizing, once for the real call) and other idiocy like lines being 800 chars long if you kept it on one line so then code style decrees one line must be 10 lines... so it's not that many *operations* and very few if any vectors for bugs (their insistence that `more lines === more bugs` is at a minimum childish, like refusing to eat vegetables, pure petulance if not straight up power tripping) The rest of the ecosystem is never going to follow on to using a corrected fork because it's not the authoritative version, unless of course the fork is decreed an official spin-off "for Windows 7 use-cases" and is maintained with backports. But then you may as well just *accept the patch that already works great* and turns the legacy support "ON" as-needed and functions entirely just like normal on every other platform/OS. The "lines" excuse is precisely laziness combined with something between paranoia and superstition. The "lines" literally evaporate when it's "not Win7" therefore doen't really "exist"... unless someone is doing something like still using Win7 (*gasp!* *monocles!*)
Author
Owner

@jwdonahue commented on GitHub (Dec 17, 2021):

@Spudz76 That all has a ring of truth to it, but it's wasted here. The owners of that library are the deciders, however arbitrary, and they do have the wording of the SemVer spec on their side. It's not the first time I've seen the EOL of an OS version being used as an excuse to simplify the code base, and it won't be the last.

@jwdonahue commented on GitHub (Dec 17, 2021): @Spudz76 That all has a ring of truth to it, but it's wasted here. The owners of that library are the deciders, however arbitrary, and they do have the wording of the SemVer spec on their side. It's not the first time I've seen the EOL of an OS version being used as an excuse to simplify the code base, and it won't be the last.
Author
Owner

@EricMCornelius commented on GitHub (Dec 17, 2021):

Yes, and they all pay Microsoft for that support. Has anyone offered to pay the owners of libuv/libuv to continue supporting it? It is OSS, so you are welcome to fork and extend its Windows 7 support for as long you like. Apparently somebody already did that. The owner of libuv/libuv is under no obligation to do so, even if someone offers to pay them.

Literally came here to point out the fact that the intention of the spec is ambiguous and used as an excuse for poor engineering practices and bikeshedding, and get treated to a masterclass in bikeshedding.

So I'll reiterate again: who is the formal maintainer of the spec who can authoritatively speak to the intention of where semantic versioning actually means anything about guarantees around breakage w.r.t minor and patch versions, and whether an API contract should be considered broken when it breaks existing usage or not?

This is the question. I've provided a concrete example where there is a lack of consensus on interpretation in a major project. Ergo ambiguity clearly exists and the spec warrants clarification of intent.

And if that intent Is that major version upgrades are not actually expected when breaking existing usage, so be it, but acknowledge that fact up front so that communities can migrate to more responsible versioning schemes.

@EricMCornelius commented on GitHub (Dec 17, 2021): > Yes, and they all pay Microsoft for that support. Has anyone offered to pay the owners of libuv/libuv to continue supporting it? It is OSS, so you are welcome to fork and extend its Windows 7 support for as long you like. Apparently somebody already did that. The owner of libuv/libuv is under no obligation to do so, even if someone offers to pay them. Literally came here to point out the fact that the intention of the spec is ambiguous and used as an excuse for poor engineering practices and bikeshedding, and get treated to a masterclass in bikeshedding. So I'll reiterate again: who is the formal maintainer of the spec who can authoritatively speak to the intention of where *semantic versioning* actually means anything about guarantees around breakage w.r.t minor and patch versions, and whether an API contract should be considered broken when it *breaks* existing usage or not? This is the question. I've provided a concrete example where there is a lack of consensus on interpretation in a major project. Ergo ambiguity clearly exists and the spec warrants clarification of intent. And if that intent Is that major version upgrades are *not* actually expected when breaking existing usage, so be it, but acknowledge that fact up front so that communities can migrate to more responsible versioning schemes.
Author
Owner

@jwdonahue commented on GitHub (Dec 17, 2021):

@EricMCornelius

who is the formal maintainer of the spec

Read the CONTRIBUTING.md file.

@jwdonahue commented on GitHub (Dec 17, 2021): @EricMCornelius > who is the formal maintainer of the spec Read the [CONTRIBUTING.md file](https://github.com/semver/semver/blob/master/CONTRIBUTING.md).
Author
Owner

@jwdonahue commented on GitHub (Dec 17, 2021):

@EricMCornelius

and used as an excuse for poor engineering practices

I call it wise engineering management, but there's always a few who insist that their specific corner case is worthy of continued support. Sometimes, you have to respond to it, some times you don't.

@jwdonahue commented on GitHub (Dec 17, 2021): @EricMCornelius > and used as an excuse for poor engineering practices I call it wise engineering management, but there's always a few who insist that their specific corner case is worthy of continued support. Sometimes, you have to respond to it, some times you don't.
Author
Owner

@FichteFoll commented on GitHub (Dec 19, 2021):

The entire discussion, like any other similar discussion, solely concerns the definition of the "public API" or a tool or library, which is generally left for the authors or maintainers of that tool or library to define, because SemVer aspires to provide a largely generic approach that can be applied to many facets of software. In general, you are most likely to understand the scope of a public API in say a C header file, where the API is directly defined, but that may not be everything. Documentation is also part of the public API, including things such as deprecation notices, platform support, or other usage restrictions that a simple function signature cannot convey.

In that sense, I entirely agree with @jwdonahue in that if the library claims to only support operating systems that are supported by their vendors, then breaking your software for such an unsupported OS is not a breaking change since you didn't support it in the first place.
If such a statement was missing and the documentation would lead one to believe that such an OS was supported, then I agree that the SemVer spec is violated with a minor-level release and should have been major.

That's pretty much it, as far as the spec is concerned, and I highly doubt that will ever change. Any more specific claims regarding a public API can be made on top of SemVer, where SemVer just defines the common ground. Thus, each such decision must consider the context it is made in, which includes the kind of software, the kind of API it provides, the documentation that is provided, the target audience, etc., which is such a wild field that SemVer cannot possibly claim to address in all its facets.


For the particular case of libuv, the points you are making for a major and breaking change are reasonable and one half of the discussion. The other is that a major version release comes with a cost for all its users, because, per the SemVer contract, each user needs to evaluate whether they are affected by the break, which can take an unknown amount of effort. As such, a major version increase should only be done if the change is actually breaking, where we now enter the territory of whether it was a breaking change as per the "public API" or not. I won't go into more into detail because I haven't studied the documentation of libuv and don't intend to do so either, since I don't have any authority on the decision, nor do I particularly care personally. However, I want to iterate again that as far as I'm concerned, given the documentation was proper, there is no violation of the SemVer spec.

@FichteFoll commented on GitHub (Dec 19, 2021): The entire discussion, like any other similar discussion, solely concerns the definition of the "public API" or a tool or library, which is generally left for the authors or maintainers of that tool or library to define, because SemVer aspires to provide a largely generic approach that can be applied to many facets of software. In general, you are most likely to understand the scope of a public API in say a C header file, where the API is directly defined, but that may not be everything. Documentation is also part of the public API, including things such as deprecation notices, platform support, or other usage restrictions that a simple function signature cannot convey. In that sense, I entirely agree with @jwdonahue in that if the library claims to only support operating systems that are supported by their vendors, then breaking your software for such an unsupported OS is not a breaking change since you didn't support it in the first place. If such a statement was missing and the documentation would lead one to believe that such an OS was supported, then I agree that the SemVer spec is violated with a minor-level release and should have been major. That's pretty much it, as far as the spec is concerned, and I highly doubt that will ever change. Any more specific claims regarding a public API can be made on top of SemVer, where SemVer just defines the common ground. Thus, each such decision must consider the context it is made in, which includes the kind of software, the kind of API it provides, the documentation that is provided, the target audience, etc., which is such a wild field that SemVer cannot possibly claim to address in all its facets. --- For the particular case of libuv, the points you are making for a major and breaking change are reasonable and one half of the discussion. The other is that a major version release comes with a cost for all its users, because, per the SemVer contract, each user needs to evaluate whether they are affected by the break, which can take an unknown amount of effort. As such, a major version increase should only be done if the change is actually breaking, where we now enter the territory of whether it was a breaking change as per the "public API" or not. I won't go into more into detail because I haven't studied the documentation of libuv and don't intend to do so either, since I don't have any authority on the decision, nor do I particularly care personally. However, I want to iterate again that as far as I'm concerned, given the documentation was proper, there is no violation of the SemVer spec.
Author
Owner

@pboling commented on GitHub (May 2, 2022):

I have always interpreted the SemVer spec as requiring a major version bump in case of dropping support for a platform. If a tool works on my platform, and I install a patch, I expect it to work.

I will always be surprised if a project stops working when the only delta is a patch update, and I'll internally consider this a bug, even if the project attempts an alternate framing. Therefore platform support can't be dropped in a patch, and it follows, can't be dropped in a minor update either, because it is obviously and implicitly, a breaking change.

This is a problem in Ruby, becuase the maintainer of rubocop (@bbatsov) inteprets the SemVer spec differently, (the narrow API version) and drops Ruby version support in minor updates.

Apparently his interpretation is common enough to warrant repeated hashing of this issue, and though I've been a supporter of SemVer for many years, if the spec isn't clear enough to put this discussion to rest it seems flawed.

I wrote about my isssues here:
https://dev.to/pboling/rubocop-ruby-matrix-gems-nj

@pboling commented on GitHub (May 2, 2022): I have always interpreted the SemVer spec as requiring a major version bump in case of dropping support for a platform. If a tool works on my platform, and I install a patch, I expect it to work. I will always be surprised if a project stops working when the only delta is a patch update, and I'll internally consider this a bug, even if the project attempts an alternate framing. Therefore platform support can't be dropped in a patch, and it follows, can't be dropped in a minor update either, because it is obviously and implicitly, a **breaking** change. This is a problem in Ruby, becuase the maintainer of `rubocop` (@bbatsov) inteprets the SemVer spec differently, (the narrow API version) and drops Ruby version support in minor updates. Apparently his interpretation is common enough to warrant repeated hashing of this issue, and though I've been a supporter of SemVer for many years, if the spec isn't clear enough to put this discussion to rest it seems flawed. I wrote about my isssues here: https://dev.to/pboling/rubocop-ruby-matrix-gems-nj
Author
Owner

@mvz commented on GitHub (May 3, 2022):

@pboling the rubocop case is a little different because dropping a supported TargetRubyVersion is not caught by the installer, and usually people don't run rubocop on the lowest Ruby version they want to support with their gem.

So I'm fully in agreement with you that dropping a TargetRubyVersion (which is a feature and not a dependency) is a breaking change and should be accompanied by a major version bump.

@mvz commented on GitHub (May 3, 2022): @pboling the `rubocop` case is a little different because dropping a supported TargetRubyVersion is not caught by the installer, and usually people don't run rubocop on the lowest Ruby version they want to support with their gem. So I'm fully in agreement with you that dropping a TargetRubyVersion (which is a feature and not a dependency) is a breaking change and should be accompanied by a major version bump.
Author
Owner

@pboling commented on GitHub (May 3, 2022):

Rubocop has never done a major bump to accommodate dropping a Ruby, and 1.29.0 will drop Ruby 2.5, both from the syntax target (TargetRubyVersion) and from the minimum install supported Ruby, if current plans materialize unchanged.

However, I think both types of version support being dropped, from installing, to syntax parsing with the target setting, require a major version bump according to SemVer, and that appears to be what this discussion is about.

The maintainer doesn't see drops as changing the API in a breaking way, because it is a gem with a "real" API in the classic sense.

But almost no end users use that API, they all use rubocop via package managers, and command line. The current release strategy breaks the intended SemVer-based utility of ~> 1.0.

As has been made clear in previous comments, the platform is part of the interface of a tool. The fact that deviance from proper SemVer is somewhat mitigated by the required_ruby_version setting from the gemspec is irrelevant.

The fact that SemVer 2.0 is defined in a way that tramples the principle of least surprise is the issue.

@pboling commented on GitHub (May 3, 2022): Rubocop has never done a major bump to accommodate dropping a Ruby, and 1.29.0 will drop Ruby 2.5, both from the syntax target (`TargetRubyVersion`) and from the minimum install supported Ruby, if current plans materialize unchanged. However, I think both types of version support being dropped, from installing, to syntax parsing with the target setting, require a major version bump according to SemVer, and that appears to be what this discussion is about. The maintainer doesn't see drops as changing the API in a breaking way, because it is a gem with a "real" API in the classic sense. But almost no end users use that API, they all use rubocop via package managers, and command line. The current release strategy breaks the intended SemVer-based utility of `~> 1.0`. As has been made clear in previous comments, the platform is part of the interface of a tool. The fact that deviance from proper SemVer is somewhat mitigated by the `required_ruby_version` setting from the gemspec is irrelevant. The fact that SemVer 2.0 is defined in a way that tramples the principle of least surprise is the issue.
Author
Owner

@mvz commented on GitHub (May 3, 2022):

Yes, I understand what the discussion in this issue is about.

I was just commenting on the fact that dropping a TargetRubyVersion is a problem orthogonal to your position on dropping support for a platform a gem runs on.

@mvz commented on GitHub (May 3, 2022): Yes, I understand what the discussion in this issue is about. I was just commenting on the fact that dropping a `TargetRubyVersion` is a problem orthogonal to your position on dropping support for a platform a gem runs on.
Author
Owner

@bbatsov commented on GitHub (May 3, 2022):

Yep, also notice that we have an extended window for supporting Rubies that reached EOL at the runtime level - we'll now be dropping support for a Ruby release that reached EOL over 1 year ago. I totally agree that changes to TargetRubyVersion are a breaking change, but the runtime compatibility stuff is definitely a gray area, especially when this is unlikely to affect anyone in practice (given how old the Ruby 2.5 is).

I do agree, however, it'd be nice if SemVer's spec was clear on this issue.

@bbatsov commented on GitHub (May 3, 2022): Yep, also notice that we have an extended window for supporting Rubies that reached EOL at the runtime level - we'll now be dropping support for a Ruby release that reached EOL over 1 year ago. I totally agree that changes to `TargetRubyVersion` are a breaking change, but the runtime compatibility stuff is definitely a gray area, especially when this is unlikely to affect anyone in practice (given how old the Ruby 2.5 is). I do agree, however, it'd be nice if SemVer's spec was clear on this issue.
Author
Owner

@pboling commented on GitHub (May 3, 2022):

this is unlikely to affect anyone in practice (given how old the Ruby 2.5 is).

I disagree. Many gem authors who support older rubies in their projects. Rubocop is heavily used by FLOSS gems that have widely varying scopes of support, for example, one of the most popular gems, rspec, still supports Ruby 1.8.7.

If 2.5 is dropped outside a major version bump, I'll have to make a mental note of "remember to stop before the arbitrary and meaningless number 1.29!" when updating many gems. 1.29 would effectively be a "magic number".

Granted I just spent dozens of hours wrapping this problem in a SemVer (as I interpret it) solution, so I can avoid rubocop versioning altogether... https://GitLab.com/rubocop-lts

To put it simply:

it is precisely because neither Ruby, nor Rubocop, release patterns dictate when my projects drop support for ancient-but-still functional platforms, that I am invested in this.

My support efforts become harder when platforms are dropped without a major bump.

This is something which, until today, I thought was settled, accepting that various projects didn't follow SemVer for particular reasons.

EOL for a still-functional dependency should not be relevant to SemVer, IMO.

@pboling commented on GitHub (May 3, 2022): > this is unlikely to affect anyone in practice (given how old the Ruby 2.5 is). I disagree. Many gem authors who support older rubies in their projects. Rubocop is heavily used by FLOSS gems that have widely varying scopes of support, for example, one of the most popular gems, `rspec`, still supports Ruby 1.8.7. If 2.5 is dropped outside a major version bump, I'll have to make a mental note of "remember to stop before the arbitrary and meaningless number 1.29!" when updating many gems. `1.29` would effectively be a ["magic number"](https://en.wikipedia.org/wiki/Magic_number_(programming)). Granted I just spent dozens of hours wrapping this problem in a SemVer (as I interpret it) solution, so I can avoid rubocop versioning altogether... https://GitLab.com/rubocop-lts To put it simply: > it is precisely because neither Ruby, nor Rubocop, release patterns dictate when my projects drop support for ancient-but-still functional platforms, that I am invested in this. My support efforts become harder when platforms are dropped without a major bump. This is something which, until today, I thought was settled, accepting that various projects didn't follow SemVer for particular reasons. EOL for a still-functional dependency should not be relevant to SemVer, IMO.
Author
Owner

@igorpupkinable commented on GitHub (May 3, 2022):

I did not expect so much ambiguity around this. At the end of the day all of us change some data in some container (folder/file/repo/HDD/cloud/etc.). The tiniest data piece is a bit. So it can really go down to a simple question: will a change of one bit break any possible variation of a consumer out there?

  • Yes, it can > Breaking change (MAJOR).
  • No, it cannot > MINOR or PATCH.

The last thing consumer should worry about is where this changed bit of data belongs to, either manifest file, code file, image file, documentation file, README, .gitignore, generated dynamically, etc. We simply should not care as we are versioning deliverable in some format via some channel.

It seems too much effort is made to define what API is, where focus should be shifted to understand that something has changed and if a change in something can break consumers.

@igorpupkinable commented on GitHub (May 3, 2022): I did not expect so much ambiguity around this. At the end of the day all of us change some data in some container (folder/file/repo/HDD/cloud/etc.). The tiniest data piece is a bit. So it can really go down to a simple question: will a change of one bit break any possible variation of a consumer out there? - Yes, it can > Breaking change (MAJOR). - No, it cannot > MINOR or PATCH. The last thing consumer should worry about is where this changed bit of data belongs to, either manifest file, code file, image file, documentation file, README, .gitignore, generated dynamically, etc. We simply should not care as we are versioning _deliverable_ in some format via some channel. It seems too much effort is made to define what _API_ is, where focus should be shifted to understand that _something has changed_ and if **a change in something can break consumers**.
Author
Owner

@mvz commented on GitHub (May 12, 2022):

So it can really go down to a simple question: will a change of one bit break any possible variation of a consumer out there?

No matter what your opinion about platform version support is, this is emphatically not what SemVer is about. Fixing a bug might break a consumer.

@mvz commented on GitHub (May 12, 2022): > So it can really go down to a simple question: will a change of one bit break any possible variation of a consumer out there? No matter what your opinion about platform version support is, this is emphatically not what SemVer is about. Fixing a bug might break a consumer.
Author
Owner

@igorpupkinable commented on GitHub (May 23, 2022):

@mvz

... version numbers ... convey ... what has been modified ...
https://semver.org/

So it is exactly about that. Changing anything in the text below (or equivalent) is a change, so it is author's responsibility to "convey what has been modified" and how it can affect consumers.

"engines": {
    "node": ">=14.15"
  },
@igorpupkinable commented on GitHub (May 23, 2022): @mvz > ... version numbers ... convey ... what has been modified ... https://semver.org/ So it is exactly about that. Changing anything in the text below (or equivalent) is a change, so it is author's responsibility to "convey what has been modified" and how it can affect consumers. ``` "engines": { "node": ">=14.15" }, ```
Author
Owner

@mvz commented on GitHub (May 23, 2022):

@igorpupkinable what is your point? We're discussing breaking changes, not what has been modified in general.

@mvz commented on GitHub (May 23, 2022): @igorpupkinable what is your point? We're discussing breaking changes, not what has been modified in general.
Author
Owner

@igorpupkinable commented on GitHub (Jul 15, 2022):

@igorpupkinable what is your point? We're discussing breaking changes, not what has been modified in general.

Platform requirements change is a breaking change if you narrowing or restricting it.

@igorpupkinable commented on GitHub (Jul 15, 2022): > @igorpupkinable what is your point? We're discussing breaking changes, not what has been modified in general. Platform requirements change is a breaking change if you narrowing or restricting it.
Author
Owner

@mvz commented on GitHub (Jul 15, 2022):

@igorpupkinable you're ignoring the context of my comment.

@mvz commented on GitHub (Jul 15, 2022): @igorpupkinable you're ignoring the context of my comment.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/semver#487