[GH-ISSUE #503] Is there any guidance/advice on multi-component APIs? #6362

Closed
opened 2026-06-17 05:06:55 -05:00 by GiteaMirror · 5 comments
Owner

Originally created by @rivenwyrm on GitHub (Feb 22, 2019).
Original GitHub issue: https://github.com/semver/semver/issues/503

I'm working on a container with multiple components, several of which have public APIs: The command line arguments, a gRPC API and some configuration files. So far we've considered them all to be separate APIs and we've also given the entire container a V# as well. In an attempt to communicate a bit more clearly and consolidate status, we want to use that container V# in a 'semantic-versioning' way.

However, this leaves us with a quandary:
API_first_component 1.0.0
API_second_component 1.0.0
API_third_component 1.0.0
container 1.0.0

now API_first_component -> 1.1
okay, easy, container follows it to 1.1
now API_second_component -> 1.1
Uh... woops. Container goes from 1.1 to... 1.1?

Clearly this doesn't quite work. There seem to be only two solutions that we can see:
A) Don't use semantic versioning for the overall container V#.
B) Have each component use the overall container V# as the version to increment from. This solves the issue but raises a point of confusion. Above, API_second_component would increment from 1.0.0 to 1.2.0, and the container would follow it to 1.2.0, but we just jumped over 1.1 completely.

Is it just totally incorrect and wrong to attempt to use semantic versioning on something which is 'composed' like this? Or is there some advice/guidance on how to do it? Is option B simply the correct method? Or is the correct thing really option (C) have every composed piece use the same V# since it's all 'one big API'?

Originally created by @rivenwyrm on GitHub (Feb 22, 2019). Original GitHub issue: https://github.com/semver/semver/issues/503 I'm working on a container with multiple components, several of which have public APIs: The command line arguments, a gRPC API and some configuration files. So far we've considered them all to be separate APIs and we've also given the entire container a V# as well. In an attempt to communicate a bit more clearly and consolidate status, we want to use that container V# in a 'semantic-versioning' way. However, this leaves us with a quandary: API_first_component 1.0.0 API_second_component 1.0.0 API_third_component 1.0.0 container 1.0.0 now API_first_component -> 1.1 okay, easy, container follows it to 1.1 now API_second_component -> 1.1 Uh... woops. Container goes from 1.1 to... 1.1? Clearly this doesn't quite work. There seem to be only two solutions that we can see: A) Don't use semantic versioning for the overall container V#. B) Have each component use the overall container V# as the version to increment from. This solves the issue but raises a point of confusion. Above, API_second_component would increment from 1.0.0 to 1.2.0, and the container would follow it to 1.2.0, but we just jumped over 1.1 completely. Is it just totally incorrect and wrong to attempt to use semantic versioning on something which is 'composed' like this? Or is there some advice/guidance on how to do it? Is option B simply the correct method? Or is the correct thing really option (C) have every composed piece use the same V# since it's all 'one big API'?
Author
Owner

@ljharb commented on GitHub (Feb 22, 2019):

In npm, this is addressed with peer dependencies - and it liberates you from needing to couple version numbers (which adds noise to the info otherwise conveyed by them).

edit: i misunderstood the question; you're talking about a single package that contains multiple components, each which might have an implicit semver version. i was presuming that each component would be published with its own package.

<!-- gh-comment-id:466541556 --> @ljharb commented on GitHub (Feb 22, 2019): ~~In npm, this is addressed with peer dependencies - and it liberates you from needing to couple version numbers (which adds noise to the info otherwise conveyed by them).~~ edit: i misunderstood the question; you're talking about a single package that contains multiple components, each which might have an implicit semver version. i was presuming that each component would be published with its own package.
Author
Owner

@rivenwyrm commented on GitHub (Feb 22, 2019):

In npm, this is addressed with peer dependencies - and it liberates you from needing to couple version numbers (which adds noise to the info otherwise conveyed by them).

I don't think peerDependencies were designed to solve quite this same problem, though it's moderately similar and at least gives food for thought.

So in this paradigm, we'd:
A) Ensure that each individual component has:
i) an independent version number
ii) a clearly defined and easily accessed/noticed peer (or in our case host) dependency list
B) Have the composed container version number simply move up one major or minor increment each time a composed API V# changed, ignoring whatever the specific numbers were

Is that right? So the various V#s are no longer in strict synchronization and the container V# doesn't really indicate which part of the system most recently changed, but it does tell you that 'something' changed.

<!-- gh-comment-id:466557002 --> @rivenwyrm commented on GitHub (Feb 22, 2019): > In npm, this is addressed with peer dependencies - and it liberates you from needing to couple version numbers (which adds noise to the info otherwise conveyed by them). I don't think peerDependencies were designed to solve quite this same problem, though it's moderately similar and at least gives food for thought. So in this paradigm, we'd: A) Ensure that each individual component has: i) an independent version number ii) a clearly defined and easily accessed/noticed peer (or in our case host) dependency list B) Have the composed container version number simply move up one major or minor increment each time a composed API V# changed, ignoring whatever the specific numbers were Is that right? So the various V#s are no longer in strict synchronization and the container V# doesn't really indicate which part of the system most recently changed, but it does tell you that 'something' changed.
Author
Owner

@ljharb commented on GitHub (Feb 22, 2019):

A given package's version number changing should be sufficient indicator that that package has changed, should it not?

<!-- gh-comment-id:466581546 --> @ljharb commented on GitHub (Feb 22, 2019): A given package's version number changing should be sufficient indicator that that package has changed, should it not?
Author
Owner

@jwdonahue commented on GitHub (Feb 24, 2019):

The package version should bump the most significant of the triple that was bumped among the set of versioned components within. If you introduce a breaking change on any one of the API's within a package, that package version should reflect that it contains a breaking change.

And yes, it does make sense to use SemVer on collections of API's. Such package version numbers tend to eventually race ahead of the individual API versions. Using your initial starting conditions, the following history could result:

API_third_component -> 1.1
Container -> 1.1
API_second_component -> 2.0.0
API_third_component -> 1.1.1
Container -> 2.0.0
API_third_component -> 2.0.0
Container -> 3.0.0

You simply have to be conscious of what it is you are versioning and apply the rules to that. For a collection of API's, you're versioning its package, not the API's themselves. The contained API's may or may not have their own independent versioning scheme.

<!-- gh-comment-id:466798952 --> @jwdonahue commented on GitHub (Feb 24, 2019): The package version should bump the most significant of the triple that was bumped among the set of versioned components within. If you introduce a breaking change on any one of the API's within a package, that package version should reflect that it contains a breaking change. And yes, it does make sense to use SemVer on collections of API's. Such package version numbers tend to eventually race ahead of the individual API versions. Using your initial starting conditions, the following history could result: API_third_component -> 1.1 Container -> 1.1 API_second_component -> 2.0.0 API_third_component -> 1.1.1 Container -> 2.0.0 API_third_component -> 2.0.0 Container -> 3.0.0 You simply have to be conscious of what it is you are versioning and apply the rules to that. For a collection of API's, you're versioning its package, not the API's themselves. The contained API's may or may not have their own independent versioning scheme.
Author
Owner

@rivenwyrm commented on GitHub (Feb 26, 2019):

The package version should bump the most significant of the triple that was bumped among the set of versioned components within. If you introduce a breaking change on any one of the API's within a package, that package version should reflect that it contains a breaking change.

And yes, it does make sense to use SemVer on collections of API's. Such package version numbers tend to eventually race ahead of the individual API versions.

Thank you, you've directly addressed the exact question we were having and confirmed what we figured was the correct approach. Appreciated.

I don't know if it's worthwhile to add anything wrt to this into the semver spec but I'll close this issue for now in either case.

<!-- gh-comment-id:467240304 --> @rivenwyrm commented on GitHub (Feb 26, 2019): > The package version should bump the most significant of the triple that was bumped among the set of versioned components within. If you introduce a breaking change on any one of the API's within a package, that package version should reflect that it contains a breaking change. > > And yes, it does make sense to use SemVer on collections of API's. Such package version numbers tend to eventually race ahead of the individual API versions. Thank you, you've directly addressed the exact question we were having and confirmed what we figured was the correct approach. Appreciated. I don't know if it's worthwhile to add anything wrt to this into the semver spec but I'll close this issue for now in either case.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/semver#6362