Closed pranavkm closed 4 years ago
We can discuss this for 3.2
I looked at how NPM does it, and it looks like it will not allow pre-releases with such a specifier.
We need to work on how we extend our syntax to support ranges (do we go with something similar to npm? Do we also allow 1.*-*
? Do we allow for version ranges ala packages.config/nuspec?
Do we also allow 1.-
AFAIK it stops when it sees the *
. @emgarten would know this better.
Yes it does, my comment was a question about what we should do in the future :)
Wondering if there is any progress on this as for CI purposes it would really help us to support 7.0.*-*
or something like
{
"version": "7.0.*",
"prerelease": true
}
Not yet, a good indication of progress would be if the item is assigned to someone for work.
Unfortunately that's what I thought... Just been open for over a year and bumped again and again... :(
Please implement this
So this ticket is still in Priority 1 and has been bumped for a couple of years.
We use CI and end up spitting out a lot of packages, the maintenance of keeping up with them is only just worth the value of keeping everything separate. Being able to specificy "Latest prerelease" in our dev branches would really be very useful.
Could we get a vague timeline at least? Maybe pointers on where to start looking at developing a pull request?
This needs a design to move forward.
The problem is that changing the behavior of *
is a breaking change, and adding a new syntax such as 1.0.*-*
will break older clients that do not know how to parse it.
Feedback and suggestions on this would be great. I would really like to see this issue fixed.
Alright so let's talk design.
1.0.*
should probably not pull -prerelease packages, as that is likely to be unexpected behavior relative to previous experience. If someone is not specifying -*
it's very probable that they don't want prerelease packages finding their way in there. Therefore we should likely not modify the behavior of preexisting wildcards and add newer syntax to handle "Get me the latest prerelease".1.0.0-build<date>-<incrementing id>
. This is per-patch CI builds, once we release a patch we increment the nightly builds to spit out prereleases for the next patch version, 1.0.1-build<date>-<incrementing id>
. Therefore the pattern we want to use is simply 1.0.0-*
.1.0.0-*
? It's unclear based on the discussion there and I've not had time to poke around the related source code. Is 1.0.0-*
as syntax already present in the system? Does it just not function as intended?1.*-*
? Or can we safely say "That's an inappropriate edge case that we don't want to support right now" and remove it so we can avoid breaking older clients and/or forcing a major version number bump?So, is making the syntax
1.0.0-*
mean get the prerelease version that is the highest number
actually a breaking change? And do we need to support any other variations on that?
For our use case, we would like the ability to mix 1.0.*
with CI builds - this would result in something like 1.0.*-*
or 1.0.*-ci*
.
This is particularly important for CI builds based on CI builds in our framework, where if we bump a component by 0.0.1
we still want the latest CI build brought into all the other builds - especially for unit testing etc. to make sure that no downstream packages fail.
This can be done (sort of) with project references, but our framework is >100 projects and can be a pain to manage that way.
1.0.0-* as syntax already present in the system? Does it just not function as intended?
1.0.0-*
works but does not go above 1.0.0
1.0.0-*
works but does not go above 1.0.0
As in, it just resolves the lowest available version? That seems to be what this documentation indicates. We attempted to use this in Visual Studio and were seeing syntax errors, but that might be us using it wrong.
1.0.*-*
would be useful.
Okay, fair enough. @emgarten You indicated messing with *
syntax would be considered a breaking change, what's the timetable and process that it would take to introduce that? Could we confirm/polish the behavior of a full specific version with floating prerelease in a faster timetable than if we were to fully implement arbitrary version and prerelease?
What about using a different symbol than * to indicate a wildcard that includes release and prerelease versions?
E.g. 1.0.%
Is there any update on this? We're in the process of migrating a bunch of projects to NuGet and this is still affecting us, over 2 years after it was first reported.
@emgarten Since you say that changing this parsing is a breaking change (I assume you mean at the client side) perhaps we could introduce something similar to the way that nuget packages have a min required client but for projects? (similar to the minClientVersion in nuspec) Then you could have a BeforeRestore target that checked for $(NuGetClientVersion) (or similar) and throws an error if it is too low or does not exist (e.g. for old tools that would not handle the extended wildcards correctly) and ensure that nuget pack and msbuild, vs etc. set the property to the installed client version. Perhaps along the lines of
<Target Name="EnsureNuGetClientVersion" BeforeTargets="Restore" Condition="'$(MinNuGetClientVersion)'!=''">
<Error Text="You require version $(MinNuGetClientVersion) or higher of the NuGet tools installed to correctly restore this project"
Condition="'$(NuGetClientVersion)'=='' OR ($([System.Version]::new($(NuGetClientVersion)) < $([System.Version]::new($(MinNuGetClientVersion)))" />
</Target>
Then in your .csproj or Directory.Build.props or whatever simply add something like
<PropertyGroup>
<MinNuGetClientVersion>4.5.0</MinNuGetClientVersion>
</PropertyGroup>
@CZEMacLeod that could work, currently the version of NuGet isn't a property in MSBuild, but potentially a task could find the assemblies and check them.
Why can’t we have something like the following:
<PackageReference Include=“MyPackage” Vesrion=“2.*” IncludePreRelease=“true”/>
@anangaur I suggested that (although at the time it was in json rather than msbuild) over a year ago!
People may want to restrict versions to specific prerelease channels like rc
. See https://fsprojects.github.io/Paket/nuget-dependencies.html#Prereleases for how Paket solves that
@anangaur we had VersionRange.IncludePreRelease in 3.0.0 which is similar to what you are proposing. We eventually removed it due to the very high number of bugs it caused. Version ranges work best as strings that can be round tripped, having a string + extra metadata that cannot be part of the string is painful.
I think we can go ahead with 1.0.*-*
which is only supported with newer clients. With older clients, it will still treat it as 1.0.*
which should be fine. thoughts?
Older clients will probably choke on that.
@jainaashish
To me 1.0.*-*
means any package with pre-release version and starts with 1.0. This will exclude the stable versions of the package. Unless we want to go away from general regex concept.
I thought the problem statement was to be able to define a floating version that includes pre-release versions (by not excluding the stable versions).
To reiterate the requirements the way I understood:
As Noel, a user who uses NuGet packages,
1.*
or [1.0.0, 2.0.0)
Looking at the above and to solve the problem in non breaking way for existing clients, additional meta data looks to be the right approach. @emgarten, I would like to understand the issues with this approach (the bugs you mentioned)
additional meta data looks to be the right approach.
It needs to be possible to express a version range as a string. It makes it easy to display, understand it as a user, and the current code base treats these as strings everywhere.
I agree with @jainaashish, 1.*-*
is the clearest representation of this. Excluding stable versions and forcing prerelease would be a very unusual scenario, I think this notation is pretty clear in that it allows prerelease and stable. I think this would be a fairly small fix to enable this.
Support for specific labels would mean that the range would no longer be contiguous, it could be added but I think that would be a different feature.
Older clients will fail on 1.0.*-*
but the alternative is that they parse 1.0.*
and then fail to read the include prerelease bool, which will make them silently fail to resolve the package. In my opinion this is worse than failing fast when they can't understand the range.
"It needs to be possible to express a version range as a string"
That is an arbitrary requirement.
Am 30.11.2017 23:07 schrieb "Justin Emgarten" notifications@github.com:
Older clients will fail on 1.0.- but the alternative is that they parse 1.0.* and then fail to read the include prerelease bool, which will make them silently fail to resolve the package. In my opinion this is worse than failing fast when they can't understand the range.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/NuGet/Home/issues/912#issuecomment-348336325, or mute the thread https://github.com/notifications/unsubscribe-auth/AADgNCrAiAHyKuvevRhg_BNPCPqfWa5iks5s7ycMgaJpZM4FVctT .
I agree with @jainaashish, 1.- is the clearest representation of this. Excluding stable versions and forcing prerelease would be a very unusual scenario, I think this notation is pretty clear in that it allows prerelease and stable.
@emgarten , @jainaashish Correct me if I am wrong here: Doesn't regex 1.-\ mean a string that starts with 1. followed by any string and then a - and then followed by any string. So it would mean only prerelease versions. I am treating to mean one or more occurrence of any character. (Most regex parsers treat as one or more occurrence of the preceding character which definitely is not something we are following here). Also I am assuming . (dot) is treated as the character dot and not "any character".
I think it is important to look at these strings as Semantic Versions which have meaning, not as opaque strings. Treating them as regular strings and applying a regex misses a lot of that meaning, and the reasons why we treat stable and prerelease differently, and the intent of the package authors when they versioned things in this way.
We can think of a floating range as two parts:
Stars are used to express the target for part 2. The decision to allow for prerelease or not is made by part 1.
Here is how I would read the ranges:
1.0.*
- I want the highest stable patch
1.0.*-*
- I want the highest stable patch and I'm ok with allowing non-stable packages to satisfy this constraint
Stars indicate floating to the highest version, and by SemVer rules 1.0.1 is higher than 1.0.1-rc. I can see how by normal wildcard matching it might appear that a -
is required. But in my opinion a user would never want to take any prerelease version but not the stable version, and if they did they could use 1.0.1-*
which would give 1.0.1-rc
.
@emgarten My use case would certainly be for something like 1.0.- as above - as you describe it.
1.0.*-*
- I want the highest stable patch and I'm ok with allowing non-stable packages to satisfy this constraint
Moreover - I think it would be likely that I might need any stable or non-stable patch package but to constrain it to be above a certain release.
e.g. I need any 1.0 release (or pre-release) after 1.0.4-rc1
and be happy (and want to get) 1.0.4-rc2
,
1.0.4
, 1.0.5-beta1
or 1.0.5
etc.
Could this not be covered by something like [1.0.4-rc1,1.1)
as it stands?
If so isn't 1.0.*-*
effectively just [1.0.0-*,1.1)
? E.g. any pre-release/unstable version from 1.0.0 up to (but not including) 1.1?
Hi @emgarten has there been any progress or more thought given to this issue?
I need a way for the latest version to always be used regardless of release or pre-release.
So if a package had the following versions available it would use 3.9.3091-rc
. At present, if I reference 3.9.*
it always uses the latest release version which is 3.9.3088
.
It would be very useful if I could reference3.9.*-*
in order to get 3.9.3091-rc
3.9.3091-rc 3.9.3090-rc 3.9.3089-rc 3.9.3088-rc 3.9.3088 3.9.3087-rc
@patricknolan as a workaround until nuget introduces a way to handle prereleases without * - take a look at https://fsprojects.github.io/Paket/nuget-dependencies.html#Prereleases
@patricknolan this is set as pri 0 for NuGet, we're hoping to get this added soon.
Thanks @emgarten that's great news. I think this issue has been a large wide spread problem and people have just been forced to implement a compromised solution or some painful hacks to get around it.
Reading through all these messages, I'm still a bit confused. I'm hoping that 1.0.*-*
would get the prerelease version. In the following, 1.0.2-ci-2 should be selected:
1.0.3 1.0.2 1.0.2-ci-2 1.0.2-ci-1 1.0.1 1.0.1-ci-1
An example of this working out well would involve using a Choose/When... When we are compiling in debug mode, get the highest prerelease version (1.-) which is non-breaking. When we are compiling in release mode, get the highest stable version (1.*) which is non-breaking. It's just one scenario... but the key here is this, we need a way to specify to get the highest version which also happens to be a prerelease package.
I find the - notation confusing. Instead we should have an explicit flag. In the above example, IMO 1.0.2 is the highest version of the package matching the floating version as prerelease versions are considered lower versions compared to the same versioning without prerelease portion of the versioning.
Hope I didn’t confuse you further?
I agree with @patricknolan that this is a very important feature for many of us. I too have the exact same use case as he does and would be extremely grateful if this would be implemented ASAP. We are transitioning from using packages.config to new PackageReference in projects and would like to transition to using NuGet wildcard versioning that meets stated use case. We are holding up this transition until there's a way to overcome this. Thanks!
@pranavkm I would like to change the description to the following, with your permission. Do let me know if the below covers your usecase and if you are okay with the change?
As Noel, who uses NuGet packages in PackageReference based projects,
Sure, our team has abandoned the use of floating versions for our projects, so I'm not entirely vested in this particular feature. Feel free to rephrase it!
Any movement towards a solution on this issue?
This is my proposal for the requirements listed earlier. Open to comments/scrutiny:
I would like to use floating versions that only resolves to stable versions of the package (Current behavior):
<PackageReference Include=“MyPackage” Vesrion=“2.*” />
I would like to use floating version that can resolve to the latest version even if the latest happens to be a pre-release version:
<PackageReference Include=“MyPackage” Vesrion=“2.*” IncludePreRelease=“*”/>
So in the above case, if the version available are 1.0, 2.0, 2.1, 2.8-alpha.9, 2.8-beta.1, 2.8-rc.1, 2.8-rc.2, 3.0, 4.0, the above PackageReference should resolve to 2.8-rc.2
I should be able to use both the braces/regex formats i.e. 1.* or [1.0.0, 2.0.0) that can include pre-release versions:
<PackageReference Include=“MyPackage” Vesrion=“[2.0.0, 3.0.0)” IncludePreRelease=“*”/>
I would like to additionally define whether I want to resolve to rc, beta, alpha or all pre-releases:
<PackageReference Include=“MyPackage” Vesrion=“2.*” IncludePreRelease=“rc;beta”/>
So in the above case, if the version available are 1.0, 2.0, 2.1, 2.8-alpha.9, 2.8-beta.1, 2.8-rc.1, 2.8-rc.2, 3.0, 4.0, the above PackageReference should resolve to 2.8-rc.2
[Open]: In the above case whether the prerelease version texts rc, beta be given equal weight-age or alphabetical weight-age? i.e. if 2.8-beta.9 also existed whether NuGet should resolve to 2.8-beta.9
(weightage given to the number after the pre-release text) or 2.8-rc.2
(alphabetically rc > beta as r > b)
@forki what's the behavior for paket for the open issue above?
Rc is newer than beta is newer than alpha. Good thing is alphabetical order works here
The suggested package resolution logic looks good. Lots of flexibility the way it's laid out.
We care about this. And hope to get to it soon.
There were some disagreements on whether there should be new attribute to specify the ability to float to pre-release versions. So just thinking aloud here, will the following be an acceptable choice? @jainaashish @nkolev92 @rrelyea
I would like to use floating versions that only resolves to stable versions of the package (Current behavior):
<PackageReference Include=“MyPackage” Vesrion=“2.*” />
Remains same
I would like to use floating version that can resolve to the latest version even if the latest happens to be a pre-release version:
<PackageReference Include=“MyPackage” Vesrion=“2.*” IncludePreRelease=“*”/>
Alternative:
<PackageReference Include=“MyPackage” Vesrion=“2.*|”/>
OR
<PackageReference Include=“MyPackage” Vesrion=“2.*|*”/>
the separator |
is to imply include pre-release versions
I should be able to use both the braces/regex formats i.e. 1.* or [1.0.0, 2.0.0) that can include pre-release versions:
<PackageReference Include=“MyPackage” Vesrion=“[2.0.0, 3.0.0)” IncludePreRelease=“*”/>
Alternative:
<PackageReference Include=“MyPackage” Vesrion=“[2.0.0, 3.0.0)|*” IncludePreRelease=“*”/>
I would like to additionally define whether I want to resolve to rc, beta, alpha or all pre-releases:
<PackageReference Include=“MyPackage” Vesrion=“2.*” IncludePreRelease=“rc;beta”/>
Alternative:
<PackageReference Include=“MyPackage” Vesrion=“2.*|rc;beta”/>
From readability and ease of use perspective, I still like the IncludePrerelease
attribute :)
I don't see the reason for introducing a new attribute. That makes things more complicated and adds implementation difficulty.
I don't believe there's an ease of use argument here with the prerelease attribute.
Version ranges already include prerelease packages.
<PackageReference Include=“MyPackage” Vesrion=“[2.0.0, 3.0.0)"/>
can already resolve to a prerelease package. Adding that new metadata would conflict with that.
Additionally, I don't see the point of introducing a new separator like
|
when
-
already exists and it's more intuitive since that's how versions are written.
Personally, I am a fan of
<PackageReference Include=“MyPackage” Vesrion=“2.*-*”/>
Which would basically say, give me highest, even it's prerelease.
I don't see the scenario of, I want rc AND beta versions for example, as that high of a priority, since you should be able to do:
<PackageReference Include=“MyPackage” Vesrion=“2*-rc*”/>
to get latest, stable or rc version.
tldr;
|
why do you need alternate approach?
<PackageReference Include=“MyPackage” Vesrion=“2.*|”/>
I like the additional parameter idea, that seems right which could work across old vs new clients. So we should stick to that.
UPDATE: final solution details
Original Issue: Consider a project.json specification such as
If the only packages in the feed are prerelease packages such as
A.1.0.0-alpha
,A.1.0.1-beta
, the restore fails stating it was unable to resolve packageA
.[anangaur] Adding the requirement as evolved during the discussions:
As Noel, who uses NuGet packages in PackageReference based projects,
Link to spec - https://github.com/NuGet/Home/wiki/Support-pre-release-packages-with-floating-versions Status - Implemented in version 5.6 of NuGet, 16.6 of Visual Studio and 3.1.300 of the .NET Core SDK.