Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When to increase version of a pure consumer? #864

Open
joerg-wille opened this issue Jul 28, 2022 · 3 comments
Open

When to increase version of a pure consumer? #864

joerg-wille opened this issue Jul 28, 2022 · 3 comments

Comments

@joerg-wille
Copy link

I understand all the rules of Semantic Versioning that forces changes of versions for API providers. But how to do versioning for code that only consumes API's? Will it always stay on 1.x.y?
Assume you have a client that consumes Lib A. When Lib A made a backward-incompatible change to its API then its major version increased. When the consumer reflects these changes, should its major or its minor version be updated? As I understand Semantic Versioning, the minor version would be updated, since there is no breaking API change in the consumer package. This would mean my consumer version would always stay on version 1.x.y, since the consumer never has a breaking API change.
In a project I saw that they updated the consumer's major version to reflect the incompatible API change in Lib A. Their explanation was that this makes it easy to see that a consumer is only compatible to Lib A when they have the same major version. This works as long as the consumer only consumes only Lib A but not if the consumer depends on an additional Lib B.
So, what is the suggested way to version a consumer only package?

@ljharb
Copy link
Contributor

ljharb commented Jul 28, 2022

Why would code that is not itself consumed by others have a version at all?

@jwdonahue
Copy link
Contributor

... But how to do versioning for code that only consumes API's? Will it always stay on 1.x.y?

That first question is mildly confusing. But reading further, I think your root query here is in regard to transitive dependencies, which have been discussed in-depth in earlier threads.

There's basically two schools of thought here. Those that take the spec literally, and those that try to read a bit more between the lines.

Scenario:

  • Given product P with version x.y.z.
  • P depends on LibA.
  • P takes a breaking change from the LibA feed (Ex: 1.y.z => 2.y.z).
  • No changes to P's API.

Literalist interpretation of Clause 8:

No API change, therefore P is not required to bump its major version.

Pragmatist's interpretation, combining Clause 8 with some comments in the introduction and context based common sense:

P MUST publish a major version bump IF upstream consumers build or run-times would be broken.

This interpretation is based on a liberal definition of what an API is. The spec is bent around API's but the tools that implement the spec are generally packaging tools, where the version is not applied to source or binary interfaces, rather, it is applied to a collection of source and/or binary interfaces and implementations. While the introduction to the spec gives the publisher carte blanc discretion to define what API means wrt to their product, that's not a scalable approach in most modern environments.

The pragmatist's approach is more nuanced and dependent on certain properties of the build and run-time environments. There are some tool chains and environments where P => LibA is not visible to upstream consumers in either the build or run-time environments. There are cases where it might affect build time but not run-time, or vice versa, and there are economic and other pragmatic concerns. If you know you're going to break <1% of your customer base AND you're willing to hear them scream AND the LibA update is a critical security patch, you just might want to forgo the major version bump to speed up ingestion of your latest release.

Some will argue that any down-stream breaking changes must be reflected to upstream consumers in all situations (javascript + NPM types mostly). This is reasonably good advice for the many, who are looking for a simple rule that always works, but it can lead to version lock when many upstream consumers block all ingestion of breaking changes, due to not having time to evaluate the impacts of those changes on their products.

See also:

@jwdonahue
Copy link
Contributor

jwdonahue commented Aug 14, 2022

Related:

#14 how to handle transitive dependencies.
#337 Public dependencies should be transitive.
#341 Transitive dependencies are part of the public API and thus should increment version accordingly.
#445 If a bug on which dependent software might rely is patched, is it a major or a patch bump?
#456 Change wording with regards to breaking change in dependency.
#468 #468.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants
@ljharb @jwdonahue @joerg-wille and others