NuGet / Home

Repo for NuGet Client issues
Other
1.5k stars 252 forks source link

Allow users to determine package resolution strategy during package restore - direct or transitive #5553

Open Wil73 opened 7 years ago

Wil73 commented 7 years ago

I am not going to debate if highest or lowest should be the default: leave the actual behavior up to the consumer.

Why on earth should Microsoft FORCE users to adopt the "safest is best" strategy in the first place?

Is there any reason why we cannot add a switch to nuget.exe and NPM that allows the user to decide their own package restore strategy?

This way consumers of nuget can align nuget behavior to their own business strategies, be they conservative or aggressive.

What I don't understand is why Microsoft has to decide this for consumers in the first place.

To me this is a straight up consumer decision based on private business strategy and policy.

It makes absolutely no sense why a tool vendor should allow themselves to unilaterally decide business strategy for all nuget consumers on the planet without an option to override that.

It's been two years and there's no apparent movement on this issue.

Leave lowest version as the default strategy if you want Microsoft, but for goodness sakes offer a switch to allow consumers to make their own business decisions.

TysonMN commented 5 years ago

I don't have any long-term need for the -DependencyVersion option. I was confused about how some aspects of NuGet package management work.

In the process of trying to remove binding redirects from my code, I thought a good solution was to request Serilog.AspNetCore change their dependencies. (I now know this was a bad idea.) The first response I got was to try Install-Package Serilog.AspNetCore -DependencyVersion Highest. But that didn't do anything different for any argument to -DependencyVersion (because, I know now, I am specifying my NuGet package dependencies via PackageReference tags in the project file...per the present issue). When I asked why in this GitHub project, I was pointed to the present issue.

To help others like me, a new issue was created suggesting that a warning be given when -DependencyVersion is used with PackageReference-specified NuGet package dependencies (at least, until the present issue is resolved).

While I have the attention of a NuGet expert, here is one thing that I think might be helpful to me. How can I "see" the NuGet dependency graph of my solution? Specifically, if some project in my solution depends on the same NuGet package (potentially with different version constraints), I would like to know what all the paths in the NuGet dependency graph are to that NuGet package as well as the version constraint contributed by each of these paths. The goal is to figure out a better way to handle duplicate indirect dependencies than a binding redirect (such as making this indirect dependency into a direct dependency and to picking the desired version). Does that all seem reasonable to you?

My plan is to understand this well enough that I can give a talk a my company to help everyone improve their NuGet package dependency management.

anangaur commented 5 years ago

While I have the attention of a NuGet expert, here is one thing that I think might be helpful to me. How can I "see" the NuGet dependency graph of my solution? ...

One of the ways is to run dotnet list --include-transitive. This funtionality is not yet available with Visual Studio, but we will get there.

The other part is to understand why a specific version was selected. We do not have a mechanism to show this information, but may be having a why command would help here. Alternatively, you can look at the lock file to figure out what was requested vs. what got resolved , but this requires parsing of the lock file.

TannerBragg commented 5 years ago

I don't understand the danger in allowing package mantainers to add additional options to their csproj files to specify the dependency resolution strategy. At my workplace, minor version never break code and we always want to use the latest minor version. If we need to lock to a specific version for a specific build, we would use the lock file.

Any traction on this issue? It's outstanding. It's desired. Why are we being ignored? Does someone have the CEO's twitter? I hear bad publicity on Twitter gets fast responses.

tebeco commented 4 years ago

hello there i think i can't just repeat thing that are already on the thread i have also issue for example with Serilog that has many Microsoft.Extensions.Xxx as transitive in 2.x being pulled down to aspnetcore3.1 i let you guess the disaster

(Some PR were rejected on Serilog to update to msft.extensions.xx 3.1.x)

it forces us to pin down transitive explicitly we are re-creating one of the biggest issue package.config had => having both direct and transitive pinned per project

i would really love to see this land as aspnetcore3.1 is now netcoreapp3.1 BUT depends on msft.exrension 3.1 that are netstandard2.0, unless all third part updates the default behavior will attempt to get 2.x as potential transitive in 3.1 apps

davidfowl commented 4 years ago

@TannerBragg do the things you depend on have the same guarantee?

tebeco commented 4 years ago

sorry about pushing that topic again, is there any info on how to to get that Highest resolution for transitive from an MsBuild Props today ? especially when using [*, ) and lockfile properly.

For example : If you depend on Serilog You would get transitive resolution of some Microsoft.Extensions.xxxx (like logging) to 2.x while the Host project is aspnetcore / netcoreapp3.1 It seems to happen because serilog also depends on Microsoft.Extensions.xxx >= 2.1 but the resolution defaults to "Lowest" for example As it is open on the right, i would love to have a switch in my sources.props to be able to choose how i want that resolution to happen so i can try whatever suits my needs

AgSync-Aaron commented 4 years ago

First, let me say I have nothing to add to this conversation. I would just like to be able to use Install-Package -DependencyVersion Highest [package_id] for .NET Core projects. I've been manually installing dependencies when I want to force the latest version and that's a PITA. Thanks for the work you do. I just wish this issue was on the list.

springy76 commented 4 years ago

@tebeco The pity is that between most Microsoft.Extensions.*.Abstracts v2.x and v3.x there is no single breaking change, so in SemVer-thinking there should be no major number change at all. But on the other hand I don't want different NuGet versions of netcore parts so I can use a single build variable to update them all, for example from 3.1.4 to 3.1.5.

TysonMN commented 4 years ago

You are applying the converse of SemVer rule 8 instead of rule 8 itself. SemVer allows the major version to be incremented for any reason (as long as the minor and patch versions are reset to 0.)

For example, I think it would be appropriate to increment the major version level if the code was totally rewritten (maybe even in another language) while keeping the API (and even all behavior) unchanged.

reiseder commented 3 years ago

Are there any updates on this issue?

It would save a ton of work for releasing well maintained internal packages at my company.

tebeco commented 3 years ago

I can only suggest anyone to upvote the first comment / issue in this issue, as it seems to be the relevant metrics being used to prioritize how much user want something to move on activity is hard to quantify by bot (because spam / irrelevant etc ...) while a +1 is quite clear

ChaseFlorell commented 3 years ago

I mean, 4 years old, perhaps it's just not a priority.

markusschaber commented 3 years ago

Is the NuGet team open for pull requests?

rdeago commented 3 years ago

Is the NuGet team open for pull requests?

Looks like they are. https://github.com/NuGet/Home/blob/dev/CONTRIBUTING.md

IanKemp commented 3 years ago

Still waiting for this critical feature, Microsoft!

mikamins commented 3 years ago

If there's no way to override the lowest version behavior, how are people expected to deal with security vulnerabilities in transitive dependencies?

As a concrete example, Azure.Core has a dependency on System.Text.Encodings.Web 4.6.0 which is susceptible to remote code execution. Even though the issue was fixed in System.Text.Encodings.Web 4.7.2 almost a year ago, I get the vulnerable version if I consume the latest Azure.Core.

RandyT97 commented 3 years ago

If there's no way to override the lowest version behavior, how are people expected to deal with security vulnerabilities in transitive dependencies?

As a concrete example, Azure.Core has a dependency on System.Text.Encodings.Web 4.6.0 which is susceptible to remote code execution. Even though the issue was fixed in System.Text.Encodings.Web 4.7.2 almost a year ago, I get the vulnerable version if I consume the latest Azure.Core.

Hi @mikamins , I actually ran into the same issue with specifically : "Microsoft.ServiceFabric.AspNetCore.Kestrel 4.2.477" => "Microsoft.ServiceFabric.AspNetCore.Abstractions 4.2.477" => "Microsoft.AspNetCore.Http.Abstractions 1.0.0"=>"System.Text.Encodings.Web 4.0.0":

I resolved this by adding System.Text.Encodings.Web 4.7.2 as a direct dependency of the msbuild project, and it will cause all lower level dependencies to reference v4.7.2 instead of v4.0.0

rdeago commented 3 years ago

@RandyT97 while your workaround of course works, it solves the problem for a specific package. Your project could well have other transitive dependencies suffering from the same problem without you even being aware of it.

Besides, a few months from now, anyone working on the project (or even some automatic tool) may remove the direct dependency on System.Text.Encodings.Web because it is not used directly, everything builds just fine without it, so why have it around?

springy76 commented 3 years ago

net5 now totally f*cked up it just from the start. Being now at 5.0.4 some newest packages are at 5.0.3, 5.0.2, 5.0.1, 5.0.0, and some other versions. And it doesn't matter whether I use 5.0.4 packages on 5.0.0 runtime or 5.0.0 packages on 5.0.4 runtime. All combinations just work and I can't tell the build server that this all probably is just wrong and smelly bullshit.

HugoLemieux commented 3 years ago

A lock file has been introduced in order to properly do this with PackageReference. Are there any updates on this issue?

canfucius commented 3 years ago

So is this issue fixed? And will there be documentation to show how to properly handle float versioning throughout an entire project?

tebeco commented 3 years ago

the title is about direct OR TRANSITIVE so it's still not possible no

also you can't decide about a strategy AT ALL, you have to go manually edit every single dependency one by one as a text file and replace digit with * like when you use dotnet add package it won't care about other package using wildcard it will put the full version down

as for the lockfile, did they fixed

Flavien commented 2 years ago

Can we hear from the NuGet team? Is this:

JonDouglas commented 2 years ago

Hi all,

I'm going to write a message here for now because this issue hasn't had a reply from the team in quite some time. I apologize in advance.

This issue is currently the 3rd đź‘Ť most upvoted issue in our client repository. There are many considerations to take into account for the behavior of package resolution that have already been discussed amongst everyone here and known workarounds & features that help you be more deterministic when resolving packages(especially with regards to security).

I want to be transparent with everyone and tell you that from my perspective(PM on the NuGet team), this issue is important but we currently do not have a plan for it. What that means is that we believe there are other critical work to complete this year prior to getting time to invest into this (and the consideration of capacity). This can change however.

We also need to understand this issue further, the current pain points, and know what is possible for the product given many of the previous blockers have been implemented or have plans to be(i.e. lock files / package overriding / etc) and the limitations we have.

Your feedback on how we can move forward with this issue and your ideal happy paths in your daily management of dependencies have already helped us tremendously. Please feel free to keep commenting on your ideal experiences so we can make the best solution. Knowing the desired end goal/experience will keep us headed in the right direction.

I am currently working with our teams to produce a year's living roadmap to clue everyone in on what we have planned for 2022. When we publish this, please provide your feedback so we can understand how this issue weighs in comparison to other highly requested features. This will help us get our plans right and be more community driven.

Thank you.

AgSync-Aaron commented 2 years ago

Thank you for providing an update, even if it is unfortunate news.

Flavien commented 2 years ago

Thanks, appreciate the update, and glad to know it's at least (somewhat) on your radar.

HugoLemieux commented 2 years ago

The ideal experience would be to resolve the transitive dependencies with a defined resolution strategy and consolidate the transitive dependencies for a solution because the lock file is by project.

JonDouglas commented 2 years ago

@HugoLemieux In the meantime, how would that look in your current development experience? What type of CLI flags, VS UI, or other happy paths would allow you to do that?

Consider the ability to:

  1. Decide the dependency resolution strategy for both direct & transitive levels.
  2. Override or set an exact version for transitive packages.

How would you like to express that in your configurations today?

HugoLemieux commented 2 years ago

It would be great to have the same experience as it was with the packages.config.

In order to resolve the transitive dependencies with a defined resolution strategy:

The VS UI in order to consolidate all the dependencies (direct and transitive) for a solution: image

I think these could work using lock file by project.

nicolascotton commented 2 years ago

We would like to have better control and cohesion between the versions of our dependencies (transitive included) across multiple projects (workspace/solution). This could be done with a global lock file and a granular control of the transitive dependencies within.

idg10 commented 2 years ago

One particular scenario that causes us to want something like this might be worth calling out as a special case: it's the fact that every single package in Microsoft.Extensions.* revs every single time there's an update to .NET whether anything has changed in a package or not. We have 40 odd open source libraries that we maintain, and every week or so we get a deluge of Dependabot notifications telling us about the zillion places in which it thinks we should update one of these packages.

So what we'd really like is some way to express the policy that we always want the latest available patch of those components by default. The combination of Microsoft's high standards for backwards compatibility plus the fact that most of the time a new patch version on one of these components hasn't changed anything of substance means that we basically always want to take the latest version of these, but tend to want to be deliberate about everything else.

(Alternatively, if these packages would only drop new patch versions when something has actually changed, that would be much better. I wouldn't be drowning in dependabot requests, and I'd also know when there is actually a meaningful change.)

viceice commented 2 years ago

Would be nice to have the dependencyVersion^1 option again, so every body can decide which updated to get

philipborg commented 1 year ago

My issue is in large part that there is no pretty way to solve outdated transient dependencies, especially when there is a critical security issue which is often. If I want to update the transient dependency I currently need to add it as a direct dependency, even though I have no actual direct dependency on it. This both bloats the project file, confuses the hell out of any project readers and observations of dependency trees either using tools or lock files.

I would prefer to be able to set both default transient dependency resolution and/or (preferably and) override transient dependencies in a clearer manner which doesn't add it as a direct dependency. Ideally for specific transient dependencies.

tdhintz commented 1 year ago

It's crazy that there is no plan articulated for this problem. Our vulnerability scanners check dependencies and report problems on dependencies we don't even deploy. Manually managing these alerts is not practical. Automation is needed.

AgSync-Aaron commented 1 year ago

It's crazy that there is no plan articulated for this problem. Our vulnerability scanners check dependencies and report problems on dependencies we don't even deploy. Manually managing these alerts is not practical. Automation is needed.

Take a hintz! Microsoft will never fix this issue until there is some bad press about it. Microsoft is being apathetic to the risk they are putting their own customers in, in regard to critical vulnerabilities.

Maybe this project can become mainstream... https://fsprojects.github.io/Paket/

davidfowl commented 1 year ago

I just re-read this, and there's been lots of changes to nuget since this was filed ~5 years ago. Have the problems changed? There are now lock files and central package management that allows you to control the resolution of packages whether they are transitive or not.

I don't want to come off as being "paternalistic" and I want developers to have control, but package dependency resolution requires a global view of the world (the world being your project's transitive closure). Packet had to work around many assumptions in how package versioning works, and some strategies will never work with certain packages.

What might help move this forward are examples of problems and existing workarounds. That would help narrow down how the existing tools have gaps. Some questions on the top of my head:

  1. Where do you specify strategy, and where would it be persisted?
  2. How do you specify this for transitive deps and where is it persisted in that case?
  3. What's the granularity of specifying this strategy?
  4. When does NuGet decide to check for updates? This probably needs to be an explicit gesture (we must be solving this problem today).
  5. Does this mode require a lock file? If not, I guess the assets file can be used in place while it exists?
  6. Is this something that is only expressed when consuming packages or also when building them? Or is it both?
giggio commented 1 year ago

@davidfowl

  1. .csproj (npm style which is already well understood, with ~ and ^)
  2. through command line, persisted in lock file
  3. can you elaborate? what do you mean?
  4. NuGet never updates anything until the user requests it, for restores it uses the information it has from .csproj and a lock file, if it exists
  5. no, but it can help, see item 2
  6. I'm not sure about this one, but probably both, so behavior is consistent between uses
tdhintz commented 1 year ago

@davidfowl

  1. We specify a NuGet config in the build pipeline with the specification we want.
  2. The NuGet configuration file referenced through the command line in the build YML.
  3. My desire is that the transitive policy applies to all transitives, regardless the source.
  4. When I run the restore command (via the YML).
  5. ?
  6. When the restore is run using the NuGet configuration I specify.
mcm-ham commented 1 year ago

It's crazy that there is no plan articulated for this problem. Our vulnerability scanners check dependencies and report problems on dependencies we don't even deploy. Manually managing these alerts is not practical. Automation is needed.

I'm in the same boat, however there are other approaches that could be implemented for this specific concern, I've suggested these in a separate ticket https://github.com/NuGet/Home/issues/12341

clyvari commented 1 year ago

I stumbled upon this discussion looking to do exactly as the OP stated, however reading the discussion and thinking long and hard about it, I definitely changed my mind: I don't think this feature is really needed nor desirable as stated, but I think some tweaks to the current features could help.

Keep in mind I'm talking only about transitive packages, since we have the ability, to specify Version=* in *.csproj files for direct packages. It's about the ability to configure one way or the other the resolution for transitive packages of a dependency you have.

Security

I think relying on "highest possible" dependency version resolution for security is a terrible idea, since there is absolutely no guarantee you will get a version without security issues. And assuming we could specify * for a transitive dependency version, there is no guarantee you will get the latest version anyway. So that would be something that makes you think you are getting the latest and greatest patched versions of everything, when in fact you do not. The security argument is, in my opinion irrelevant.

--

Another point: we can classify packages in two types.

Self-contained packages

I don't think there is a need to change anything. As long as they work, they work, even if the version used is "ancient". And if you do rely on specific optimizations or features of a transitive package, well it should definitely be part of your direct project dependencies.

External resources packages

There is usually NO good reason to use an older version of those packages. Most of the time, you do want the latest package possible. There is usually only 1 instance of a Web API you want to consume, that definitely works with the latest packages, and most definitely do not work with older packages. And for those packages, even tough the code interface did not change, it is entirely possible that internal changes produce different Requests to the External API: Even though your code can compile AND run without exceptions, it might not work the the resource you want to consume.

So those packages sound like a good candidate for the feature. However, those packages are well identified, you definitely know which resources you are consuming (or else you have more pressing concerns), and can already use Central Package Management Transitive Pinning to tell which version you want (but you cannot at the moment specify Version=* in central package management, which is one of my suggestions). But most likely, they should be included as direct dependecies of your poject, see suggestion 2).

TL;DR: I think we only really need custom transitive dependency resolution for a small well known subset of packages, allowing global "Highest"-version for transitive packages will cause more trouble than it is worth.

--

So then, a couple of suggestions:

1. Allow floating versions in Central Package Management (CPM)

Basically allow the exact syntax we have in *.csproj at the moment. Using floating versions at the moment result in error NU1011. Maybe only allow floating versions when packages.lock.json is enabled. CPM does work with package lock, so I don't see any blocker.

2. Add a .nuspec option to mark some dependencies as "direct"

It helps solves the issue for packages that depend on an "API nuget".

Exemple: An helper library (Lib1) that simplifies working with an Azure API. This helper library has a dependency on an Azure API Nuget (Azure.X.nupkg).

As a Nuget publisher, my package (Lib1.nupkg) works for the foreseeable future, with version >= 2.0.0 of Azure.X.nupkg. I would like to mark this dependency as "direct", so a user of my helper library has more control over this dependency. As consumer of Lib1, I want to be able to easily control the Azure.X dependency and update it when needed.

With the new .nuspec "direct" dependency option, as a consumer of Lib1, adding Lib1.nupkg to my project would add Lib1 as a direct reference, but also Azure.X as a direct dependency, instead of a transitive one.

My *.csproj would look like this after adding only Lib1 :

<Project Sdk="Microsoft.NET.Sdk">
  <!-- ... -->
  <ItemGroup>
    <PackageVersion Include="Lib1" Version="1.0.0" />
    <!-- Below was added automatically, this dependency is less hidden and I can easily mark it as floating if I wish to. -->
    <!-- "direct" dependencies in Azure.X package (if any) should recursively follow the same logic, and be included here -->
    <!-- Since it's not a transitive dependency, I will easily be able to update this package -->
    <PackageVersion Include="Azure.X" Version "2.0.0" />
  </ItemGroup>
</Project>

Nuget that should be referenced directly because they are "important" to your project can now be automatically included. When there is an update to this package, I will be prompted to update this dependency in the future.

3. Warn if my code use transitive package code

I'll keep this one short since it's not related to Nuget directly: I should not be able to use code existing only in a transitive dependency without at least a warning, hinting me at including the package I'm using as a direct dependency.

--

Having thought about all the use cases I have met, I think those first 2 suggestions would cover pretty much everything, and allow me to be pretty confident in the management of my transitive packages.

voroninp commented 1 year ago

@clyvari If this strategy can be set individually for each dependency/package source, I'd turn it on for packages in my private feed, so whenever minor or patch get bump, packages are automatically updated.

clyvari commented 1 year ago

@voroninp That's already possible for direct dependecies of your projet. If you add a depency with Version=2.*, you will automatically use the latest version possible that is <3.0. It's only an issue for transitive dependencies, when you add a nuget Lib1 that itself uses, say, System.Text.Json. You don't really care what version of System.Text.Json Lib1 uses, as long as it works. And if you do, well that means you care enough about System.Text.Json to add it as a direct dependency of your project.

voroninp commented 1 year ago

@clyvari , let's replace System.Text.Json with MyLib and imagine larger (deeper) dependency graph.

Now imagine, we found a bug in MyLib.

How many manipulations/rebuilds are required to update end project with the fixed MyLib depending on resolution strategy?

clyvari commented 1 year ago

@voroninp Assuming a bug in any dependency, at the moment you can (and probably should) use CPM with Transitive Pinning. It's 1 commit to the Dependency.Packages.props file, and 1 build.

If at the root of a solution, it will be common to all projects in a solution, useful if the dependency is used in multiple projects.

Here is why using "highest possible" resolution strategy isn't sufficient : Let's assume you have a several packages referencing VulnerableLib. One requires VulnerableLib Version=[5.2, ), another VulnerableLib [5.0, 5.7). Latest VulnerableLib version is 5.7 You specify "Highest possible version" as a resolution strategy.

The version that satisfy your requirement is 5.6. Let's say a bug is found in VulnerableLib 5.x versions, fixed in version 5.8

Despite your "Highest possible version" as a resolution strategy, VulnerableLib will still resolve to vulnerable version 5.6.

And worse, because it is not intuitive (the version requirements might be deep down the dependency tree), you might be mislead into thinking: "VulnerableLib was bumped, all my projects use "Highest possible version" for transitive packages, I'm safe."

tdhintz commented 1 year ago

Its true that “highest possible” doesn’t always fix the vulnerability, but in my experience it fixes most. An audit report will tell you if it didn’t fix something and enables you to focus on the less easily resolved issues.

voroninp commented 1 year ago

@clyvari > another VulnerableLib [5.0, 5.7)

I'd question first this range ;-)

seanamos commented 1 year ago

I never understood why Nuget had to re-invent the wheel here and come up with this bonkers system that we now sit with.

It's confusing for users coming from anywhere else and almost ensures you are going to have security vulnerabilities, even though patches are available. It's also encouraged an ecosystem where only a minimum version constraint is specified on dependencies, MS packages being a prime example of this.

Pre-dating Nuget, package managers had some simple concepts:

  1. There is a lock file for repeatability.
  2. Packages specify their dependencies.
  3. Those dependencies have a minimum and a maximum version constraint.
  4. Maximum compatible versions are chosen by default.
springy76 commented 1 year ago

NuGet developed (or maybe always was) into a new kind of DLL hell - source of random "Method not found" exceptions at runtime (can't the exe-compiler or at least the publish task just check everything once?)

I'm just right now adding the net6 package ErikEJ.EntityFrameworkCore.SqlServer.DateOnlyTimeOnly to a net7 project which already uses EFcore.SqlServer 7.0.x, the package itself only to extend EFcore.SqlServer 6.0.0+

Thats what "Preview Changes" tells me:

Uninstalling:

Microsoft.Win32.Registry.5.0.0
System.Globalization.4.3.0
System.IO.4.3.0
System.Reflection.4.3.0
System.Reflection.Primitives.4.3.0
System.Resources.ResourceManager.4.3.0
System.Threading.Tasks.4.3.0

Updates:

Azure.Core.1.24.0 -> Azure.Core.1.25.0
Azure.Identity.1.6.0 -> Azure.Identity.1.7.0
Microsoft.Data.SqlClient.5.0.1 -> Microsoft.Data.SqlClient.5.1.0
Microsoft.Data.SqlClient.SNI.runtime.5.0.1 -> Microsoft.Data.SqlClient.SNI.runtime.5.1.0
Microsoft.Identity.Client.4.45.0 -> Microsoft.Identity.Client.4.47.2
Microsoft.IdentityModel.Abstractions.6.21.0 -> Microsoft.IdentityModel.Abstractions.6.24.0
Microsoft.IdentityModel.JsonWebTokens.6.21.0 -> Microsoft.IdentityModel.JsonWebTokens.6.24.0
Microsoft.IdentityModel.Logging.6.21.0 -> Microsoft.IdentityModel.Logging.6.24.0
Microsoft.IdentityModel.Protocols.6.21.0 -> Microsoft.IdentityModel.Protocols.6.24.0
Microsoft.IdentityModel.Protocols.OpenIdConnect.6.21.0 -> Microsoft.IdentityModel.Protocols.OpenIdConnect.6.24.0
Microsoft.IdentityModel.Tokens.6.21.0 -> Microsoft.IdentityModel.Tokens.6.24.0
Microsoft.NETCore.Platforms.5.0.0 -> Microsoft.NETCore.Platforms.1.1.0
Microsoft.Win32.SystemEvents.5.0.0 -> Microsoft.Win32.SystemEvents.6.0.0
System.Buffers.4.5.1 -> System.Buffers.4.5.0
System.Configuration.ConfigurationManager.5.0.0 -> System.Configuration.ConfigurationManager.6.0.1
System.Diagnostics.DiagnosticSource.5.0.0 -> System.Diagnostics.DiagnosticSource.6.0.0
System.Drawing.Common.5.0.0 -> System.Drawing.Common.6.0.0
System.IdentityModel.Tokens.Jwt.6.21.0 -> System.IdentityModel.Tokens.Jwt.6.24.0
System.Runtime.Caching.5.0.0 -> System.Runtime.Caching.6.0.0
System.Security.AccessControl.5.0.0 -> System.Security.AccessControl.6.0.0
System.Security.Cryptography.ProtectedData.5.0.0 -> System.Security.Cryptography.ProtectedData.6.0.0
System.Security.Permissions.5.0.0 -> System.Security.Permissions.6.0.0
System.Text.Encoding.CodePages.5.0.0 -> System.Text.Encoding.CodePages.6.0.0
System.Windows.Extensions.5.0.0 -> System.Windows.Extensions.6.0.0

Installing:

ErikEJ.EntityFrameworkCore.SqlServer.DateOnlyTimeOnly.7.0.1
System.Runtime.CompilerServices.Unsafe.6.0.0

It's a wild mix of up- and downgrades, outtake:

Microsoft.NETCore.Platforms.5.0.0 -> Microsoft.NETCore.Platforms.1.1.0
Microsoft.Win32.SystemEvents.5.0.0 -> Microsoft.Win32.SystemEvents.6.0.0
System.Buffers.4.5.1 -> System.Buffers.4.5.0

I can just only hope this has no serious effect on the final app.

yanivru commented 1 year ago

In my company, we develop several nuget packages and consume them in other programs. E.g. P1 <- N1 <- E1 Program1 (P1) references internal nuget N1 that references some external nuget (E1). When I fix bugs in N1 we increase the patch part of the version.

P1 references N1 with floating version (e.g. 1.*). So that P1 (and all other Ps) will take all the bug fixes automatically in next build.

Now if a newer version of E1 was released (e.g. 1.0.1), we want P1 to get it (cause it's might contain a bug fix, or security fix). What we usually do is update N1 to reference the newer N1 (1.0.1), otherwise, we will need to go over all the consuming projects (P1, P2, …) and reference E1 (1.0.1) directly, which is ugly and time consuming.

But since P1 might be directly refencing older version of E1 (1.0.0) it might cause a warning of package downgrade, and because treat warnings as errors it breaks P1.

So eventually the change to N1 is a breaking change. Which is not ideal. Either we break some builds or we increase major of N1 each time we change some minor version of some referenced nuget package (time consuming cause all P's need to be changed).

Is there a better way to do it, that will solve both problems?

What I would like to do is that N1 references the minimum version it requires (e.g. E1 1.0.0) and when P1 is compiled it takes the highest E1, with the bug fixes. This way there won't be a package downgrade error and still the fixes will arrive to all refencing programs (Px). This is not feasible currently since there is no "Biggest major" dependency resolution.

We don't really care about deterministic builds. Our builds are not deterministic anyway, since we use floating versions and for other reasons.

brentthierens commented 1 year ago

Long time no response anymore, any update on this? I really need to be able to use the latest minor version of dependencies without having to recompile all other packages