dependabot-nuget 0.287.0 → 0.288.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/helpers/lib/NuGetUpdater/.gitignore +1 -0
  3. data/helpers/lib/NuGetUpdater/Directory.Build.targets +17 -0
  4. data/helpers/lib/NuGetUpdater/Directory.Packages.props +10 -3
  5. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/DiscoverCommand.cs +7 -3
  6. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/RunCommand.cs +1 -1
  7. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Discover.cs +72 -51
  8. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/AnalyzeWorker.cs +1 -1
  9. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/DependencyDiscovery.props +7 -0
  10. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/DependencyDiscovery.targets +10 -0
  11. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DiscoveryWorker.cs +36 -19
  12. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/PackagesConfigDiscovery.cs +6 -2
  13. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/PackagesConfigDiscoveryResult.cs +2 -1
  14. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/ProjectDiscoveryResult.cs +5 -0
  15. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/SdkProjectDiscovery.cs +386 -12
  16. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/WorkspaceDiscoveryResult.cs +1 -1
  17. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ExperimentsManager.cs +11 -0
  18. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/NuGetUpdater.Core.csproj +7 -2
  19. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/Job.cs +23 -0
  20. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/RunWorker.cs +0 -4
  21. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/TargetFrameworkReporter.targets +13 -0
  22. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/LockFileUpdater.cs +1 -0
  23. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackageReferenceUpdater.cs +2 -0
  24. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/CollectionExtensions.cs +17 -0
  25. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +57 -4
  26. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/PathComparer.cs +31 -0
  27. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/PathHelper.cs +30 -2
  28. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTests.cs +50 -0
  29. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTestBase.cs +74 -38
  30. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.PackagesConfig.cs +50 -4
  31. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Proj.cs +5 -5
  32. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Project.cs +728 -253
  33. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs +322 -78
  34. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/ExpectedDiscoveryResults.cs +2 -6
  35. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/SdkProjectDiscoveryTests.cs +472 -0
  36. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/MockNuGetPackage.cs +46 -1
  37. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/NuGetUpdater.Core.Test.csproj +0 -1
  38. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/RunWorkerTests.cs +1 -1
  39. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/SerializationTests.cs +33 -0
  40. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TemporaryDirectory.cs +3 -2
  41. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs +4 -2
  42. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/PathHelperTests.cs +3 -2
  43. data/lib/dependabot/nuget/file_parser.rb +7 -1
  44. data/lib/dependabot/nuget/native_discovery/native_discovery_json_reader.rb +0 -3
  45. data/lib/dependabot/nuget/native_discovery/native_workspace_discovery.rb +7 -10
  46. data/lib/dependabot/nuget/native_helpers.rb +13 -4
  47. metadata +12 -8
  48. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DirectoryPackagesPropsDiscovery.cs +0 -69
  49. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DirectoryPackagesPropsDiscoveryResult.cs +0 -11
  50. data/lib/dependabot/nuget/native_discovery/native_directory_packages_props_discovery.rb +0 -44
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3bb2d903f08322511a7917fba47df7b66208dbbaca42e52d30a1954f9ef3eaa2
4
- data.tar.gz: f19cfed3ad2939c93812727546b53ecec603c712641a6c1d0581469cce72d584
3
+ metadata.gz: 970779cacdfb8250a46cf1c24ac9fcda325b69b1502c3f0e99b9f1bf80a1add8
4
+ data.tar.gz: a8c7a1b0aba00354ffdb35a8903e912d60ce00e73521f53b76b5f20458194e2f
5
5
  SHA512:
6
- metadata.gz: a3fdc15bd985678106cf45f57c6af6dd4be57858f54b50abea6f4521a8aed3ab66b7ca67cb54f9e73dabe536d8c012619bbf049662207211bc92cbb5e938c321
7
- data.tar.gz: 3542f489f10b67fe78b3bd55703cc420a58279bf5fb131da4a99be0d99a20fcd7430b124c4b49100929b74f39178b3c7e108e7bb0170baef5f5a91a16dfbd63f
6
+ metadata.gz: 0ae55b0bfbfa8874ef9b2f9a6864587b13d107e9702319397161dbd70c9df97f638b9e906807966f3a0ca2214fce5760c1b4c58eb5b481c68171a270fadbbded
7
+ data.tar.gz: bea5ba0649370308fa5a1a6c8d2211708ebdf99d33da6461d38c3a4a10e095b87be83e8ae39b4050fa7ce40ad096fdb349c7bc715971c7e0971ba5eb1f68265d
@@ -4,3 +4,4 @@ bin/
4
4
  obj/
5
5
  Properties/launchSettings.json
6
6
  NuGetUpdater.sln.DotSettings.user
7
+ *.binlog
@@ -0,0 +1,17 @@
1
+ <Project>
2
+ <ItemGroup>
3
+ <!--
4
+ The NuGetUpdater.Core project needs to reference `Microsoft.Build.*`, et al. packages, but they require some
5
+ special handling. The documentation explains that:
6
+
7
+ https://learn.microsoft.com/en-us/visualstudio/msbuild/find-and-use-msbuild-versions?view=vs-2022#use-nuget-packages-preferred
8
+
9
+ The `ExcludeAssets` attribute doesn't do what we'd like through a <ProjectReference> element, so to get around that
10
+ we're adding the packages to _all_ projects so they all get the `ExcludeAssets` behavior. For more information see
11
+ this: https://github.com/dotnet/sdk/issues/42708
12
+ -->
13
+ <PackageReference Include="Microsoft.Build" ExcludeAssets="runtime" PrivateAssets="all" />
14
+ <PackageReference Include="Microsoft.Build.Framework" ExcludeAssets="runtime" PrivateAssets="all" />
15
+ <PackageReference Include="Microsoft.Build.Utilities.Core" ExcludeAssets="runtime" PrivateAssets="all" />
16
+ </ItemGroup>
17
+ </Project>
@@ -4,19 +4,26 @@
4
4
  <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
5
5
  </PropertyGroup>
6
6
 
7
+ <PropertyGroup>
8
+ <MSBuildPackageVersion>17.5.0</MSBuildPackageVersion>
9
+ </PropertyGroup>
10
+
7
11
  <ItemGroup>
8
12
  <PackageVersion Include="DiffPlex" Version="1.7.1" />
9
13
 
10
14
  <PackageVersion Include="GuiLabs.Language.Xml" Version="1.2.93" />
11
15
 
12
- <PackageVersion Include="Microsoft.Build.Locator" Version="1.6.1" />
13
- <PackageVersion Include="Microsoft.Build" Version="17.5.0" ExcludeAssets="Runtime" PrivateAssets="All" />
14
- <PackageVersion Include="Microsoft.Build.Utilities.Core" Version="17.5.0" ExcludeAssets="Runtime" PrivateAssets="All" />
16
+ <PackageVersion Include="Microsoft.Build" Version="$(MSBuildPackageVersion)" />
17
+ <PackageVersion Include="Microsoft.Build.Framework" Version="$(MSBuildPackageVersion)" />
18
+ <PackageVersion Include="Microsoft.Build.Locator" Version="1.7.8" />
19
+ <PackageVersion Include="Microsoft.Build.Utilities.Core" Version="$(MSBuildPackageVersion)" />
15
20
 
16
21
  <PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.9.2" />
17
22
 
18
23
  <PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
19
24
 
25
+ <PackageVersion Include="MSBuild.StructuredLogger" Version="2.2.386" />
26
+
20
27
  <PackageVersion Include="NuGet.Core" Version="2.14.0-rtm-832" Aliases="CoreV2" />
21
28
 
22
29
  <PackageVersion Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
@@ -7,6 +7,7 @@ namespace NuGetUpdater.Cli.Commands;
7
7
 
8
8
  internal static class DiscoverCommand
9
9
  {
10
+ internal static readonly Option<FileInfo> JobPathOption = new("--job-path") { IsRequired = true };
10
11
  internal static readonly Option<DirectoryInfo> RepoRootOption = new("--repo-root") { IsRequired = true };
11
12
  internal static readonly Option<string> WorkspaceOption = new("--workspace") { IsRequired = true };
12
13
  internal static readonly Option<FileInfo> OutputOption = new("--output") { IsRequired = true };
@@ -15,6 +16,7 @@ internal static class DiscoverCommand
15
16
  {
16
17
  Command command = new("discover", "Generates a report of the workspace dependencies and where they are located.")
17
18
  {
19
+ JobPathOption,
18
20
  RepoRootOption,
19
21
  WorkspaceOption,
20
22
  OutputOption
@@ -22,11 +24,13 @@ internal static class DiscoverCommand
22
24
 
23
25
  command.TreatUnmatchedTokensAsErrors = true;
24
26
 
25
- command.SetHandler(async (repoRoot, workspace, outputPath) =>
27
+ command.SetHandler(async (jobPath, repoRoot, workspace, outputPath) =>
26
28
  {
27
- var worker = new DiscoveryWorker(new ConsoleLogger());
29
+ var logger = new ConsoleLogger();
30
+ var experimentsManager = await ExperimentsManager.FromJobFileAsync(jobPath.FullName, logger);
31
+ var worker = new DiscoveryWorker(experimentsManager, logger);
28
32
  await worker.RunAsync(repoRoot.FullName, workspace, outputPath.FullName);
29
- }, RepoRootOption, WorkspaceOption, OutputOption);
33
+ }, JobPathOption, RepoRootOption, WorkspaceOption, OutputOption);
30
34
 
31
35
  return command;
32
36
  }
@@ -35,7 +35,7 @@ internal static class RunCommand
35
35
  var apiHandler = new HttpApiHandler(apiUrl.ToString(), jobId);
36
36
  var logger = new ConsoleLogger();
37
37
  var experimentsManager = await ExperimentsManager.FromJobFileAsync(jobPath.FullName, logger);
38
- var discoverWorker = new DiscoveryWorker(logger);
38
+ var discoverWorker = new DiscoveryWorker(experimentsManager, logger);
39
39
  var analyzeWorker = new AnalyzeWorker(logger);
40
40
  var updateWorker = new UpdaterWorker(experimentsManager, logger);
41
41
  var worker = new RunWorker(apiHandler, discoverWorker, analyzeWorker, updateWorker, logger);
@@ -17,12 +17,16 @@ public partial class EntryPointTests
17
17
  {
18
18
  public class Discover : DiscoveryWorkerTestBase
19
19
  {
20
- [Fact]
21
- public async Task PathWithSpaces()
20
+ [Theory]
21
+ [InlineData(true)]
22
+ [InlineData(false)]
23
+ public async Task PathWithSpaces(bool useDirectDiscovery)
22
24
  {
23
25
  await RunAsync(path =>
24
26
  [
25
27
  "discover",
28
+ "--job-path",
29
+ Path.Combine(path, "job.json"),
26
30
  "--repo-root",
27
31
  path,
28
32
  "--workspace",
@@ -30,11 +34,15 @@ public partial class EntryPointTests
30
34
  "--output",
31
35
  Path.Combine(path, DiscoveryWorker.DiscoveryResultFileName),
32
36
  ],
33
- packages: [],
37
+ experimentsManager: new ExperimentsManager() { UseDirectDiscovery = useDirectDiscovery },
38
+ packages:
39
+ [
40
+ MockNuGetPackage.CreateSimplePackage("Some.Package", "1.2.3", "net8.0"),
41
+ ],
34
42
  initialFiles:
35
43
  [
36
44
  ("path/to/some directory with spaces/project.csproj", """
37
- <Project Sdk="Microsoft.NETSdk">
45
+ <Project Sdk="Microsoft.NET.Sdk">
38
46
  <PropertyGroup>
39
47
  <TargetFramework>net8.0</TargetFramework>
40
48
  </PropertyGroup>
@@ -52,8 +60,6 @@ public partial class EntryPointTests
52
60
  {
53
61
  FilePath = "project.csproj",
54
62
  TargetFrameworks = ["net8.0"],
55
- ReferencedProjectPaths = [],
56
- ExpectedDependencyCount = 2,
57
63
  Dependencies = [
58
64
  new("Some.Package", "1.2.3", DependencyType.PackageReference, TargetFrameworks: ["net8.0"], IsDirect: true),
59
65
  ],
@@ -66,12 +72,16 @@ public partial class EntryPointTests
66
72
  );
67
73
  }
68
74
 
69
- [Fact]
70
- public async Task WithSolution()
75
+ [Theory]
76
+ [InlineData(true)]
77
+ [InlineData(false)]
78
+ public async Task WithSolution(bool useDirectDiscovery)
71
79
  {
72
80
  await RunAsync(path =>
73
81
  [
74
82
  "discover",
83
+ "--job-path",
84
+ Path.Combine(path, "job.json"),
75
85
  "--repo-root",
76
86
  path,
77
87
  "--workspace",
@@ -79,6 +89,7 @@ public partial class EntryPointTests
79
89
  "--output",
80
90
  Path.Combine(path, DiscoveryWorker.DiscoveryResultFileName),
81
91
  ],
92
+ experimentsManager: new ExperimentsManager() { UseDirectDiscovery = useDirectDiscovery },
82
93
  packages:
83
94
  [
84
95
  MockNuGetPackage.CreateSimplePackage("Some.Package", "7.0.1", "net45"),
@@ -141,26 +152,26 @@ public partial class EntryPointTests
141
152
  {
142
153
  FilePath = "path/to/my.csproj",
143
154
  TargetFrameworks = ["net45"],
144
- ReferencedProjectPaths = [],
145
- ExpectedDependencyCount = 2,
146
155
  Dependencies = [
147
156
  new("Some.Package", "7.0.1", DependencyType.PackagesConfig, TargetFrameworks: ["net45"]),
148
157
  ],
149
- Properties = [
150
- new("TargetFrameworkVersion", "v4.5", "path/to/my.csproj"),
151
- ],
158
+ Properties = [],
152
159
  }
153
160
  ]
154
161
  }
155
162
  );
156
163
  }
157
164
 
158
- [Fact]
159
- public async Task WithProject()
165
+ [Theory]
166
+ [InlineData(true)]
167
+ [InlineData(false)]
168
+ public async Task WithProject(bool useDirectDiscovery)
160
169
  {
161
170
  await RunAsync(path =>
162
171
  [
163
172
  "discover",
173
+ "--job-path",
174
+ Path.Combine(path, "job.json"),
164
175
  "--repo-root",
165
176
  path,
166
177
  "--workspace",
@@ -168,6 +179,7 @@ public partial class EntryPointTests
168
179
  "--output",
169
180
  Path.Combine(path, DiscoveryWorker.DiscoveryResultFileName),
170
181
  ],
182
+ experimentsManager: new ExperimentsManager() { UseDirectDiscovery = useDirectDiscovery },
171
183
  packages:
172
184
  [
173
185
  MockNuGetPackage.CreateSimplePackage("Some.Package", "7.0.1", "net45"),
@@ -207,27 +219,27 @@ public partial class EntryPointTests
207
219
  {
208
220
  FilePath = "my.csproj",
209
221
  TargetFrameworks = ["net45"],
210
- ReferencedProjectPaths = [],
211
- ExpectedDependencyCount = 2,
212
222
  Dependencies = [
213
223
  new("Some.Package", "7.0.1", DependencyType.PackagesConfig, TargetFrameworks: ["net45"])
214
224
  ],
215
- Properties = [
216
- new("TargetFrameworkVersion", "v4.5", "path/to/my.csproj"),
217
- ],
225
+ Properties = [],
218
226
  }
219
227
  ]
220
228
  }
221
229
  );
222
230
  }
223
231
 
224
- [Fact]
225
- public async Task WithDirectory()
232
+ [Theory]
233
+ [InlineData(true)]
234
+ [InlineData(false)]
235
+ public async Task WithDirectory(bool useDirectDiscovery)
226
236
  {
227
237
  var workspacePath = "path/to/";
228
238
  await RunAsync(path =>
229
239
  [
230
240
  "discover",
241
+ "--job-path",
242
+ Path.Combine(path, "job.json"),
231
243
  "--repo-root",
232
244
  path,
233
245
  "--workspace",
@@ -235,6 +247,7 @@ public partial class EntryPointTests
235
247
  "--output",
236
248
  Path.Combine(path, DiscoveryWorker.DiscoveryResultFileName),
237
249
  ],
250
+ experimentsManager: new ExperimentsManager() { UseDirectDiscovery = useDirectDiscovery },
238
251
  packages:
239
252
  [
240
253
  MockNuGetPackage.CreateSimplePackage("Some.Package", "7.0.1", "net45"),
@@ -274,14 +287,10 @@ public partial class EntryPointTests
274
287
  {
275
288
  FilePath = "my.csproj",
276
289
  TargetFrameworks = ["net45"],
277
- ReferencedProjectPaths = [],
278
- ExpectedDependencyCount = 2,
279
290
  Dependencies = [
280
291
  new("Some.Package", "7.0.1", DependencyType.PackagesConfig, TargetFrameworks: ["net45"])
281
292
  ],
282
- Properties = [
283
- new("TargetFrameworkVersion", "v4.5", "path/to/my.csproj"),
284
- ],
293
+ Properties = [],
285
294
  }
286
295
  ]
287
296
  }
@@ -294,6 +303,8 @@ public partial class EntryPointTests
294
303
  await RunAsync(path =>
295
304
  [
296
305
  "discover",
306
+ "--job-path",
307
+ Path.Combine(path, "job.json"),
297
308
  "--repo-root",
298
309
  path,
299
310
  "--workspace",
@@ -304,27 +315,33 @@ public partial class EntryPointTests
304
315
  new[]
305
316
  {
306
317
  ("path/to/my.csproj", """
307
- <Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
318
+ <Project Sdk="Microsoft.NET.Sdk">
308
319
  <PropertyGroup>
309
320
  <TargetFramework>net8.0</TargetFramework>
321
+ <ManagePackageVersionsCentrally>false</ManagePackageVersionsCentrally>
310
322
  </PropertyGroup>
311
323
  <ItemGroup>
312
- <PackageReference Include="Newtonsoft.Json" Version="7.0.1" />
324
+ <PackageReference Include="Package.A" Version="1.2.3" />
313
325
  </ItemGroup>
314
- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
315
326
  </Project>
316
327
  """),
317
328
  ("path/Directory.Build.props", """
318
329
  <Project>
319
- <ItemGroup Condition="'$(ManagePackageVersionsCentrally)' == 'true'">
320
- <GlobalPackageReference Include="System.Text.Json" Version="8.0.3" />
321
- </ItemGroup>
322
330
  <ItemGroup Condition="'$(ManagePackageVersionsCentrally)' != 'true'">
323
- <PackageReference Include="System.Text.Json" Version="8.0.3" />
331
+ <PackageReference Include="Package.B" Version="4.5.6" />
332
+ </ItemGroup>
333
+ <ItemGroup Condition="'$(ManagePackageVersionsCentrally)' == 'true'">
334
+ <GlobalPackageReference Include="Package.B" Version="7.8.9" />
324
335
  </ItemGroup>
325
336
  </Project>
326
337
  """)
327
338
  },
339
+ experimentsManager: new ExperimentsManager() { UseDirectDiscovery = true },
340
+ packages:
341
+ [
342
+ MockNuGetPackage.CreateSimplePackage("Package.A", "1.2.3", "net8.0"),
343
+ MockNuGetPackage.CreateSimplePackage("Package.B", "4.5.6", "net8.0"),
344
+ ],
328
345
  expectedResult: new()
329
346
  {
330
347
  Path = "path/to",
@@ -333,28 +350,19 @@ public partial class EntryPointTests
333
350
  {
334
351
  FilePath = "my.csproj",
335
352
  TargetFrameworks = ["net8.0"],
336
- ReferencedProjectPaths = [],
337
353
  ExpectedDependencyCount = 2,
338
354
  Dependencies = [
339
- new("Newtonsoft.Json", "7.0.1", DependencyType.PackageReference, TargetFrameworks: ["net8.0"], IsDirect: true),
340
- // $(ManagePackageVersionsCentrally) evaluates false by default, we only get a PackageReference
341
- new("System.Text.Json", "8.0.3", DependencyType.PackageReference, TargetFrameworks: ["net8.0"])
355
+ new("Package.A", "1.2.3", DependencyType.PackageReference, TargetFrameworks: ["net8.0"], IsDirect: true),
356
+ new("Package.B", "4.5.6", DependencyType.PackageReference, TargetFrameworks: ["net8.0"], IsDirect: true),
342
357
  ],
343
358
  Properties = [
359
+ new("ManagePackageVersionsCentrally", "false", "path/to/my.csproj"),
344
360
  new("TargetFramework", "net8.0", "path/to/my.csproj"),
345
361
  ],
346
- },
347
- new()
348
- {
349
- FilePath = "../Directory.Build.props",
350
- ReferencedProjectPaths = [],
351
- ExpectedDependencyCount = 2,
352
- Dependencies = [
353
- new("System.Text.Json", "8.0.3", DependencyType.PackageReference, IsDirect: true),
354
- new("System.Text.Json", "8.0.3", DependencyType.GlobalPackageReference, IsDirect: true)
355
- ],
356
- Properties = [],
357
362
  }
363
+ ],
364
+ ImportedFiles = [
365
+ "Directory.Build.props"
358
366
  ]
359
367
  }
360
368
  );
@@ -364,8 +372,10 @@ public partial class EntryPointTests
364
372
  Func<string, string[]> getArgs,
365
373
  TestFile[] initialFiles,
366
374
  ExpectedWorkspaceDiscoveryResult expectedResult,
367
- MockNuGetPackage[]? packages = null)
375
+ MockNuGetPackage[]? packages = null,
376
+ ExperimentsManager? experimentsManager = null)
368
377
  {
378
+ experimentsManager ??= new ExperimentsManager();
369
379
  var actualResult = await RunDiscoveryAsync(initialFiles, async path =>
370
380
  {
371
381
  var sb = new StringBuilder();
@@ -378,8 +388,19 @@ public partial class EntryPointTests
378
388
 
379
389
  try
380
390
  {
391
+ await UpdateWorkerTestBase.MockJobFileInDirectory(path, experimentsManager);
381
392
  await UpdateWorkerTestBase.MockNuGetPackagesInDirectory(packages, path);
382
393
  var args = getArgs(path);
394
+
395
+ // manually pull out the experiments manager for the validate step below
396
+ for (int i = 0; i < args.Length - 1; i++)
397
+ {
398
+ if (args[i] == "--job-path")
399
+ {
400
+ experimentsManager = await ExperimentsManager.FromJobFileAsync(args[i + 1], new TestLogger());
401
+ }
402
+ }
403
+
383
404
  var result = await Program.Main(args);
384
405
  if (result != 0)
385
406
  {
@@ -398,7 +419,7 @@ public partial class EntryPointTests
398
419
  return resultObject!;
399
420
  });
400
421
 
401
- ValidateWorkspaceResult(expectedResult, actualResult);
422
+ ValidateWorkspaceResult(expectedResult, actualResult, experimentsManager);
402
423
  }
403
424
  }
404
425
  }
@@ -391,8 +391,8 @@ public partial class AnalyzeWorker : IAnalyzeWorker
391
391
 
392
392
  var projectFrameworks = projectsWithDependency
393
393
  .SelectMany(p => p.TargetFrameworks)
394
- .Distinct()
395
394
  .Select(NuGetFramework.Parse)
395
+ .Distinct()
396
396
  .ToImmutableArray();
397
397
 
398
398
  // When updating peer dependencies, we only need to consider top-level dependencies.
@@ -0,0 +1,7 @@
1
+ <Project>
2
+ <!-- The following properties enable target framework and dependency discovery when OS-specific workloads are required -->
3
+ <PropertyGroup>
4
+ <DesignTimeBuild>true</DesignTimeBuild>
5
+ <TargetPlatformVersion Condition=" $(TargetFramework.Contains('-')) ">1.0</TargetPlatformVersion>
6
+ </PropertyGroup>
7
+ </Project>
@@ -0,0 +1,10 @@
1
+ <Project>
2
+ <Import Project="DependencyDiscovery.props" />
3
+
4
+ <Target Name="_DiscoverDependencies" DependsOnTargets="GenerateBuildDependencyFile;ResolvePackageAssets">
5
+ <!--
6
+ The target GenerateBuildDependencyFile is sufficient for projects targeting .NET Standard or .NET Core.
7
+ The target ResolvePackageAssets is necessary for projects targeting .NET Framework.
8
+ -->
9
+ </Target>
10
+ </Project>
@@ -16,6 +16,7 @@ public partial class DiscoveryWorker : IDiscoveryWorker
16
16
  {
17
17
  public const string DiscoveryResultFileName = "./.dependabot/discovery.json";
18
18
 
19
+ private readonly ExperimentsManager _experimentsManager;
19
20
  private readonly ILogger _logger;
20
21
  private readonly HashSet<string> _processedProjectPaths = new(StringComparer.OrdinalIgnoreCase); private readonly HashSet<string> _restoredMSBuildSdks = new(StringComparer.OrdinalIgnoreCase);
21
22
 
@@ -25,8 +26,9 @@ public partial class DiscoveryWorker : IDiscoveryWorker
25
26
  Converters = { new JsonStringEnumConverter() },
26
27
  };
27
28
 
28
- public DiscoveryWorker(ILogger logger)
29
+ public DiscoveryWorker(ExperimentsManager experimentsManager, ILogger logger)
29
30
  {
31
+ _experimentsManager = experimentsManager;
30
32
  _logger = logger;
31
33
  }
32
34
 
@@ -52,6 +54,7 @@ public partial class DiscoveryWorker : IDiscoveryWorker
52
54
  ErrorDetails = "(" + string.Join("|", NuGetContext.GetPackageSourceUrls(PathHelper.JoinPath(repoRootPath, workspacePath))) + ")",
53
55
  Path = workspacePath,
54
56
  Projects = [],
57
+ ImportedFiles = [],
55
58
  };
56
59
  }
57
60
 
@@ -60,7 +63,7 @@ public partial class DiscoveryWorker : IDiscoveryWorker
60
63
 
61
64
  public async Task<WorkspaceDiscoveryResult> RunAsync(string repoRootPath, string workspacePath)
62
65
  {
63
- MSBuildHelper.RegisterMSBuild(Environment.CurrentDirectory, repoRootPath);
66
+ MSBuildHelper.RegisterMSBuild(repoRootPath, workspacePath);
64
67
 
65
68
  // the `workspacePath` variable is relative to a repository root, so a rooted path actually isn't rooted; the
66
69
  // easy way to deal with this is to just trim the leading "/" if it exists
@@ -74,7 +77,6 @@ public partial class DiscoveryWorker : IDiscoveryWorker
74
77
 
75
78
  DotNetToolsJsonDiscoveryResult? dotNetToolsJsonDiscovery = null;
76
79
  GlobalJsonDiscoveryResult? globalJsonDiscovery = null;
77
- DirectoryPackagesPropsDiscoveryResult? directoryPackagesPropsDiscovery = null;
78
80
 
79
81
  ImmutableArray<ProjectDiscoveryResult> projectResults = [];
80
82
  WorkspaceDiscoveryResult result;
@@ -93,26 +95,30 @@ public partial class DiscoveryWorker : IDiscoveryWorker
93
95
 
94
96
  // this next line should throw or something
95
97
  projectResults = await RunForDirectoryAsnyc(repoRootPath, workspacePath);
96
-
97
- directoryPackagesPropsDiscovery = DirectoryPackagesPropsDiscovery.Discover(repoRootPath, workspacePath, projectResults, _logger);
98
-
99
- if (directoryPackagesPropsDiscovery is not null)
100
- {
101
- projectResults = projectResults.Remove(projectResults.First(p => p.FilePath.Equals(directoryPackagesPropsDiscovery.FilePath, StringComparison.OrdinalIgnoreCase)));
102
- }
103
98
  }
104
99
  else
105
100
  {
106
101
  _logger.Log($"Workspace path [{workspacePath}] does not exist.");
107
102
  }
108
103
 
104
+ var importedFiles = new HashSet<string>(PathComparer.Instance);
105
+ foreach (var project in projectResults)
106
+ {
107
+ // imported files are relative to the project and need to be converted to be relative to the repo root
108
+ var repoRootRelativeImportedFiles = project.ImportedFiles
109
+ .Select(p => Path.Join(Path.GetDirectoryName(project.FilePath) ?? "", p))
110
+ .Select(p => p.NormalizePathToUnix().NormalizeUnixPathParts())
111
+ .ToArray();
112
+ importedFiles.AddRange(repoRootRelativeImportedFiles);
113
+ }
114
+
109
115
  result = new WorkspaceDiscoveryResult
110
116
  {
111
117
  Path = initialWorkspacePath,
112
118
  DotNetToolsJson = dotNetToolsJsonDiscovery,
113
119
  GlobalJson = globalJsonDiscovery,
114
- DirectoryPackagesProps = directoryPackagesPropsDiscovery,
115
120
  Projects = projectResults.OrderBy(p => p.FilePath).ToImmutableArray(),
121
+ ImportedFiles = importedFiles.ToImmutableArray(),
116
122
  };
117
123
 
118
124
  _logger.Log("Discovery complete.");
@@ -288,11 +294,9 @@ public partial class DiscoveryWorker : IDiscoveryWorker
288
294
  }
289
295
  _processedProjectPaths.Add(actualProjectPath);
290
296
 
291
- var relativeProjectPath = Path.GetRelativePath(workspacePath, actualProjectPath);
292
- var packagesConfigDependencies = PackagesConfigDiscovery.Discover(workspacePath, projectPath, _logger)
293
- ?.Dependencies;
294
-
295
- var projectResults = await SdkProjectDiscovery.DiscoverAsync(repoRootPath, workspacePath, actualProjectPath, _logger);
297
+ var relativeProjectPath = Path.GetRelativePath(workspacePath, actualProjectPath).NormalizePathToUnix();
298
+ var packagesConfigResult = await PackagesConfigDiscovery.Discover(repoRootPath, workspacePath, actualProjectPath, _logger);
299
+ var projectResults = await SdkProjectDiscovery.DiscoverAsync(repoRootPath, workspacePath, actualProjectPath, _experimentsManager, _logger);
296
300
 
297
301
  // Determine if there were unrestored MSBuildSdks
298
302
  var msbuildSdks = projectResults.SelectMany(p => p.Dependencies.Where(d => d.Type == DependencyType.MSBuildSdk)).ToImmutableArray();
@@ -301,7 +305,7 @@ public partial class DiscoveryWorker : IDiscoveryWorker
301
305
  // If new SDKs were restored, then we need to rerun SdkProjectDiscovery.
302
306
  if (await TryRestoreMSBuildSdksAsync(repoRootPath, workspacePath, msbuildSdks, _logger))
303
307
  {
304
- projectResults = await SdkProjectDiscovery.DiscoverAsync(repoRootPath, workspacePath, actualProjectPath, _logger);
308
+ projectResults = await SdkProjectDiscovery.DiscoverAsync(repoRootPath, workspacePath, actualProjectPath, _experimentsManager, _logger);
305
309
  }
306
310
  }
307
311
 
@@ -313,9 +317,9 @@ public partial class DiscoveryWorker : IDiscoveryWorker
313
317
  }
314
318
 
315
319
  // If we had packages.config dependencies, merge them with the project dependencies
316
- if (projectResult.FilePath == relativeProjectPath && packagesConfigDependencies is not null)
320
+ if (projectResult.FilePath == relativeProjectPath && packagesConfigResult is not null)
317
321
  {
318
- packagesConfigDependencies = packagesConfigDependencies.Value
322
+ var packagesConfigDependencies = packagesConfigResult.Dependencies
319
323
  .Select(d => d with { TargetFrameworks = projectResult.TargetFrameworks })
320
324
  .ToImmutableArray();
321
325
 
@@ -329,6 +333,19 @@ public partial class DiscoveryWorker : IDiscoveryWorker
329
333
  results[projectResult.FilePath] = projectResult;
330
334
  }
331
335
  }
336
+
337
+ if (!results.ContainsKey(relativeProjectPath) &&
338
+ packagesConfigResult is not null &&
339
+ packagesConfigResult.Dependencies.Length > 0)
340
+ {
341
+ // project contained only packages.config dependencies
342
+ results[relativeProjectPath] = new ProjectDiscoveryResult()
343
+ {
344
+ FilePath = relativeProjectPath,
345
+ Dependencies = packagesConfigResult.Dependencies,
346
+ TargetFrameworks = packagesConfigResult.TargetFrameworks,
347
+ };
348
+ }
332
349
  }
333
350
 
334
351
  return [.. results.Values];
@@ -4,7 +4,7 @@ namespace NuGetUpdater.Core.Discover;
4
4
 
5
5
  internal static class PackagesConfigDiscovery
6
6
  {
7
- public static PackagesConfigDiscoveryResult? Discover(string workspacePath, string projectPath, ILogger logger)
7
+ public static async Task<PackagesConfigDiscoveryResult?> Discover(string repoRootPath, string workspacePath, string projectPath, ILogger logger)
8
8
  {
9
9
  if (!NuGetHelper.TryGetPackagesConfigFile(projectPath, out var packagesConfigPath))
10
10
  {
@@ -20,10 +20,14 @@ internal static class PackagesConfigDiscovery
20
20
  .OrderBy(d => d.Name)
21
21
  .ToImmutableArray();
22
22
 
23
+ // generate `$(TargetFramework)` via MSBuild
24
+ var tfms = await MSBuildHelper.GetTargetFrameworkValuesFromProject(repoRootPath, projectPath, logger);
25
+
23
26
  return new()
24
27
  {
25
28
  FilePath = packagesConfigFile.RelativePath,
26
- Dependencies = dependencies,
29
+ Dependencies = dependencies.Select(d => d with { TargetFrameworks = tfms }).ToImmutableArray(),
30
+ TargetFrameworks = tfms,
27
31
  };
28
32
  }
29
33
  }
@@ -6,5 +6,6 @@ public sealed record PackagesConfigDiscoveryResult : IDiscoveryResultWithDepende
6
6
  {
7
7
  public required string FilePath { get; init; }
8
8
  public bool IsSuccess { get; init; } = true;
9
- public ImmutableArray<Dependency> Dependencies { get; init; }
9
+ public required ImmutableArray<Dependency> Dependencies { get; init; }
10
+ public required ImmutableArray<string> TargetFrameworks { get; init; }
10
11
  }
@@ -1,4 +1,5 @@
1
1
  using System.Collections.Immutable;
2
+ using System.Text.Json.Serialization;
2
3
 
3
4
  namespace NuGetUpdater.Core.Discover;
4
5
 
@@ -10,4 +11,8 @@ public record ProjectDiscoveryResult : IDiscoveryResultWithDependencies
10
11
  public ImmutableArray<Property> Properties { get; init; } = [];
11
12
  public ImmutableArray<string> TargetFrameworks { get; init; } = [];
12
13
  public ImmutableArray<string> ReferencedProjectPaths { get; init; } = [];
14
+
15
+ // this is purely for internal record keeping and should not be serialized
16
+ [JsonIgnore]
17
+ public ImmutableArray<string> ImportedFiles { get; init; } = [];
13
18
  }