Skip to content

Commit cecbc9a

Browse files
authored
Enable advisory suppressions in CLI restore for PackageReference projects (#5679)
1 parent f2f99ab commit cecbc9a

25 files changed

Lines changed: 494 additions & 17 deletions

src/NuGet.Core/NuGet.Build.Tasks.Console/MSBuildStaticGraphRestore.cs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,11 @@ internal sealed class MSBuildStaticGraphRestore : IDisposable
3737
private static readonly Lazy<IMachineWideSettings> MachineWideSettingsLazy = new Lazy<IMachineWideSettings>(() => new XPlatMachineWideSetting());
3838

3939
/// <summary>
40-
/// Represents the small list of targets that must be executed in order for PackageReference, PackageDownload, and FrameworkReference items to be accurate.
40+
/// Represents the small list of targets that must be executed in order for various restore input items to be accurate.
4141
/// </summary>
4242
private static readonly string[] TargetsToBuild =
4343
{
44-
"CollectPackageReferences",
45-
"CollectPackageDownloads",
46-
"CollectFrameworkReferences",
47-
"CollectCentralPackageVersions"
44+
"_CollectRestoreInputs"
4845
};
4946

5047
private readonly Lazy<ConsoleLoggingQueue> _loggingQueueLazy;
@@ -836,7 +833,7 @@ private PackageSpec GetPackageSpec(IMSBuildProject project, IReadOnlyDictionary<
836833

837834
(bool isCentralPackageManagementEnabled, bool isCentralPackageVersionOverrideDisabled, bool isCentralPackageTransitivePinningEnabled, bool isCentralPackageFloatingVersionsEnabled) = MSBuildRestoreUtility.GetCentralPackageManagementSettings(project, projectStyle);
838835

839-
RestoreAuditProperties auditProperties = MSBuildRestoreUtility.GetRestoreAuditProperties(project);
836+
RestoreAuditProperties auditProperties = MSBuildRestoreUtility.GetRestoreAuditProperties(project, GetAuditSuppressions(project));
840837

841838
List<TargetFrameworkInformation> targetFrameworkInfos = GetTargetFrameworkInfos(projectsByTargetFramework, isCentralPackageManagementEnabled);
842839

@@ -1009,7 +1006,7 @@ private ICollection<ProjectWithInnerNodes> LoadProjects(IEnumerable<ProjectGraph
10091006
continue;
10101007
}
10111008

1012-
// If the project supports restore, queue up a build of the 3 targets needed for restore
1009+
// If the project supports restore, queue up a build of the targets needed for restore
10131010
BuildSubmission buildSubmission = BuildManager.DefaultBuildManager.PendBuildRequest(
10141011
new BuildRequestData(
10151012
projectInstance,
@@ -1060,6 +1057,14 @@ private ICollection<ProjectWithInnerNodes> LoadProjects(IEnumerable<ProjectGraph
10601057
}
10611058
}
10621059

1060+
private static HashSet<string> GetAuditSuppressions(IMSBuildProject project)
1061+
{
1062+
IEnumerable<string> suppressions = GetDistinctItemsOrEmpty(project, "NuGetAuditSuppress")
1063+
.Select(i => i.Identity);
1064+
1065+
return suppressions?.Count() > 0 ? new HashSet<string>(suppressions) : null;
1066+
}
1067+
10631068
/// <summary>
10641069
/// Returns the list of distinct items with the <paramref name="itemName"/> name.
10651070
/// Two items are equal if they have the same <see cref="IMSBuildItem.Identity"/>.
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.Collections.Generic;
6+
using Microsoft.Build.Framework;
7+
using Microsoft.Build.Utilities;
8+
using Newtonsoft.Json;
9+
10+
namespace NuGet.Build.Tasks
11+
{
12+
public class GetRestoreNuGetAuditSuppressionsTask : Microsoft.Build.Utilities.Task
13+
{
14+
/// <summary>
15+
/// Full path to the msbuild project.
16+
/// </summary>
17+
[Required]
18+
public string ProjectUniqueName { get; set; }
19+
20+
[Required]
21+
public ITaskItem[] NuGetAuditSuppressions { get; set; }
22+
23+
/// <summary>
24+
/// Target frameworks to apply this for. If empty this applies to all.
25+
/// </summary>
26+
public string TargetFrameworks { get; set; }
27+
28+
/// <summary>
29+
/// Output items
30+
/// </summary>
31+
[Output]
32+
public ITaskItem[] RestoreGraphItems { get; set; }
33+
34+
public override bool Execute()
35+
{
36+
if (NuGetAuditSuppressions.Length == 0) return true;
37+
38+
var entries = new List<ITaskItem>(NuGetAuditSuppressions.Length);
39+
var seenIds = new HashSet<string>(NuGetAuditSuppressions.Length, StringComparer.Ordinal);
40+
41+
foreach (var msbuildItem in NuGetAuditSuppressions)
42+
{
43+
var packageId = msbuildItem.ItemSpec;
44+
45+
if (string.IsNullOrEmpty(packageId) || !seenIds.Add(packageId))
46+
{
47+
// Skip empty or already processed ids
48+
continue;
49+
}
50+
51+
var properties = new Dictionary<string, string>();
52+
properties.Add("ProjectUniqueName", ProjectUniqueName);
53+
properties.Add("Type", "NuGetAuditSuppress");
54+
properties.Add("Id", packageId);
55+
56+
if (!string.IsNullOrEmpty(TargetFrameworks))
57+
{
58+
properties.Add("TargetFrameworks", TargetFrameworks);
59+
}
60+
61+
entries.Add(new TaskItem(Guid.NewGuid().ToString(), properties));
62+
}
63+
64+
RestoreGraphItems = entries.ToArray();
65+
66+
return true;
67+
}
68+
}
69+
}

src/NuGet.Core/NuGet.Build.Tasks/GlobalSuppressions.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
[assembly: SuppressMessage("Build", "CA1819:Properties should not return arrays", Justification = "<Pending>", Scope = "member", Target = "~P:NuGet.Build.Tasks.GetRestoreDotnetCliToolsTask.RestoreSources")]
3838
[assembly: SuppressMessage("Build", "CA1819:Properties should not return arrays", Justification = "<Pending>", Scope = "member", Target = "~P:NuGet.Build.Tasks.GetRestoreFrameworkReferencesTask.FrameworkReferences")]
3939
[assembly: SuppressMessage("Build", "CA1819:Properties should not return arrays", Justification = "<Pending>", Scope = "member", Target = "~P:NuGet.Build.Tasks.GetRestoreFrameworkReferencesTask.RestoreGraphItems")]
40+
[assembly: SuppressMessage("Build", "CA1819:Properties should not return arrays", Justification = "<Pending>", Scope = "member", Target = "~P:NuGet.Build.Tasks.GetRestoreNuGetAuditSuppressionsTask.NuGetAuditSuppressions")]
41+
[assembly: SuppressMessage("Build", "CA1819:Properties should not return arrays", Justification = "<Pending>", Scope = "member", Target = "~P:NuGet.Build.Tasks.GetRestoreNuGetAuditSuppressionsTask.RestoreGraphItems")]
4042
[assembly: SuppressMessage("Build", "CA1819:Properties should not return arrays", Justification = "<Pending>", Scope = "member", Target = "~P:NuGet.Build.Tasks.GetRestorePackageDownloadsTask.PackageDownloads")]
4143
[assembly: SuppressMessage("Build", "CA1819:Properties should not return arrays", Justification = "<Pending>", Scope = "member", Target = "~P:NuGet.Build.Tasks.GetRestorePackageDownloadsTask.RestoreGraphItems")]
4244
[assembly: SuppressMessage("Build", "CA1819:Properties should not return arrays", Justification = "<Pending>", Scope = "member", Target = "~P:NuGet.Build.Tasks.GetRestorePackageReferencesTask.PackageReferences")]

src/NuGet.Core/NuGet.Build.Tasks/NuGet.targets

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ Copyright (c) .NET Foundation. All rights reserved.
138138
<UsingTask TaskName="NuGet.Build.Tasks.GetCentralPackageVersionsTask" AssemblyFile="$(RestoreTaskAssemblyFile)" />
139139
<UsingTask TaskName="NuGet.Build.Tasks.GetRestorePackageDownloadsTask" AssemblyFile="$(RestoreTaskAssemblyFile)" />
140140
<UsingTask TaskName="NuGet.Build.Tasks.GetRestoreFrameworkReferencesTask" AssemblyFile="$(RestoreTaskAssemblyFile)" />
141+
<UsingTask TaskName="NuGet.Build.Tasks.GetRestoreNuGetAuditSuppressionsTask" AssemblyFile="$(RestoreTaskAssemblyFile)" />
141142
<UsingTask TaskName="NuGet.Build.Tasks.GetRestoreDotnetCliToolsTask" AssemblyFile="$(RestoreTaskAssemblyFile)" />
142143
<UsingTask TaskName="NuGet.Build.Tasks.GetProjectTargetFrameworksTask" AssemblyFile="$(RestoreTaskAssemblyFile)" />
143144
<UsingTask TaskName="NuGet.Build.Tasks.GetRestoreSolutionProjectsTask" AssemblyFile="$(RestoreTaskAssemblyFile)" />
@@ -329,6 +330,52 @@ Copyright (c) .NET Foundation. All rights reserved.
329330
Condition="'%(FrameworkReference.IsTransitiveFrameworkReference)' != 'true'"/>
330331
</ItemGroup>
331332
</Target>
333+
334+
<!--
335+
============================================================
336+
CollectNuGetAuditSuppressions
337+
Gathers all NuGetAuditSuppress items from the project.
338+
This target may be used as an extension point to modify
339+
advisory suppressions before NuGet reads them.
340+
============================================================
341+
-->
342+
<Target Name="CollectNuGetAuditSuppressions" Returns="@(NuGetAuditSuppress)">
343+
<!-- NOTE for design-time builds we need to ensure that we continue on error. -->
344+
<PropertyGroup>
345+
<CollectNuGetAuditSuppressionsContinueOnError>$(ContinueOnError)</CollectNuGetAuditSuppressionsContinueOnError>
346+
<CollectNuGetAuditSuppressionsContinueOnError Condition="'$(ContinueOnError)' == '' ">false</CollectNuGetAuditSuppressionsContinueOnError>
347+
</PropertyGroup>
348+
349+
<CheckForDuplicateNuGetItemsTask
350+
Items="@(NuGetAuditSuppress)"
351+
ItemName="NuGetAuditSuppress"
352+
LogCode="NU1505"
353+
MSBuildProjectFullPath="$(MSBuildProjectFullPath)"
354+
TreatWarningsAsErrors="$(TreatWarningsAsErrors)"
355+
WarningsAsErrors="$(WarningsAsErrors)"
356+
WarningsNotAsErrors="$(WarningsNotAsErrors)"
357+
NoWarn="$(NoWarn)"
358+
ContinueOnError="$(CollectNuGetAuditSuppressionsContinueOnError)"
359+
>
360+
<Output TaskParameter="DeduplicatedItems" ItemName="DeduplicatedNuGetAuditSuppressions" />
361+
</CheckForDuplicateNuGetItemsTask>
362+
363+
<ItemGroup Condition="'@(DeduplicatedNuGetAuditSuppressions)' != ''">
364+
<NuGetAuditSuppress Remove="@(NuGetAuditSuppress)" />
365+
<NuGetAuditSuppress Include="@(DeduplicatedNuGetAuditSuppressions)" />
366+
</ItemGroup>
367+
</Target>
368+
369+
<!--
370+
============================================================
371+
_CollectRestoreInputs
372+
Runs all the 'Collect' targets
373+
============================================================
374+
-->
375+
<Target Name="_CollectRestoreInputs"
376+
DependsOnTargets="CollectPackageReferences;CollectPackageDownloads;CollectFrameworkReferences;CollectCentralPackageVersions;CollectNuGetAuditSuppressions">
377+
</Target>
378+
332379
<!--
333380
============================================================
334381
_LoadRestoreGraphEntryPoints
@@ -998,7 +1045,7 @@ Copyright (c) .NET Foundation. All rights reserved.
9981045
============================================================
9991046
-->
10001047
<Target Name="_GenerateProjectRestoreGraphPerFramework"
1001-
DependsOnTargets="_GetRestoreProjectStyle;CollectPackageReferences;CollectPackageDownloads;CollectFrameworkReferences;CollectCentralPackageVersions"
1048+
DependsOnTargets="_GetRestoreProjectStyle;_CollectRestoreInputs"
10021049
Returns="@(_RestoreGraphEntry)">
10031050

10041051
<!-- Write out project references -->
@@ -1065,6 +1112,19 @@ Copyright (c) .NET Foundation. All rights reserved.
10651112
ItemName="_RestoreGraphEntry" />
10661113
</GetRestoreFrameworkReferencesTask>
10671114

1115+
<!-- Write out advisory suppressions-->
1116+
<GetRestoreNuGetAuditSuppressionsTask
1117+
Condition=" '$(PackageReferenceCompatibleProjectStyle)' == 'true' "
1118+
ProjectUniqueName="$(MSBuildProjectFullPath)"
1119+
NuGetAuditSuppressions="@(NuGetAuditSuppress)"
1120+
TargetFrameworks="$(TargetFramework)"
1121+
>
1122+
1123+
<Output
1124+
TaskParameter="RestoreGraphItems"
1125+
ItemName="_RestoreGraphEntry" />
1126+
</GetRestoreNuGetAuditSuppressionsTask>
1127+
10681128
<!-- Write out target framework information -->
10691129
<ItemGroup Condition=" '$(PackageReferenceCompatibleProjectStyle)' == 'true'">
10701130
<_RestoreGraphEntry Include="$([System.Guid]::NewGuid())">

src/NuGet.Core/NuGet.Commands/PublicAPI/net472/PublicAPI.Shipped.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -951,7 +951,6 @@ override NuGet.Commands.WarningPropertiesCollection.GetHashCode() -> int
951951
~static NuGet.Commands.MSBuildRestoreUtility.GetDependencySpec(System.Collections.Generic.IEnumerable<NuGet.Commands.IMSBuildItem> items, bool readOnly) -> NuGet.ProjectModel.DependencyGraphSpec
952952
~static NuGet.Commands.MSBuildRestoreUtility.GetMessageForUnsupportedProject(string path) -> NuGet.Common.RestoreLogMessage
953953
~static NuGet.Commands.MSBuildRestoreUtility.GetPackageSpec(System.Collections.Generic.IEnumerable<NuGet.Commands.IMSBuildItem> items) -> NuGet.ProjectModel.PackageSpec
954-
~static NuGet.Commands.MSBuildRestoreUtility.GetRestoreAuditProperties(NuGet.Commands.IMSBuildItem specItem) -> NuGet.ProjectModel.RestoreAuditProperties
955954
~static NuGet.Commands.MSBuildRestoreUtility.GetWarningForUnsupportedProject(string path) -> NuGet.Common.RestoreLogMessage
956955
~static NuGet.Commands.MSBuildRestoreUtility.HasInvalidClear(System.Collections.Generic.IEnumerable<string> values) -> bool
957956
~static NuGet.Commands.MSBuildRestoreUtility.LogErrorForClearIfInvalid(System.Collections.Generic.IEnumerable<string> values, string projectPath, NuGet.Common.ILogger logger) -> bool
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
#nullable enable
2+
~static NuGet.Commands.MSBuildRestoreUtility.GetRestoreAuditProperties(NuGet.Commands.IMSBuildItem specItem, System.Collections.Generic.HashSet<string> suppressionItems) -> NuGet.ProjectModel.RestoreAuditProperties

src/NuGet.Core/NuGet.Commands/PublicAPI/netcoreapp5.0/PublicAPI.Shipped.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -950,7 +950,6 @@ override NuGet.Commands.WarningPropertiesCollection.GetHashCode() -> int
950950
~static NuGet.Commands.MSBuildRestoreUtility.GetDependencySpec(System.Collections.Generic.IEnumerable<NuGet.Commands.IMSBuildItem> items, bool readOnly) -> NuGet.ProjectModel.DependencyGraphSpec
951951
~static NuGet.Commands.MSBuildRestoreUtility.GetMessageForUnsupportedProject(string path) -> NuGet.Common.RestoreLogMessage
952952
~static NuGet.Commands.MSBuildRestoreUtility.GetPackageSpec(System.Collections.Generic.IEnumerable<NuGet.Commands.IMSBuildItem> items) -> NuGet.ProjectModel.PackageSpec
953-
~static NuGet.Commands.MSBuildRestoreUtility.GetRestoreAuditProperties(NuGet.Commands.IMSBuildItem specItem) -> NuGet.ProjectModel.RestoreAuditProperties
954953
~static NuGet.Commands.MSBuildRestoreUtility.GetWarningForUnsupportedProject(string path) -> NuGet.Common.RestoreLogMessage
955954
~static NuGet.Commands.MSBuildRestoreUtility.HasInvalidClear(System.Collections.Generic.IEnumerable<string> values) -> bool
956955
~static NuGet.Commands.MSBuildRestoreUtility.LogErrorForClearIfInvalid(System.Collections.Generic.IEnumerable<string> values, string projectPath, NuGet.Common.ILogger logger) -> bool
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
#nullable enable
2+
~static NuGet.Commands.MSBuildRestoreUtility.GetRestoreAuditProperties(NuGet.Commands.IMSBuildItem specItem, System.Collections.Generic.HashSet<string> suppressionItems) -> NuGet.ProjectModel.RestoreAuditProperties

src/NuGet.Core/NuGet.Commands/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -949,7 +949,6 @@ override NuGet.Commands.WarningPropertiesCollection.GetHashCode() -> int
949949
~static NuGet.Commands.MSBuildRestoreUtility.GetDependencySpec(System.Collections.Generic.IEnumerable<NuGet.Commands.IMSBuildItem> items, bool readOnly) -> NuGet.ProjectModel.DependencyGraphSpec
950950
~static NuGet.Commands.MSBuildRestoreUtility.GetMessageForUnsupportedProject(string path) -> NuGet.Common.RestoreLogMessage
951951
~static NuGet.Commands.MSBuildRestoreUtility.GetPackageSpec(System.Collections.Generic.IEnumerable<NuGet.Commands.IMSBuildItem> items) -> NuGet.ProjectModel.PackageSpec
952-
~static NuGet.Commands.MSBuildRestoreUtility.GetRestoreAuditProperties(NuGet.Commands.IMSBuildItem specItem) -> NuGet.ProjectModel.RestoreAuditProperties
953952
~static NuGet.Commands.MSBuildRestoreUtility.GetWarningForUnsupportedProject(string path) -> NuGet.Common.RestoreLogMessage
954953
~static NuGet.Commands.MSBuildRestoreUtility.HasInvalidClear(System.Collections.Generic.IEnumerable<string> values) -> bool
955954
~static NuGet.Commands.MSBuildRestoreUtility.LogErrorForClearIfInvalid(System.Collections.Generic.IEnumerable<string> values, string projectPath, NuGet.Common.ILogger logger) -> bool
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
#nullable enable
2+
~static NuGet.Commands.MSBuildRestoreUtility.GetRestoreAuditProperties(NuGet.Commands.IMSBuildItem specItem, System.Collections.Generic.HashSet<string> suppressionItems) -> NuGet.ProjectModel.RestoreAuditProperties

0 commit comments

Comments
 (0)