[GH-ISSUE #95] you shouldn't allow a build version without a pre-release version #6057

Closed
opened 2026-06-17 04:28:29 -05:00 by GiteaMirror · 18 comments
Owner

Originally created by @dtudury on GitHub (May 5, 2013).
Original GitHub issue: https://github.com/semver/semver/issues/95

my understanding is that the versions progress from inception to release goes something like this (it's totally possible I'm missing something):

  • 1.0.0-alpha _new product spec'd and ready for dev_
  • 1.0.0-alpha+build.1 _first few builds towards alpha_
  • 1.0.0-alpha+build.2
  • ...
  • 1.0.0-alpha.1 _based on new feedback alpha target is changed_
  • 1.0.0-alpha.1+build.1
  • 1.0.0-alpha.1+build.2
  • ...
  • 1.0.0-beta.5+build.724
  • ...
  • 1.0.0-rc3.27+build.231
  • ...
  • 1.0.0 _release_

pre-release versions come before non-pre-release versions and build versions come after non-build versions. I guess my question is: why would you ever use a build version without a pre-release version? the spec seems to allow it.

my reading of the spec says 1.0.0 is before 1.0.0+build.1. But what could 1.0.0+build.1 possibly be? is it a release? if it is and it's not the same as 1.0.0 then it must be updated to at least 1.0.1. if it's not released then it's a pre-release and should be labeled as such. without mandating a new pre-release version for build versions you're implying that 1.0.0+build.1 is effectively 1.0.1-pre-alpha+build.1 but people will treat them like patches. people already do: 1.0.0-1 comes after 1.0.0 in joyent/nodejitsu-land (and I followed one of their links to find the spec)

in one line: you are always working towards the next release

Originally created by @dtudury on GitHub (May 5, 2013). Original GitHub issue: https://github.com/semver/semver/issues/95 my understanding is that the versions progress from inception to release goes something like this (it's totally possible I'm missing something): - 1.0.0-alpha **_new product spec'd and ready for dev**_ - 1.0.0-alpha+build.1 **_first few builds towards alpha**_ - 1.0.0-alpha+build.2 - ... - 1.0.0-alpha.1 **_based on new feedback alpha target is changed**_ - 1.0.0-alpha.1+build.1 - 1.0.0-alpha.1+build.2 - ... - 1.0.0-beta.5+build.724 - ... - 1.0.0-rc3.27+build.231 - ... - 1.0.0 **_release**_ pre-release versions come before non-pre-release versions and build versions come after non-build versions. I guess my question is: why would you ever use a build version without a pre-release version? the spec seems to allow it. my reading of the spec says 1.0.0 is before 1.0.0+build.1. But what could 1.0.0+build.1 possibly be? is it a release? if it is and it's not the same as 1.0.0 then it must be updated to at least 1.0.1. if it's not released then it's a pre-release and should be labeled as such. without mandating a new pre-release version for build versions you're implying that 1.0.0+build.1 is effectively 1.0.1-pre-alpha+build.1 but people will treat them like patches. people already do: 1.0.0-1 comes after 1.0.0 in joyent/nodejitsu-land (and I followed one of their links to find the spec) in one line: **you are always working towards the next release**
Author
Owner

@colin-haber commented on GitHub (May 5, 2013):

I think you're misunderstanding the concept of build metadata. It's not as much a version like the rest of the SemVer string, nor is it usually going to be made for human eyes. The build ID is intended (though not required) to be generated by build scripts or programs, like CI systems, for mostly internal reference.

So, think more like:

  • 1.0.0-alpha.1
  • 1.0.0-alpha.2
  • 1.0.0-alpha.3+build.2013-02-01.1 //CI system introduced to workflow here
  • 1.0.0-alpha.4+build.2013-02-14.4
  • 1.0.0-beta.1+build.2013-03-04.12
  • 1.0.0-beta.2+build.2013-03-14.2
  • 1.0.0-rc.1+build.2013-03-29.16
  • 1.0.0+build.2013-04-03.1 //First public release
  • 1.0.0+build.2013-04-03.3 //An internal build, never to be released to the public
  • 1.0.1+build.2013-04-03.4 //Publicly released patch
  • et.c.

Different build meta schemes will use different things, but my main point is that the build metadata allows automatically built projects to have a permanent reference to them by SemVer, as well as by whatever other methods are provided.

<!-- gh-comment-id:17461273 --> @colin-haber commented on GitHub (May 5, 2013): I think you're misunderstanding the concept of build metadata. It's not as much a version like the rest of the SemVer string, nor is it usually going to be made for human eyes. The build ID is intended (though not required) to be generated by build scripts or programs, like CI systems, for mostly internal reference. So, think more like: - 1.0.0-alpha.1 - 1.0.0-alpha.2 - 1.0.0-alpha.3+build.2013-02-01.1 //CI system introduced to workflow here - 1.0.0-alpha.4+build.2013-02-14.4 - 1.0.0-beta.1+build.2013-03-04.12 - 1.0.0-beta.2+build.2013-03-14.2 - 1.0.0-rc.1+build.2013-03-29.16 - 1.0.0+build.2013-04-03.1 //First public release - _1.0.0+build.2013-04-03.3 //An internal build, never to be released to the public_ - 1.0.1+build.2013-04-03.4 //Publicly released patch - _et.c._ Different build meta schemes will use different things, but my main point is that the _build metadata allows automatically built projects to have a permanent reference to them by SemVer_, as well as by whatever other methods are provided.
Author
Owner

@dtudury commented on GitHub (May 5, 2013):

Thanks for the quick reply! Regarding your example:

  • 1.0.0+build.2013-04-03.1
  • 1.0.0+build.2013-04-03.3

I don't understand how that would have happened. they were both called 1.0.0-rc.1+build.2013-04-03.x when worked on internally. then one got promoted to release at which point it became 1.0.0+build.2013-04-03.x. why would a second one get promoted to the same release? either it's the same or it's different.

maybe the spec should say build versions on non-pre-release builds are informational only and also that they must be unique? This doesn't prohibit automatic generation. It prohibits people breaking the intention of the spec.

<!-- gh-comment-id:17461620 --> @dtudury commented on GitHub (May 5, 2013): Thanks for the quick reply! Regarding your example: - 1.0.0+build.2013-04-03.1 - 1.0.0+build.2013-04-03.3 I don't understand how that would have happened. they were both called 1.0.0-rc.1+build.2013-04-03.x when worked on internally. then one got promoted to release at which point it became 1.0.0+build.2013-04-03.x. why would a second one get promoted to the same release? either it's the same or it's different. maybe the spec should say build versions on non-pre-release builds are informational only and also that they _must_ be unique? This doesn't prohibit automatic generation. It prohibits people breaking the intention of the spec.
Author
Owner

@dtudury commented on GitHub (May 6, 2013):

The issue is clear in my head but when I try to explain it it seems to become unnecessarily weird and complicated.

Engineers only create pre-release versions. When a pre-release is deemed worthy, the pre-release tag is dropped and it becomes the release. This can only happen once for each x.y.z version.

<!-- gh-comment-id:17465661 --> @dtudury commented on GitHub (May 6, 2013): The issue is clear in my head but when I try to explain it it seems to become unnecessarily weird and complicated. Engineers only create pre-release versions. When a pre-release is deemed worthy, the pre-release tag is dropped and it becomes the release. This can only happen once for each x.y.z version.
Author
Owner

@Tieske commented on GitHub (May 6, 2013):

Engineers only create pre-release versions.

maybe some, maybe many, but certainly not all. Current state of build meta data in semver makes it as flexible as possible, for everyone to use at their own liking. There is no use in restricting it.

<!-- gh-comment-id:17468652 --> @Tieske commented on GitHub (May 6, 2013): > Engineers only create pre-release versions. maybe some, maybe many, but certainly not all. Current state of build meta data in semver makes it as flexible as possible, for everyone to use at their own liking. There is no use in restricting it.
Author
Owner

@dtudury commented on GitHub (May 6, 2013):

what I mean is it's pre-release until it's released (and if someone's working on it, it hasn't been released). once it's released no other release can ever share the same version. if 1.2.3+4 is different than 1.2.3+5, then two releases share the same x.y.z version. that makes the +r effectively a second patch number.

actually, I guess that works... for release version: x.y.z+r the patch version is "z+r". is that what I was missing?

<!-- gh-comment-id:17469235 --> @dtudury commented on GitHub (May 6, 2013): what I mean is it's pre-release until it's released (and if someone's working on it, it hasn't been released). once it's released no other release can ever share the same version. if 1.2.3+4 is different than 1.2.3+5, then two releases share the same x.y.z version. that makes the +r effectively a second patch number. actually, I guess that works... for release version: x.y.z+r the patch version is "z+r". is that what I was missing?
Author
Owner

@Tieske commented on GitHub (May 6, 2013):

say a toolchain is in use, CI server, whatever. Now the toolchain gets upgraded, then tests start breaking. The source wasn't modified, so the version is the same. But to help diagnose the problem it is very helpful to know the buildnumber, so it can be determined with which toolchain it was build and whether something changed there that made it break.

To the core of your comment: not necessarily all versions need to be released, nor all builds. I think that is the implicit assumption you make.

<!-- gh-comment-id:17469884 --> @Tieske commented on GitHub (May 6, 2013): say a toolchain is in use, CI server, whatever. Now the toolchain gets upgraded, then tests start breaking. The source wasn't modified, so the version is the same. But to help diagnose the problem it is very helpful to know the buildnumber, so it can be determined with which toolchain it was build and whether something changed there that made it break. To the core of your comment: not necessarily all versions need to be released, nor all builds. I think that is the implicit assumption you make.
Author
Owner

@dtudury commented on GitHub (May 6, 2013):

I'm not opposed to build numbers. in fact, I'm really excited about build numbers (certain products shoe-horned them into the last spec and it wasn't great). I think all I really want is a definitive answer to "can I release 1.2.3+4 and then later release 1.2.3+5 of the same product?".

these are my assumptions:

  • there are two kinds of builds: pre-release and release.
  • pre-release builds look like _x.y.z-p_ or _x.y.z-p+r_.
  • release builds look like _x.y.z_ or _x.y.z+r_.
  • all builds are pre-release until they are released.

@Tieske and @dgn1nja, thanks for your responses, I'm playing devil's advocate a little, please let me know if my friendly antagonism is unhelpful (or unfriendly :)

<!-- gh-comment-id:17470922 --> @dtudury commented on GitHub (May 6, 2013): I'm not opposed to build numbers. in fact, I'm really excited about build numbers (certain products shoe-horned them into the last spec and it wasn't great). I think all I really want is a definitive answer to _"can I release 1.2.3+4 and then later release 1.2.3+5 of the same product?"_. these are my assumptions: - there are two kinds of builds: pre-release and release. - pre-release builds look like **_x.y.z-p**_ or **_x.y.z-p+r**_. - release builds look like **_x.y.z**_ or **_x.y.z+r**_. - all builds are pre-release until they are released. @Tieske and @dgn1nja, thanks for your responses, I'm playing devil's advocate a little, please let me know if my friendly antagonism is unhelpful (or unfriendly :)
Author
Owner

@colin-haber commented on GitHub (May 6, 2013):

In regards to whether 1.2.3+4 and 1.2.3+5 are acceptable releases of the same product, think of it this way. As a consumer of your API or library, I am almost never interested in your build ID. It has no effect on compatibility or stability whatsoever. To me, those are effectively the same, and you would probably never have released both of them publicly.
However, if you had a nightly build system, there might be the case where you nightly-released 1.2.3+4 one night, and 1.2.3+5 the next one. Like I said, build meta is mostly for automated systems.
So, are they acceptable? Yes. Would you usually see both of them as public, stable releases? No.

<!-- gh-comment-id:17471145 --> @colin-haber commented on GitHub (May 6, 2013): In regards to whether 1.2.3+4 and 1.2.3+5 are acceptable releases of the same product, think of it this way. As a consumer of your API or library, I am almost never interested in your build ID. It has no effect on compatibility or stability whatsoever. To me, those are effectively the same, and you would probably never have released both of them publicly. However, if you had a nightly build system, there might be the case where you nightly-released 1.2.3+4 one night, and 1.2.3+5 the next one. Like I said, build meta is mostly for automated systems. So, are they acceptable? Yes. Would you usually see both of them as public, stable releases? No.
Author
Owner

@dtudury commented on GitHub (May 6, 2013):

@dgn1nja so the definitive answer is "yes, the spec won't prohibit it, but probably you shouldn't do it".

It has no effect on compatibility or stability whatsoever

I know it's not supposed to but... no offense, I don't know you well enough to trust that you didn't break something in 1.2.3+5 that worked in 1.2.3+4. (I wouldn't trust myself that far in fact :) for a project with lots of complicated and fragile dependencies, I'd demand version 1.2.3+4

also, you're saying there are 3 kinds of builds: pre-releases, releases, and public-stable-releases? if that's true I think the pre-release version should be repurposed for non-public-stable-release versions. it's important to be able to differentiate public stable releases from everything else.

regardless, from your example, if you're working toward 1.2.3, I think you should have your nightly build output something like _1.2.3-nightly+2013-05-06_

<!-- gh-comment-id:17473216 --> @dtudury commented on GitHub (May 6, 2013): @dgn1nja so the definitive answer is "yes, the spec won't prohibit it, but probably you shouldn't do it". > It has no effect on compatibility or stability whatsoever I know it's not supposed to but... no offense, I don't know you well enough to trust that you didn't break something in 1.2.3+5 that worked in 1.2.3+4. (I wouldn't trust myself that far in fact :) for a project with lots of complicated and fragile dependencies, I'd demand version 1.2.3+4 also, you're saying there are 3 kinds of builds: pre-releases, releases, and public-stable-releases? if that's true I think the pre-release version should be repurposed for non-public-stable-release versions. it's important to be able to differentiate public stable releases from everything else. regardless, from your example, if you're working toward 1.2.3, I think you should have your nightly build output something like **_1.2.3-nightly+2013-05-06**_
Author
Owner

@Tieske commented on GitHub (May 6, 2013):

"yes, the spec won't prohibit it, but probably you shouldn't do it".

no, the anser is yes, without a 'but'. SemVer guarantees compatibility within the rules as set forward on major/minor/patch numbers.

I don't know you well enough to trust that you didn't break something in 1.2.3+5 that worked in 1.2.3+4.

That is exactly what it is: trust. If you wouldn't trust the change in buildnumber, then why would you trust backward compatibility of 3.2.1 with 3.2.0 ? If you go down that path, than nothing can be trusted.

<!-- gh-comment-id:17478838 --> @Tieske commented on GitHub (May 6, 2013): > "yes, the spec won't prohibit it, but probably you shouldn't do it". no, the anser is yes, without a 'but'. SemVer guarantees compatibility within the rules as set forward on major/minor/patch numbers. > I don't know you well enough to trust that you didn't break something in 1.2.3+5 that worked in 1.2.3+4. That is exactly what it is: trust. If you wouldn't trust the change in buildnumber, then why would you trust backward compatibility of 3.2.1 with 3.2.0 ? If you go down that path, than nothing can be trusted.
Author
Owner

@dtudury commented on GitHub (May 6, 2013):

@Tieske yes, trust, exactly.
according to the 4th rule:

Once a versioned package has been released, the contents of that version MUST NOT be modified. Any modifications must be released as a new version.

A build version changing a new version and is the same as a patch version changing. It ought to function the same, but it's still a change. For release version: x.y.z+r the patch version is "z+r"

<!-- gh-comment-id:17485938 --> @dtudury commented on GitHub (May 6, 2013): @Tieske yes, trust, exactly. according to the 4th rule: > Once a versioned package has been released, the contents of that version MUST NOT be modified. Any modifications must be released as a new version. A build version changing a new version and is the same as a patch version changing. It ought to function the same, but it's still a change. For release version: x.y.z+r the patch version is "z+r"
Author
Owner

@Tieske commented on GitHub (May 6, 2013):

Nope. Not a change. Source didn't change. Unless you want to start a big debate on the form in which a "package" must be distributed (binary, source, compressed, etc.) to be made part of semver.

There is a line somewhere, common practice says source code. This is getting to a nitpicking level by now.

<!-- gh-comment-id:17486968 --> @Tieske commented on GitHub (May 6, 2013): Nope. Not a change. Source didn't change. Unless you want to start a big debate on the form in which a "package" must be distributed (binary, source, compressed, etc.) to be made part of semver. There is a line somewhere, common practice says source code. This is getting to a nitpicking level by now.
Author
Owner

@colin-haber commented on GitHub (May 6, 2013):

@Tieske I agree. Either way, this issue should be closed.

<!-- gh-comment-id:17487027 --> @colin-haber commented on GitHub (May 6, 2013): @Tieske I agree. Either way, this issue should be closed.
Author
Owner

@Tieske commented on GitHub (May 6, 2013):

@dgn1nja agree!

<!-- gh-comment-id:17487370 --> @Tieske commented on GitHub (May 6, 2013): @dgn1nja agree!
Author
Owner

@dtudury commented on GitHub (May 6, 2013):

I don't think it's nitpicking, I didn't know that source couldn't change. if it is in the spec it's implied.

  • 1.0.0-alpha new product spec'd and ready for dev
  • 1.0.0-alpha.1 first few features added towards alpha
  • 1.0.0-alpha.2 a few more features added
  • ...
  • 1.0.0-alpha.234+build.567
  • 1.0.0-alpha.234+build.568 automated build, _absolutely no change_
  • 1.0.0-alpha.234+build.569 automated build (exactly the same as any other 1.0.0-alpha.234)
  • ...
  • 1.0.0-beta.5+build.678
  • ...
  • 1.0.0-rc3.27+build.789
  • ...
  • 1.0.0+build.890 release
  • 1.0.0+build.891 automated build, _absolutely no change_ (exactly the same as release)

@Tieske @dgn1nja, you're right, this has become a different issue.
@Tieske @dgn1nja @mojombo @Haacked do you think it's worth opening an issue to make that explicit? ("should explicitly state that source can't change between releases who's only difference is build version") (or do you want me to go away? :)

I feel confident that as it stands package managers will ignore it and other people will miss it. you'll find people releasing 0.0.0+100 as a patch to 0.0.0+99

@Tieske @dgn1nja thanks so much for your help! sorry to come across as nit-picky, I (obviously) didn't understand a couple of points in the spec

<!-- gh-comment-id:17495663 --> @dtudury commented on GitHub (May 6, 2013): I don't think it's nitpicking, I didn't know that source couldn't change. if it is in the spec it's implied. - 1.0.0-alpha _new product spec'd and ready for dev_ - 1.0.0-alpha.1 _first few features added towards alpha_ - 1.0.0-alpha.2 _a few more features added_ - ... - 1.0.0-alpha.234+build.567 - 1.0.0-alpha.234+build.568 _automated build,_ **_absolutely no change**_ - 1.0.0-alpha.234+build.569 _automated build (exactly the same as any other 1.0.0-alpha.234)_ - ... - 1.0.0-beta.5+build.678 - ... - 1.0.0-rc3.27+build.789 - ... - 1.0.0+build.890 _release_ - 1.0.0+build.891 _automated build,_ **_absolutely no change**_ _(exactly the same as release)_ @Tieske @dgn1nja, you're right, this has become a different issue. @Tieske @dgn1nja @mojombo @Haacked do you think it's worth opening an issue to make that explicit? ("should explicitly state that source can't change between releases who's only difference is build version") (or do you want me to go away? :) I feel confident that as it stands package managers will ignore it and other people will miss it. you'll find people releasing 0.0.0+100 as a patch to 0.0.0+99 @Tieske @dgn1nja thanks so much for your help! sorry to come across as nit-picky, I (obviously) didn't understand a couple of points in the spec
Author
Owner

@Tieske commented on GitHub (May 6, 2013):

I feel confident that as it stands package managers will ignore it and other people will miss it. you'll find people releasing 0.0.0+100 as a patch to 0.0.0+99

that is non confirming to semver (except that it is in the 0.x.x range which is special in semver, but that is besides your point). And regarding my opinion on pre-release, see #30

<!-- gh-comment-id:17496395 --> @Tieske commented on GitHub (May 6, 2013): > I feel confident that as it stands package managers will ignore it and other people will miss it. you'll find people releasing 0.0.0+100 as a patch to 0.0.0+99 that is non confirming to semver (except that it is in the 0.x.x range which is special in semver, but that is besides your point). And regarding my opinion on pre-release, see #30
Author
Owner

@dtudury commented on GitHub (May 6, 2013):

@Tieske no, yeah, I know now. but I didn't before... (I wasn't being hypothetical) :)
in the past I let jitsu (a deployment script) auto-increment my version and I did exactly that (0.0.0-99 -> 0.0.0-100). Which was fine because npm (a package manager) doesn't allow any dashes so I was forced to update the patch version before publishing it. after the 2.0.0 spec auto-incrementing will likely occur after a plus and package managers will accept versions with pluses. This makes the automatic policing that helped me difficult.

actually... I guess it could still work; the error would be something like "redundant release 0.0.1+100: 0.0.1 was already published (previous build named: 0.0.1+99)"

<!-- gh-comment-id:17499103 --> @dtudury commented on GitHub (May 6, 2013): @Tieske no, yeah, I know now. but I didn't before... (I wasn't being hypothetical) :) in the past I let jitsu (a deployment script) auto-increment my version and I did exactly that (0.0.0-99 -> 0.0.0-100). Which was fine because npm (a package manager) doesn't allow any dashes so I was **forced** to update the patch version before publishing it. after the 2.0.0 spec auto-incrementing will likely occur after a plus and package managers will accept versions with pluses. This makes the automatic policing that helped me difficult. actually... I guess it could still work; the error would be something like "redundant release 0.0.1+100: 0.0.1 was already published (previous build named: 0.0.1+99)"
Author
Owner

@dtudury commented on GitHub (May 9, 2013):

@Tieske hey look at that... 2.0.0-rc.2 explicitly says build metadata doesn't differentiate versions. looks like that's what you were fighting for in #30 . well done! seems to solve the only problem (misinterpreted ambiguity) I could see

<!-- gh-comment-id:17693587 --> @dtudury commented on GitHub (May 9, 2013): @Tieske hey look at that... 2.0.0-rc.2 explicitly says build metadata doesn't differentiate versions. looks like that's what you were fighting for in #30 . well done! seems to solve the only problem (misinterpreted ambiguity) I could see
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/semver#6057