-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
Pre-release version numbers #2222
Comments
Specifically, if I put
|
Yes, Cargo should follow SemVer here. I think that this might be the fault of the |
Ok, sorting should be fixed, but that’s separate from the original issue. |
Well, given that |
Let me rephrase. Let’s say a package has three versions published: 1.0.0, 1.0.1, and 1.1.0-beta. If I depend on it with version requirement Or, more generally, should we assign meaning (and tool behavior) other than the relative ordering to "pre-release"? |
That is exactly what I am speaking about in #2222 (comment) |
From the same paragraph that you quoted:
Precedence is not what I’m talking about. This part of paragraph 9 is relevant to what I’m talking about, though:
Should Cargo consider 1.1.0-beta incompatible with 1.0.0 in the same way that 2.0.0 is incompatible with 1.0.0? (Whereas 1.1.0 is compatible with 1.0.0.) |
As far as I'm aware, Cargo's notion of "compatible with x.y" is just |
I.e. since "compatible with 1.0" is |
No. It’s |
Or rather something like |
Er, sorry, yes, you are correct (4AM here...). But my point still stands. |
I agree with @SimonSapin that it seems odd if I say "semver compatible with 1.0.0" that I'll start picking up I agree that there also may be an issue with the semver crate which needs to be handled as well, especially if we consider |
Two things that I think are somewhat uncontroversial:
I'd like to suggest canonizing the concept of channels, so that:
The idea is to make the Rust-style release cycle more first class and give people a way, through their Cargo.toml, of subscribing to a particular "release channel". We could also make subscription explicit through additional metadata: [dependencies.nix]
version = "1.3.0"
channel = "beta" This would always select the latest betathat also matches the semver versioning ( |
What do you mean by supersedes? “ Note that semver.org only talks about precedence, “how versions are compared to each other when ordered”. And 1.3.0-beta does sort after 1.2.0.
Would there be a list of allowed keywords? semver.org allows arbitrary identifiers for pre-release versions. |
Precisely.
Arbitrary identifiers for channels would be allowed, but you could only upgrade across versions on the same "channel". In practice, it is probably good to stick to a few well-known names like "nightly", "alpha", "beta", "rc", but they would not be interpreted as having any relation to each other across versions. Just like in Rust, if you subscribe to the "beta" channel, you stick to beta. |
One thing we'd need to figure out is what to do when we see a request like: foo = "1.0.2-beta2" That's valid by today's rules, but should that only match the package |
I'm not seeing the behavior that's being talked about in the beginning of the post. In particular, cargo seems to not select prerelease versions at all? Specifying a dependency core_rustc-serialize = "*" (or core_rustc-serialize = "^0.3") results in Cargo choosing 0.3.19, while it should choose the newer 0.3.20-v0.3.19patch1. You can't specify 0.3.20-v0.3.19patch1 in either case by using cargo update --precise. Specifying the exact version string does work. I don't see any code changes linked here that suggest the behavior has changed though. It seems people in here want cargo to not automatically update to higher prerelease versions, e.g. if the spec is "^0.3.19", it wouldn't update to "0.3.20-alpha". I understand that sentiment, but I think cargo should allow manually updating to that version in this case by using |
In general, it shouldn't select prerelease versions unless you explicitly ask for prerelease versions. |
I had a problem recently with a published binary (see #9999). I published cargo-temp v0.2.3 using clap |
I just noticed now that leftwm-theme has the exact same issue! https://github.com/leftwm/leftwm-theme imo this clearly shows that this is a pitfall |
There was a discussion in the internals forum here: https://internals.rust-lang.org/t/changing-cargo-semver-compatibility-for-pre-releases/14820/10?u=djc. The preferred suggestion seemed to be this:
Cargo team, does that need an RFC, or just an implementation? |
I think that will need a detailed description of how people opt in to the breaking change. |
Okay, here are two directions that we could work out more. Option 1: reuse the resolver = "3" Option 2: separate value: pre-release-updates = "sticky" # or "default" |
Strike again, rwf2/Rocket#2166, I think a small fix could be that cargo consider by defaut that pre release is for exact version edit: #2222 (comment) I'm blind sorry for spamming. @djc option 1 seem way better than option 2 cause option 2 require the user to always put this in every cargo.toml file, while "resolver = "3" is a naturel way to just update semver rule, and can be set by default in edition 2024. |
Rfc proposition rust-lang/rfcs#3263 my first ever ! hope it's ok |
As this is a more stable place to be holding this conversation, I'm moving a thread over from rust-lang/rfcs#3263 @ehuss said
@epage said
@ehuss said
|
Its number of places and chance for errors (tracking what the requirements should be).
Its hard to gauge how much a feature would be used if it had better support. I minimized my use of it for clap v4 and I didn't bother switching my version requirements for the few pre-releases I did do, hoping I wouldn't have a breaking change affected by this, because I didn't want to deal with the version requirement clean up.
I hope we can come to a better solution for handling of pre-releases than comment directives.
While channels might be useful in some contexts, I doubt they can generally resolve this problem. A lot of pre-release testing is more one off; people aren't as likely to continually want to do pre-release testing unless they are patching their crates to get ahead of time notice, like people testing nightlies in CI.
imo this is a non-starter. If clap v3 had to have a separate channel for each pre-release breaking change, we would have run out of well-recognized channel names. I had brought this up in one of the other threads that we cannot assume semver compatibility even within the same pre-release type as it doesn't make sense to constrain compatibility on that axis. |
Trying to sum up the issues and efforts regarding pre-releases and how I see the design space. General contextSemVer provides a system (called Semantic Versioning) to document versions of the code of a given package based on the version number only:
Note that SemVer only provides "baseline" guarantees. The user may provide additional guarantees in their own package documentation (for example compatibility across different major versions if only a given subset of the public API is used). Similarly, package managers may also provide additional guarantees for all packages they manage (for example stability for releases with a major number of zero). Note that those 3 notions are interconnected. For stable versions, compatibility is "contiguous" with respect to precedence. If A, B, and C are stable versions where A precedes B, B precedes C, and A is compatible with C, then A is compatible with B and B is compatible with C. This "strong transitivity" permits using ranges of stable versions in a "compatibility-friendly" way, and meant to be leveraged by package managers for dependency management. What works well
What doesn't work wellCargo extends compatibility to pre-releases as follows:
The problem of extending compatibility like that, is that this is "maximal" and leaves no freedom to users (because the "baseline" guarantees are the "maximal" guarantees). Concretely, with this extension, a library author cannot introduce a breaking change within pre-releases of a given release. In practice, they will because they must, and now the exact scenario that SemVer is supposed to prevent happens: Instead, Cargo should have extended compatibility to pre-releases in a way that leaves some freedom to library authors to release both breaking and non-breaking changes within pre-releases of a given release. See the last section for an example of such extension. Immediate workaroundRecommend to use Planned efforts
Extension exampleWhy did SemVer come up with the notion of unstable versions? This question should drive the design around pre-releases. I believe unstable versions are meant as development branches that you can publish without impacting your stable branch. In SemVer, your stable branch is composed of stable versions (releases with non-zero major number). Your development branches are unstable versions (releases with zero major number for initial Here is how I would deal with development branches in a uniform way (this is not meant to be adopted by Cargo, but could be lints/recommendations for users and a coherent general direction for incremental changes). The core idea is to consider development branches as forks of the package, for example Concretely, this alternative extends SemVer as follows:
In addition to "strong transitivity" for the stable branch, we have "strong transitivity" for each development branch too. Version requirements are valid only if all matched versions are in the same branch. For example:
Possible incremental changes with this design in mind would be:
Footnotes
|
imo that is too dramatic of a shift to move the ecosystem through and is a superset of the problems with just making pre-releases assume |
Making pre-releases assume
Note also that in the list of problems, there's also the fact that Cargo defines compatibility ranges regardless of the branch. It is always the major number of the version, even if it's a pre-release. The correct definition would be (it simply follows from the "package fork" model):
Without doing this correctly, you will get diamond problems. For example, the case above having both
Yes, this is definitely a major change, and shouldn't be done at once (if at all). I never said that. However, it is the north star defining the general direction for incremental improvements (like a warning to not rely on the default version requirement for pre-releases, and instead specify precisely what is meant, which is currently package-specific, so each package should document its pre-release behavior). Said otherwise, agreeing on a north star is necessary, otherwise incremental improvements are just Brownian motion, where improvements may introduce new problems (either now or in the future by preventing another better improvement). It is important to have a consistent long-term strategy regarding pre-releases. And it's not because it's a hard problem that it should not be handled. I suggested such a long-term strategy above. It doesn't need to be implemented even in 10 years from now, however incremental improvements should approximately align with this general direction. |
Another example of incremental non-breaking changes1 that aligns with this north star and fixes all issues:
Document the limited use of pre-releasesPre-releases are useless because they assume you're able to get every change right from the first version you introduce it. This goes against the idea of pre-releases, which is to experiment without commitment. The workaround is to fork your package for each release for which you want to experiment. For example, if you want to experiment before committing a Note The proof that pre-releases are useless is by case over the 3 types of pre-releases:
Warn when publishing pre-releasesPrint a warning when publishing a pre-release. The message would point to the documentation of pre-releases and suggest immediately yanking the pre-release. This could eventually become a breaking change if needed (to avoid the yanking), by adding a Footnotes
|
Not really. In fact, they're basically the complete opposite version of this:
The way prereleases are used in Rails, which is the community that semver came out of (well Ruby more generally, and Rails actually doesn't follow semver more generally, but that's neither here nor there right now, the point is this is how these semantics originally came to be), are effectively release candidates. You get releases like these (real example):
Note the use of Sometimes there are pre-releases named "beta", like for example, Rails 3.0.0 was a massive release, so you had this:
The beta releases are a "it's getting into shape but we aren't committing to exactly this just yet" style release, so this is closer to what you're talking about. This is also why the behavior is the way it is, historically. The use case is "I want to let people opt in to kicking the tires." And that's why something like Anyway, I know that there's tons of desire to change this behavior, but l've always thought it makes sense. |
Wait, how is that different from a development branch? I think we're saying the same thing with different vocabulary. The other word I used is "experiment without commitment". We can also say "let users check if it matches their needs". That's all the same thing to me. Feel free to clarify the difference if you see one, so I can use your vocabulary.
Sorry but I don't see a logical implication between the use-case and opting in breaking changes (which I understand as uncontrolled build breakage1). What I described is an example of fulfilling the use-case while preventing uncontrolled build breakage. Let me give a concrete example if it helps:
Now, if your package manager understands that
If your package manager doesn't help you because it considers all pre-releases to be compatible, then you can at least tell your users to only use
Do you mean it makes sense that users either stay on the stable branch or opt-in to uncontrolled build breakage in the development branch? It makes much more sense to me to be able to both opt in a development branch and preserve the SemVer property of never getting a broken build because a new version is published. Said otherwise, when you opt in a development branch, you opt in more maintenance when bumping the This non-contaminating aspect is very important for scale. Think of it like Footnotes
|
Should Cargo do something special when a dependency has versions published with pre-release version numbers? Maybe not select them unless requested explicitly with
cargo update --precise
?CC whitequark/rust-xdg#9, @whitequark, @alexcrichton
The text was updated successfully, but these errors were encountered: