NuGet / Home

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

[PackageReference] Centrally manage NuGet package versions for a solution or a repo #6764

Closed anangaur closed 2 years ago

anangaur commented 6 years ago

PackageReference enhancements are summarized as part of this Epic issue: https://github.com/NuGet/Home/issues/6763

tebeco commented 3 years ago

The error message X does not contain an inclusive lower bound ... means that the attempted PackageReference did not found any associated version. So there's either

roji commented 3 years ago

@tebeco please read my above message carefully - things work just fine when doing dotnet build (implying that there's no typo), but fail when doing dotnet msbuild.

tebeco commented 3 years ago

You are right, I should have be more precise,

as it's working for me here I wondered about possible known edge case I stumbled upon in the past

Can you provide a repro ?

Here is one of the repository that was linked in this issue: https://github.com/dotnet-experimentations/CentrallyManagingNuGetPackageVersions I just made few changes right now to make sure it's working with multiple TFM

@roji can you confirm that this repo works for you ?

eg:

Sdk 4.1.403:

wildcard (ok):

image

"known bound" (warning)

image

SDK 5.x

Wildcard

Very weird behaviod of dotnet msbuild :D but dotnet restore output the same error msg than dotnet build

error NU1011: Centrally defined floating package versions are not allowed.

image

Known bounds

image

I attempted to see but I'm just poking around in the dark here and could not reproduce the difference of behavior. I managed to have the same warning as you, but when I do, both command seems to output it

roji commented 3 years ago

@tebeco apologies, after looking more closely, dotnet msbuild does seem to work from the command-line for my case; this seems to be more of an IDE-related issue (I'm using Rider). I'll investigate further.

tebeco commented 3 years ago

Arg, this is not going to be fun :s

I hope you find something working for you

zivkan commented 3 years ago

Will this be the default behavior for VS/Nuget management of packages?

It wasn't originally the plan to, but depending on feedback, it could change. Of course, that'd raise a whole bunch of questions about how to make it default without risking breaking projects/solutions. But that's all part of the product development process. But since the feature is still in early preview, I think it's much too early to work out "on by default" problems.

On the topic of being in preview, we're supposed to show a warning message on every restore. It looks like it's not working on the dotnet cli, probably because it has a lower default verbosity level than msbuild.exe. I'll need to get this fixed.

tebeco commented 3 years ago

Will this be the default behavior for VS/Nuget management of packages?

It wasn't originally the plan to, but depending on feedback, it could change. Of course, that'd raise a whole bunch of questions about how to make it default without risking breaking projects/solutions. > But that's all part of the product development process. But since the feature is still in early preview, I think it's much too early to work out "on by default" problems.

Well this is a general issue that can be observed from years now. If the craftmanship does not comes from Microsoft it is not going to be an adopted standard. So this would definitly be a good thing in the long run that "clean architecture" is being promoted by Nuget Team and Vs Teams:

stevenbrix commented 3 years ago

Of course, that'd raise a whole bunch of questions about how to make it default without risking breaking projects/solutions. =

Well this is a general issue that can be observed from years now. If the craftmanship does not comes from Microsoft it is not going to be an adopted standard.

💯. I can't stress how much MS needs to have conviction in the tech we build and guide users down the right path.

This one seems fairly easy to make the default. Does this feature support more than one Directory.Packages.props (like Directory.Build.props)? If so, VS could detect which projects all have the same packages versions and the next time you update packages in VS, drop the files on disk where they will keep your projects on the same packages.

For example if you have the following structure:

-src
  -proja
  -projb
  -projc

if they are all on the same packages, you just drop this:

-src
 Directory.Packages.props
  -proja
  -projb
  -projc

If they don't, then you do something like this:

-src
 Directory.Packages.props
  -proja
   Directory.Packages.props
  -projb
  -projc

At a minimum, if that can't make work because there are edge cases that I don't know of, then a newly created .sln should drop the file on disk. Or there could be a checkbox in the VS Package Manager settings UI. Or even new Items in the "Add New Items" dialogue in VS. I've always felt there needs to be a set of MSBuild items for Directory.Build.props/targets, so it would make sense to have one for Directory.Packages.props as well.

jmecosta commented 3 years ago

comment regarding the override version in project file. Can u instead of have an additional file in the project Directory.Packages.props have override specifiers directlry in the csproj? This is a more clear approach for the end user. since they dont need to guess there is another file they need to bother.

https://github.com/Microsoft/MSBuildSdks/tree/master/src/CentralPackageVersions got it right in my opinion....

kzu commented 3 years ago

I absolutely think that having something like a VersionOverride in the .csproj is the best thing for that scenario. Agreed with @jmecosta .

tebeco commented 3 years ago

Can u instead of have an additional file in the project Directory.Packages.props have override specifiers directlry in the csproj ?

Warning: do NOT use Directory.Build.props for version but Directory.Build.targets You're going to have trouble if you cross target : TargetFrameworks + TargetFramework in various project and when you'll have like:

<ItemGroup Condition=" $(TargetFramework) == 'net5.0'">
  <PackageReference ...... />
</ItemGroup>

props are imported/interpreted at the beginning of the files (csproj, ...) while targets at the end, so if you use props, then, you will have situation where TargetFramework is null/empty

CPMV is also impacted by this, and this feedback was raised, but not concidered "yet" for the current implementation I hope that we won't have another overlay to handle TFMs specifically for CPVM, but just straight native support for TFMs and version will be computed properly from targets, and that every TFM declare will create a group automagically

kzu commented 3 years ago

I don't think it's highly relevant that the Directory.Packages.props is instead a .targets, since it just declares the items and it's conceivable useful to be able to override the version via the .csproj (i.e. with a PackageVersion Update="..." Version="..." Condition="...", which would be impossible otherwise (unless you runAfterTargets="CollectCentralPackageVersions"` or something like that).

So, overriding version in the csproj should already be possible, albeit in a more verbose way 🤔

Varorbc commented 3 years ago

Why does Vs have no related functions? Did I miss any configuration?

nkolev92 commented 3 years ago

@Varorbc

This feature is still under development, there's no VS experience yet.

Varorbc commented 3 years ago

@nkolev92 Thanks, is there any plan to release it?

nkolev92 commented 3 years ago

At this point we're evaluating the feedback we have received over the preview versions of the feature, so we can improve it and prepare it for it's final release.

GG123456932 commented 3 years ago

@nkolev92 hello, how can I test the option --force-version-update ? I tried with the following sdk versions

And none of these versions recognize the option --force-version-update

nkolev92 commented 3 years ago

@GG123456932

That functionality is not implemented just yet. Only the core functionality is available for preview at this point.

ghost commented 3 years ago

Adding this feedback here, as item #10700 was resolved duplicate

One of the major challenges of PackageReferences, one not addressed at all by the Microsoft.Build.CentralPackageVersions nuget, is upgrading transitive package references due to security vulns. We were recently hit by CVE-2021-24112, and it was a major, multi-hour undertaking to track down all the transitive references to this package across our projects. It wasn't a simple matter of updating Packages.props to refer to version 4.7.1 -- libraries that didn't include an explicit reference to this transitive package were still downloading, building, and packaging the vulnerable version of the package.

A core requirement of this feature request is that it be able to centrally force upgrade of specific transitive package references.

ghost commented 3 years ago

@nkolev92

This feature is still under development, there's no VS experience yet.

This might surprise you, but some developers actually know how to write code, and not just point-and-click through wizards and templates.

Absence of this feature is posing an active security risk to our products. Is there any way we can adopt this feature with just a "command line" or "manually edit the configs" experience yet?

martincostello commented 3 years ago

Is there any way we can adopt this feature with just a "command line" or "manually edit the configs" experience yet?

Yes, you can add a Directory.Packages.props file to your solution root to define your packages, enable <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally> in either Directory.Build.props or your individual .csproj files, and then drop the versions from the PackageReference MSBuild items in your project files.

If you're happy to manually edit the files (e.g. with Visual Studio Code), then this has been available since at least June 2020 as long as you're also using a new enough version of the .NET SDK.

ghost commented 3 years ago

@martincostello

Does that include support for updating transitive references as well? We're currently already using the Microsoft.Build.CentralPackageVersions sdk with a Packages.props file, but that sdk specifically does not support updating transitive references, only direct references.

martincostello commented 3 years ago

I'm not sure on that specific feature of central package management.

ghost commented 3 years ago

Yeah, I'm chatting with @aortiz-msft and @nkolev92 now, and they both are indicating transitive package pinning is not available in any form in any release version of dotnetsdk.

tebeco commented 3 years ago

as long as the Wildcard are allowed back that will be nice

also hopping that it support XTargeting condition (aka: putting .targets file holding the condition for Version vs TF)

Directory.Packages.props

<PackageVersion Version="$(Foo)" ... />

Directory.Build.targets

<Foo Condition=" '$(TargetFramework ... = 'ns2.0' ....
martincostello commented 3 years ago

as long as the Wildcard are allowed back that will be nice

Yeah, that was slightly painful with trying out the later .NET 5.0 previews when the instructions in the blog post to just do 5.0.0-rc1.* stopped working.

tebeco commented 3 years ago

I would not say slightly using wildcard basically allow you to always have patches for free or even minor change (so non-breaking)

combining that with msbuild could also force lock file on CI and wildcard on major locally (aka: on local repo covered by unit test) with auto re-compute and get latest of major

and could even do nightly equivalent of dependabot just by running --force-evaluate instead of --locked-mode so backed by both lockfile + full CI

at least make it an OPT_IN flag is you want to disable by default

🤷‍♂️

dominoFire commented 3 years ago

Mentioned in https://developercommunity.visualstudio.com/t/VS2019-has-regression-after-169--Centr/1388352

jimmylewis commented 3 years ago

@dominoFire I would hazard a guess that the VS Feedback item is about this, not the NuGet CPVM feature.

HeikeHofmann commented 3 years ago

We had opened a issue for VisualStudio 2019 V16.9.x (16.9.0-16.9.3): https://developercommunity.visualstudio.com/t/ManagePackageVersionsCentrally-does-not/1371228

But it was closed with forward to this nuget issue 6764. I readed this nuget issue here and dont understand one part. Why was transitive restore working with VS 2019 V16.8.x ? We have an own ProGet Server, where we store only a part of all existing packages, because we need validated environment for medical devices. If we configure package versions in the file Directory.Packages.props, than this package version should be used also for transitive references. But since VS2019 16.9.x, it is not working anymore. (for example: we add newtonsoft.json at directory.packages.props with version 12.0.3. but netcoreapp3.1 unittest projects will restore version 9.0.1, if this package is not added as packagereference in these unittest projects. That means, transitive restore will ignore the directory.packages.props since VS2019 16.9.x)

tompazourek commented 3 years ago

@HeikeHofmann The "transitive dependency pinning" part of CPVM was disabled recently in #10132, which got into NuGet version 5.9, which got into MSBuild version 16.9, which got into VS version 16.9...

See my comment here: https://github.com/NuGet/Home/issues/10389#issuecomment-791475359. I'm as unhappy about this as anyone, because the need for consolidating transitive dependency versions and direct dependency versions was the reason why we adopted CPVM in the first place.

EDIT: In general, I think the changes between VS versions are poorly communicated... We had lots of issues with the VS 16.8 to VS 16.9 update. For example, various MSBuild props work differently for non-SDK-style projects under 16.9 compared to 16.8, and the only way we found out about it was to diff the installed files collected from users with different versions.

About the NuGet changes, you can actually read about this in the release notes: https://docs.microsoft.com/en-us/nuget/release-notes/nuget-5.9. It's too bad the release notes were published a week after the actual release when we've already spent lot of time diagnosing and fixing the issues.

I don't know if there are also release notes for MSBuild 16.9 (similar granularity as the NuGet 5.9, which are great and detailed), but if anyone has a link, it would be really useful.

ds1709 commented 3 years ago

Transitive dependencies is big problem for developers. It's pain to debug applications with big bunch of projects. Every time you update any nuget package version or add new dependency you are at risk of crash with assembly loading exception. More then, you dont know all transitive dependencies, so, when it happens, you should analyze all dependencies for all projects to find conflicting dependency manualy. Based on this issue open date, problem persists more then two year. The situation is very disappointing.

tebeco commented 3 years ago

Yet again I would love to have an Opt In for that feature ... and as a reminder dotnet is suppose to have lockfile

so if one think that floating transitive on latest is an issue ... just enforcing lockfile for that feature would fix point raised previously

if lockfile are flacky then this needs to be also addressed at some point 🤷‍♂️

I really think that together

could come work nicely

ghost commented 3 years ago

Lock files only cover resolved packages, not restored packages. We already saw cases where lockfiles failed to detect downloading of the wrong package version, only because a closer dependency ended up resolving a closer package version. Packages which are restored but not resolved don't end up in the log file. :S

This might be by design, but it's putting a lot of faith in the resolution mechanism to be deterministic.

nkolev92 commented 3 years ago

We already saw cases where lockfiles failed to detect downloading of the wrong package version, only because a closer dependency ended up resolving a closer package version. Packages which are restored but not resolved don't end up in the log file

@aaronla-ms I'd love to learn more about that in a separate issue.

tebeco commented 3 years ago

Lock files only cover resolved packages, not restored packages.

this is part of what i'm trying to suggest Allow resolving transitive to the latest at the condition you also have to enable lockfile

on dev computer: resolve up to date / latest => update lockfile

on ci: just restore from lockfile

That way you have a repeatable and predictable CI while human have the ability to force the update you can also force the update on nightly trigger and create PR with bot

AroglDarthu commented 3 years ago

I'm trying to use this preview feature on one of our solutions. Do I understand correctly that is should be working with the latest bits of Visual Studio? I am using Visual Studio Professional 2019 Version 16.9.3. The about windows says it is using NuGet Package Manager 5.9.0

What I've done:

Opening the solution started a NuGet restore, with NuGet package restore failed for each project. In the error list it shows each project with an error NU1008 - Projects that use central package version management should not define the version on the PackageReference items but on the PackageVersion items: <LIST OF ALL PACKAGEREFERENCES IN Directory.Packages.props>.

Now if I run a Rebuild Solution all of these messages disappear and I get these instead: NETSDK1005 - Assets file 'C:\PathToProject\obj\project.assets.json' doesn't have a target for 'netcoreapp3.1'. Ensure that restore has run and that you have included 'netcoreapp3.1' in the TargetFrameworks for your project.

The Directory.Build.props contains a <TargetFramework>netcoreapp3.1</TargetFramework>. None of the projects overrides this setting.

I am at a loss here. Any ideas?

batzen commented 3 years ago

@AroglDarthu Inside Directory.Packages.props you have to use PackageVersion instead of PackageReference. Inside your projects you have to use PackageReference without Version.

AroglDarthu commented 3 years ago

You're a life saver. Can't believe I misread that!

AroglDarthu commented 3 years ago

Is it already possible to update a package via the CLI? My efforts thus far have resulted in updates of the project file and not the Directory.Packages.props.

martincostello commented 3 years ago

CLI and Visual Studio commands to manage packages aren't yet implemented. You need to edit them manually.

ds1709 commented 3 years ago

I have two project in my solution. The first one depends on GraphQL.4.2.0 and the second one depends on Microsoft.Extensions.DependencyInjection.5.0.1. Both packages transitively depend on System.Runtime.CompilerServices.Unsafe, but the first depends on version 4.7.1, while the second depends on version 4.5.3. ManagePackageVersionsCentrally enabled. In Directory.Packages.props I added package version System.Runtime.CompilerServices.Unsafe.4.7.1. When I rebuild the first project in output directory I got System.Runtime.CompilerServices.Unsafe.dll from package 4.7.1. When I rebuild the second project I got System.Runtime.CompilerServices.Unsafe.dll from package 4.5.3. This is my Directory.Packages.props

<Project>
  <ItemGroup>
    <PackageVersion Include="GraphQL" Version="4.2.0" />
    <PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="5.0.1" />
    <PackageVersion Include="System.Runtime.CompilerServices.Unsafe" Version="4.7.1" />
  </ItemGroup>  
</Project>

and this is screenshot of how dependencies resolves image So my question is: what I'm doing wrong, does centrally manage should work for transitive dependencies, and, if not, than why?

martincostello commented 3 years ago

So my question is: what I'm doing wrong, does centrally manage should work for transitive dependencies, and, if not, than why?

It doesn't work for transitive dependencies at the moment because it isn't implemented yet.

ds1709 commented 3 years ago

It doesn't work for transitive dependencies at the moment because it isn't implemented yet.

Thanks for quick response. Is there any plans to implement it, according to this issue or any other?

tebeco commented 3 years ago

Well at this point it's not a transitive anymore if you want to enforce the version of it. So you could Explicitly depend on it when you want it

This is also why there's another issue open asking for a Feature Flipping on Transitive resolution algorithm to allow transitive to resolve the "lastest compliant" one with the dependency tree.

And yes it "could" break ... just like anything could break (which is why it should be an opt-in) It should have a TransitiveRollforwardPolicy just like global.json for the SDK major/minor/patch

Also ... lockfile (instead of generating transitive constraint from nuget transitive, which should also be possible to disable with a Feature Flipping flag)

tebeco commented 3 years ago

@kalleOlaviNiemitalo, I understand it might not be convenient said like this, but one of the biggest issue I see is that if a decision is taken without a feature flag to enable / disable it, you're going to hurt lots of people.

As of today the Transittive Resolution is a good example of the long running problem, having a flag to choose if you want to allow something else to happen would open the door to fix redudant CVE by allowing "rollforward: Transitive" This is what the SDK team decided to do and the flag is existing inside global.json: see https://docs.microsoft.com/en-us/dotnet/core/tools/global-json?tabs=netcore3x#rollforward image

It's also possible today to use lockfile to have repeatable build so it would also secure your repository build with open rollforward. That's what paket managed to solved for few year and yarn npm ci and now dotnet restore --locked-mode

And the same way "emitting transitive" explicitly from a repo using CMPV could also just be a flag yes/no as it would allow more flexibility especially with lockfile, and if something like a rollForward would land on the transitive resolution algorithm

dominikjeske commented 3 years ago

This feature is in development quite long time – now it looks like there is no work on this so the question is – Are there any plans for releasing it? Is this approved or could never leave preview stage?

AroglDarthu commented 3 years ago

Is it possible to specify the private assets metadata in the Directory.Packages.props?

For instance, in my test projects I have a package reference for coverlet. Would be nice not to have to duplicate the PrivateAssets part in each test project when it could be mentioned once in Directory.Packages.props.

kwlin commented 3 years ago

@AroglDarthu according to faq not possible (2 bad): https://github.com/NuGet/Home/wiki/Centrally-managing-NuGet-package-versions#where-are-privateassetsexcludeassetsincludeassets-defined

tebeco commented 3 years ago

it's not very surprising since the PrivateAssets is suppose to let you control what's going to be "leaked" out and when you want the granularity to be possible per package => so it's per project nothing global OOB

now, as it's msbuild you could still use the standard way to do that I suppose create a Directory.Build.targets at SLN level and use <PackageRef... Update="name here" PrivateAssets="...." />

this is probably what you used before and that is still suppose to work out