dependabot / dependabot-core

🤖 Dependabot's core logic for creating update PRs.
https://docs.github.com/en/code-security/dependabot
MIT License
4.73k stars 1.02k forks source link

Specify Target Framework for .NET libraries #2733

Open cristipufu opened 4 years ago

cristipufu commented 4 years ago

Having this .csproj in my .NET library will try to update the dependencies that target netstandard2.0, which I don't want to do because then the library would lose back-compat with older versions of AspNetCore.

<ItemGroup Condition="$(TargetFramework) == 'netstandard2.0'">
    <PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
    <PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="2.2.0" />
    <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="2.2.0" />
    <PackageReference Include="Microsoft.Extensions.Options" Version="2.2.0" />
    <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
</ItemGroup>

<ItemGroup Condition="$(TargetFramework) == 'netcoreapp3.1'">
    <PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="3.1.9" />
    <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.1.9" />
    <PackageReference Include="Microsoft.Extensions.Options" Version="3.1.9" />
    <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
</ItemGroup>

It would be really helpful if there was a way to tell dependabot to only look for and update the dependencies in the netcoreapp3.1 target framework. Is there a way to achieve this?

acraven commented 3 years ago

I have a similar requirement, but the latest version of a package is different for different frameworks.

  <ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp3.1' ">
    <PackageReference Include="Microsoft.AspNetCore.TestHost" Version="3.1.15" />
  </ItemGroup>

  <ItemGroup Condition=" '$(TargetFramework)' == 'net5.0' ">
    <PackageReference Include="Microsoft.AspNetCore.TestHost" Version="5.0.6" />
  </ItemGroup>

The output of dotnet outdated is as follows:

  [.NETCoreApp,Version=v5.0]
  Microsoft.AspNetCore.TestHost  5.0.6 -> 5.0.9
  [.NETCoreApp,Version=v3.1]
  Microsoft.AspNetCore.TestHost  3.1.15 -> 3.1.18

Dependabot is incorrectly trying to upgrade both of these references to 5.0.9 rather than as above.

mwaddell commented 2 years ago

Dependabot does not actually run the Nuget commandline but parses the csproj/etc files directly. The overhead of parsing the "freetext" Condition for all possible permutations of TargetFramework, Environment, etc is currently beyond the scope of dependabot.

mikeblakeuk commented 2 years ago

Shame :( Are there any workarounds?

mwaddell commented 2 years ago

I know that dependabot does not inspect imported targets, so you might have some success pulling the portion you want ignored out into a separate .targets file and importing it into your .csproj file instead of including it directly.

Dependabot's nuget support is (currently) written entirely in ruby, so I while think it could add limited support for parsing target frameworks (like the very straightforward example you gave), there's a lot of complexity in msbuild conditions that would require integrating a separate dotnet-specific helper tool (like https://github.com/dotnet-outdated/dotnet-outdated) to provide more complete support. While I think that is entirely possible, it is a very big change and would require integration with the maintainers of that tool in order to add additional flexibility.

iancooper commented 2 years ago

The biggest reason that OSS maintainers like us want multi-targeting support. If we want to support both newer framework releases, like .NET 6, but continue to support older versions of the framework, we need to multi-target.

We now have to mostly treat dependabot as a notification that something has changed for libraries that have a .NET 6.0 version, and then edit the .csproj by hand to update the dependencies for the different targets.

Arguably, this is quite a significant cost to .NET devs, as it removes the automation of the change

dersia commented 1 year ago

Dependabot is great, but this feature is very much needed when it comes to the dotnet eco system, since we'd like to provide support for LTS and STS versions. If I build for net7 I'd like to use net7 dependencies and when using net6 or net8 we need to use net6/8 dependencies so we can guarantee LTS.

ilmax commented 1 year ago

I think dependabot should use dotnet outdated that can understand conditions and target frameworks rather than implementing this logic itself. Without that, if you're not on the latest target supported framework, most of the PR generated by dependabot are noise.

One example where this is really noisy is if you have an asp.net project that targets net6.0 (the current LTS release). Since net7.0 has been released already, dependabot creates PR for each and every asp.net dependency trying to bump it to version 7. Version 7 of asp.net runs on net7.0 so accepting the PR will actually be a mistake. On top of that, since every month there's a new patch version being release, we get these PRs every month for the wrong version and we don't get the one that bumps the correct version of the dependencies.

To summarize this causes a lot of noise with little value missing out the important part of keeping the right dependencies updated.

soenneker commented 1 year ago

Hopefully this can get on the roadmap soon. Supporting multitargeting without using netstandard is critical for dependabot.

AndrewTriesToCode commented 1 year ago

Would also like this feature.

deivid-rodriguez commented 1 year ago

Please use reactions to show support for a feature, without adding anything else to the discussion. Thank you!

Danielku15 commented 10 months ago

Would it be a feasable solution to control the target framework additionally in the dependabot.yml? I am thinking of following solution design:

Single Target Framework

Problem today: Even if you just target net7.0 dependabot proposes .net packages to be upgraded to 8.0 which fails then on dotnet restore. This topic was not yet touched in the discussion but is a problem we just encountered.

Solution: In dependabot you would specify your maximum target framework (e.g. net7.0) explicitly and dependabot will respect it when selecting available frameworks. There is a bit of complexity with checking the compatibility of packages (e.g. target-framework: net7.0 in the dependabot.yml would also allow netstandard2.0 or netstandard2.1 packages. But it should be achievable.

It is a bit of additional effort to keep the dependabot.yml in sync with your project but it is a step forward.

Multiple TargetFrameworks

Problem today: if you target multiple runtimes also the available package versions might differ. dependabot ignores those constraints and changes all versions.

Solution: This could be solved with a setup which combines a dependabot setting and splitting out the dependency versions via central package management like this (example from OP):

Directory.Packages.props ```xml ```
.net/netstandard2.0/Directory.Packages.props ```xml ```
.net/netcoreapp3.1/Directory.Packages.props ```xml ```
.github/dependabot.yml ```yml version: 3 # Dependabot Change 1: Would be a new version I assume? updates: - package-ecosystem: # Dependabot Change 2: Extended configuration for the ecosystems with package manager specific settings id: nuget target-framework: netstandard2.0 directory: '/.net/netstandard2.0' schedule: interval: 'weekly' - package-ecosystem: id: nuget target-framework: netcoreapp3.1 # Dependabot Change 3 (optional): restrict updates to a specific file, this gives devs even more flexibility, but this would be a change should be considered for all ecosystems. # in organizing their projects file: '/.net/netcoreapp3.1/Directory.Packages.props' schedule: interval: 'weekly' ```

Conclusion of this approach

Pros:

Cons:

Unclarity:

JamesMcConaghie commented 4 months ago

@brettfo I have noticed in recent PRs that you have been working on many changes to the nuget side of dependabot. Is the resolution of this issue one of your goals?

brettfo commented 4 months ago

@JamesMcConaghie I have been doing a lot of updates to the NuGet stuff, but if I'm understanding your request correctly, that might be something that's out-of-scope for the updater. Eventually we plan to support the Condition attributes (e.g., to only include a package for nestandard2.0 but not for net8.0) but to only run updates for a single TFM isn't something we can support. When the NuGet updater runs it tries to take the whole project into consideration which includes the <TargetFrameworks> element (e.g., netstandard2.0;net8.0).

JamesMcConaghie commented 4 months ago

@brettfo,

Supporting Condition attributes in general would greatly help my processes. I don't intend to leave one targeted framework stagnant and would want all <TargetFrameworks> values to be evaluated and updated if needed.

I'm glad that it is planned to eventually get tackled. Do you have a rough idea of the timeline (weeks, months, years)? Thank you for all your hard work so far, I am glad to see that nuget is getting more support in dependabot with native tooling.

brettfo commented 4 months ago

@JamesMcConaghie I don't have an estimate at this time, but we are slowly migrating more of our logic to using real MSBuild (instead of manual XML crawling) which is what will eventually enable this.

konarx commented 6 days ago

@JamesMcConaghie I don't have an estimate at this time, but we are slowly migrating more of our logic to using real MSBuild (instead of manual XML crawling) which is what will eventually enable this.

Great news! Do you have an update on this (since you mentioned it in July)?

brettfo commented 5 days ago

@konarx Your timing is amazing! A few hours ago we merged a change that does direct dependency detection via MSBuild. That's experimental work and currently behind a feature flag that I'll slowly roll out over the coming weeks. There will certainly be bugs, but we're actively working on it.