Skip to content

Commit 4f3eacd

Browse files
authored
Merge pull request #721 from dotnet-maestro-bot/merge/release/2.2-to-master
[automated] Merge branch 'release/2.2' => 'master'
2 parents 1a52f7b + f1f0406 commit 4f3eacd

File tree

3 files changed

+150
-13
lines changed

3 files changed

+150
-13
lines changed

dir.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
<PackageReportDataFile>$(PackageReportDir)prebuilt-usage.json</PackageReportDataFile>
7272
<ProdConManifestFile>$(PackageReportDir)prodcon-build.xml</ProdConManifestFile>
7373
<PoisonedReportFile>$(PackageReportDir)poisoned.txt</PoisonedReportFile>
74+
<ConflictingPackageReportDir>$(BaseOutputPath)conflict-report/</ConflictingPackageReportDir>
7475
</PropertyGroup>
7576

7677
<!-- Import Build tools common props file where repo-independent properties are found -->

repos/dir.targets

Lines changed: 46 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
</ItemGroup>
88

99
<UsingTask AssemblyFile="$(TasksBinDir)Microsoft.DotNet.SourceBuild.Tasks.dll" TaskName="AddSourceToNuGetConfig" />
10+
<UsingTask AssemblyFile="$(TasksBinDir)Microsoft.DotNet.SourceBuild.Tasks.dll" TaskName="GetSourceBuiltNupkgCacheConflicts" />
1011
<UsingTask AssemblyFile="$(TasksBinDir)Microsoft.DotNet.SourceBuild.Tasks.dll" TaskName="ReadNuGetPackageInfos" />
1112
<UsingTask AssemblyFile="$(TasksBinDir)Microsoft.DotNet.SourceBuild.Tasks.dll" TaskName="RemoveInternetSourcesFromNuGetConfig" />
1213
<UsingTask AssemblyFile="$(TasksBinDir)Microsoft.DotNet.SourceBuild.Tasks.dll" TaskName="UpdateJson" />
@@ -155,7 +156,8 @@
155156
<Target Name="CreateBuildOutputProps"
156157
BeforeTargets="Build">
157158
<ItemGroup>
158-
<_PreviouslySourceBuiltPackages Include="$(SourceBuiltPackagesPath)*.nupkg" />
159+
<_PreviouslySourceBuiltPackages Include="$(SourceBuiltPackagesPath)*.nupkg"
160+
Exclude="$(SourceBuiltPackagesPath)*.symbols.nupkg" />
159161
<_AdditionalAssetDirs Include="$(SourceBuiltToolsetDir)" Condition="Exists('$(SourceBuiltToolsetDir)')" />
160162
</ItemGroup>
161163
<WriteBuildOutputProps NuGetPackages="@(_PreviouslySourceBuiltPackages)"
@@ -172,6 +174,34 @@
172174

173175
<Message Importance="High" Text="$(RepositoryName) is using versions $(PackageVersionPropsPath)" />
174176
<Message Importance="High" Text="%(VersionProperties.Identity)" />
177+
178+
<ReadNuGetPackageInfos PackagePaths="@(_PreviouslySourceBuiltPackages)">
179+
<Output TaskParameter="PackageInfoItems" ItemName="_PreviouslySourceBuiltPackageInfos" />
180+
</ReadNuGetPackageInfos>
181+
182+
<GetSourceBuiltNupkgCacheConflicts SourceBuiltPackageInfos="@(_PreviouslySourceBuiltPackageInfos)"
183+
PackageCacheDir="$(PackagesDir)">
184+
<Output TaskParameter="ConflictingPackageInfos" ItemName="ConflictingPackageInfos" />
185+
</GetSourceBuiltNupkgCacheConflicts>
186+
</Target>
187+
188+
<Target Name="CheckSourceBuiltNupkgConflictUsages"
189+
DependsOnTargets="GetAllProjectDirectories"
190+
AfterTargets="CreateBuildOutputProps"
191+
Condition="'@(ConflictingPackageInfos)' != ''">
192+
<PropertyGroup>
193+
<_ReportDir>$(ConflictingPackageReportDir)before-$(RepositoryName)/</_ReportDir>
194+
<_ReportDataFile>$(_ReportDir)usage.json</_ReportDataFile>
195+
</PropertyGroup>
196+
197+
<WritePackageUsageData NuGetPackageInfos="@(ConflictingPackageInfos)"
198+
ProjectDirectories="@(ProjectDirectories)"
199+
DataFile="$(_ReportDataFile)" />
200+
201+
<WriteUsageReports DataFile="$(_ReportDataFile)"
202+
OutputDirectory="$(_ReportDir)" />
203+
204+
<Warning Text="Detected package id/version(s) in the cache that were source-built, but contents don't match. They were probably downloaded. See $(_ReportDir) for usage details. @(ConflictingPackageInfos->'%(PackageId) %(PackageVersion)', ', ')" />
175205
</Target>
176206

177207
<Target Name="CreateRestoreSourceProps"
@@ -320,18 +350,8 @@
320350
</ItemGroup>
321351
</Target>
322352

323-
<Target Name="WritePrebuiltUsageData">
324-
<ItemGroup>
325-
<AllRepoProjects Include="$(ProjectDir)repos\*.proj" />
326-
</ItemGroup>
327-
328-
<Message Importance="High" Text="Finding project directories..." />
329-
330-
<MSBuild Projects="@(AllRepoProjects)"
331-
Targets="GetProjectDirectory">
332-
<Output TaskParameter="TargetOutputs" ItemName="ProjectDirectories" />
333-
</MSBuild>
334-
353+
<Target Name="WritePrebuiltUsageData"
354+
DependsOnTargets="GetAllProjectDirectories">
335355
<ItemGroup>
336356
<PrebuiltPackages Include="$(PrebuiltPackagesPath)*.nupkg" />
337357
<PrebuiltPackages Include="$(TarballPrebuiltPackagesPath)*.nupkg" Condition="'$(TarballPrebuiltPackagesPath)' != ''"/>
@@ -356,6 +376,19 @@
356376
DataFile="$(PackageReportDataFile)" />
357377
</Target>
358378

379+
<Target Name="GetAllProjectDirectories">
380+
<ItemGroup>
381+
<AllRepoProjects Include="$(ProjectDir)repos\*.proj" />
382+
</ItemGroup>
383+
384+
<Message Importance="High" Text="Finding project directories..." />
385+
386+
<MSBuild Projects="@(AllRepoProjects)"
387+
Targets="GetProjectDirectory">
388+
<Output TaskParameter="TargetOutputs" ItemName="ProjectDirectories" />
389+
</MSBuild>
390+
</Target>
391+
359392
<Target Name="ReportPrebuiltUsage"
360393
DependsOnTargets="GetPreviousReleasePrebuiltPackageInfos">
361394
<ItemGroup>
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using Microsoft.Build.Framework;
6+
using Microsoft.Build.Utilities;
7+
using System;
8+
using System.IO;
9+
using System.Linq;
10+
11+
namespace Microsoft.DotNet.SourceBuild.Tasks
12+
{
13+
/// <summary>
14+
/// For each source-built nupkg info given, ensure that if the package cache contains a package
15+
/// with the same id and version, the cached nupkg is the same as the source-built one.
16+
///
17+
/// If the package cache contains a package with the same package id and version as a
18+
/// source-built one, nuget restore short-circuits and doesn't look for the source-built one.
19+
/// This usually results in prebuilt packages being used, which can either break the build or
20+
/// end up in the outputs.
21+
/// </summary>
22+
public class GetSourceBuiltNupkgCacheConflicts : Task
23+
{
24+
/// <summary>
25+
/// Items containing package id and version of each source-built package.
26+
/// ReadNuGetPackageInfos is recommended to generate these.
27+
///
28+
/// %(Identity): Path to the original nupkg.
29+
/// %(PackageId): Identity of the package.
30+
/// %(PackageVersion): Version of the package.
31+
/// </summary>
32+
[Required]
33+
public ITaskItem[] SourceBuiltPackageInfos { get; set; }
34+
35+
/// <summary>
36+
/// Package cache dir containing nupkgs to compare. Path is expected to be like:
37+
///
38+
/// {PackageCacheDir}/{lowercase id}/{version}/{lowercase id}.{version}.nupkg
39+
/// </summary>
40+
[Required]
41+
public string PackageCacheDir { get; set; }
42+
43+
[Output]
44+
public ITaskItem[] ConflictingPackageInfos { get; set; }
45+
46+
public override bool Execute()
47+
{
48+
DateTime startTime = DateTime.Now;
49+
50+
ConflictingPackageInfos = SourceBuiltPackageInfos
51+
.Where(item =>
52+
{
53+
string sourceBuiltPath = item.ItemSpec;
54+
string id = item.GetMetadata("PackageId");
55+
string version = item.GetMetadata("PackageVersion");
56+
57+
string packageCachePath = Path.Combine(
58+
PackageCacheDir,
59+
id.ToLowerInvariant(),
60+
version,
61+
$"{id.ToLowerInvariant()}.{version}.nupkg");
62+
63+
if (!File.Exists(packageCachePath))
64+
{
65+
Log.LogMessage(
66+
MessageImportance.Low,
67+
$"OK: Package not found in package cache: {id} {version}");
68+
return false;
69+
}
70+
71+
Log.LogMessage(
72+
MessageImportance.Low,
73+
$"Package id/version found in package cache, verifying: {id} {version}");
74+
75+
bool identical = File.ReadAllBytes(sourceBuiltPath)
76+
.SequenceEqual(File.ReadAllBytes(packageCachePath));
77+
78+
if (!identical)
79+
{
80+
Log.LogMessage(
81+
MessageImportance.Low,
82+
"BAD: Source-built nupkg is not byte-for-byte identical " +
83+
$"to nupkg in cache: {id} {version}");
84+
return true;
85+
}
86+
87+
Log.LogMessage(
88+
MessageImportance.Low,
89+
$"OK: Package in cache is identical to source-built: {id} {version}");
90+
return false;
91+
})
92+
.ToArray();
93+
94+
// Tell the user about this task, in case it takes a while.
95+
Log.LogMessage(
96+
MessageImportance.High,
97+
"Checked cache for conflicts with source-built nupkgs. " +
98+
$"Took {DateTime.Now - startTime}");
99+
100+
return !Log.HasLoggedErrors;
101+
}
102+
}
103+
}

0 commit comments

Comments
 (0)