It is somewhat surprising that the solver will use pre-releases for dependencies.
See eg. https://github.com/dart-lang/pub/issues/2446
Ideally this would be off by default - but that might be a breaking change.
If solving without prereleases fails we should probably report that a solution exists with prereleases and mention the flag.
One question we have not answered:
Probably want to allow explicitly chosen pre-releases from the root pubspec.
dependencies:
foo: 1.0.0-dev # just get me that prerelease!
But it is not clear how to generalize this. (Should we allow that also transitively - what does ^1.0.0-dev mean...)
The use case I feel the most strongly about is the one where a pubspec.yaml lists a package and a stable version (single or range), and the solver ends up resolving that to a pre-release. Consider this example:
foo is published in one version:foo 1.0.0 which depends on bar: ^1.0.0bar is published in one version:bar 1.0.0 with no dependenciesThe developer starts with this pubspec.yaml:
foo: ^1.0.0
bar: ^1.0.0
````
Running `pub get`, the developers gets locked on `foo 1.0.0` and `bar 1.0.0` as expected.
Updates are now published on pub.dev:
* package `foo` is published in two versions:
* `foo 1.0.0` which depends on `bar: ^1.0.0`
* `foo 2.0.0` which depends on `bar: ^1.1.0-dev`
* package `bar` is published in two versions:
* `bar 1.0.0` with no dependencies
* `bar 1.1.0-dev-1.0` with no dependencies
The developer now hears about `foo 2.0.0` and it has something they need, so they update their pubspec.yaml to:
foo: ^2.0.0
bar: ^1.0.0
````
The developer runs pub get with an intention of picking up foo 2.0.0. They are not aware that foo itself depends on a pre-release bar, and they generally have a policy to only use stable versions. So when they later debug a bug in their app, and realize it's coming from bar and that they had been locked on foo 2.0.0 and bar 1.1.0-dev-1.0 they get angry.
I suggest that a pub get/upgrade without an --allow-pre-release flag should have failed and reported something like:
Could not resolve, foo 2.0.0 requires bar >=1.1.0-dev and your pubspec allows only stable versions of bar >=1.0.0 <2.0.0. Update your dependency on bar to allow a pre-release, or opt-in to selecting pre-release by passing the flag --allow-pre-releases.
They can then either use the flag, or change pubspec.yaml to:
```
foo: ^2.0.0
bar: ^1.1.0-dev-1.0
````
Probably want to allow explicitly chosen pre-releases from the root pubspec.
I agree that this is probably the most desirable behavior, with a small tweak which is that we allow explicit pre-release dependencies in pre-release packages always. This way an explicit pre-release dependency in the root package is allowed to itself have pre-release deps without any warnings.
Ultimately we don't want people to release stable versions of a package if they have any immediate prerelease dependencies anyways, so this just encourages that.
@sigurdm recently did a warning to discourage this too.
Assuming everybody follows this policy there can be no explicit prerelease dep (even transitively) without a prerelease dep in the root pubspec.
We could enforce this, but I'm not sure we need to be this strict.
If solving without prereleases fails we should probably report that a solution exists with prereleases and mention the flag.
That, or we could print a warning if we use pre-releases in the solution.
So 1st try to solve without pre-releases (except those allowed by root pubspec.yaml, or transitively from there), then try to solve with pre-releases if that doesn't work. And print a warning if we had to do a second resolution.
If we go with the solution suggested by @jakemac53 two more questions came up while @jonasfj and i discussed this a bit:
If
foo: 1.0.0 and bar: 1.0.0-dev andfoo 1.0.0 depends on baz: ^1.0.0bar 1.0.0-dev depends on baz: ^1.1.0-devbaz exists in 1.0.0 and 1.1.0-devAnother interesting case:
foo: 1.0.0 depends on bar: 1.0.0-dev.foo.My suggestion: Without the -allow-pre-release flag, we simple disallow / filter away all pre-release versions. We could allow-list any packages in the pubspec.yaml listed with pre-release versions. That seems like a simple to understand solution?
Most helpful comment
I agree that this is probably the most desirable behavior, with a small tweak which is that we allow explicit pre-release dependencies in pre-release packages always. This way an explicit pre-release dependency in the root package is allowed to itself have pre-release deps without any warnings.
Reasoning