dependabot-nuget 0.289.0 → 0.291.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/helpers/lib/NuGetUpdater/Directory.Packages.props +1 -1
  3. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/AnalyzeCommand.cs +7 -3
  4. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/RunCommand.cs +1 -1
  5. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Analyze.cs +26 -1
  6. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Discover.cs +2 -1
  7. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Run.cs +0 -6
  8. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Update.cs +1 -1
  9. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/AnalyzeWorker.cs +6 -1
  10. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/CompatabilityChecker.cs +24 -9
  11. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/DependencyFinder.cs +2 -0
  12. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/NuGetContext.cs +0 -13
  13. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/RequirementConverter.cs +17 -0
  14. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DiscoveryWorker.cs +44 -5
  15. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/PackagesConfigDiscovery.cs +2 -2
  16. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/ProjectDiscoveryResult.cs +2 -0
  17. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/SdkProjectDiscovery.cs +19 -11
  18. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ErrorType.cs +1 -0
  19. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ExperimentsManager.cs +3 -0
  20. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/Advisory.cs +13 -0
  21. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/AllowedUpdate.cs +18 -1
  22. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/CommitOptions.cs +8 -0
  23. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/Condition.cs +19 -0
  24. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/DependencyGroup.cs +8 -0
  25. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/GroupPullRequest.cs +9 -0
  26. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/Job.cs +13 -10
  27. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/PullRequest.cs +11 -0
  28. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/RequirementsUpdateStrategy.cs +15 -0
  29. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/RunWorker.cs +24 -4
  30. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/VersionConverter.cs +19 -0
  31. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/BindingRedirectManager.cs +2 -1
  32. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/LockFileUpdater.cs +3 -2
  33. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackageReferenceUpdater.cs +43 -18
  34. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackagesConfigUpdater.cs +13 -12
  35. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdaterWorker.cs +1 -1
  36. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/JsonHelper.cs +2 -0
  37. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +40 -14
  38. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/NuGetHelper.cs +2 -2
  39. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ProcessExtensions.cs +45 -7
  40. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ProjectHelper.cs +2 -2
  41. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTestBase.cs +5 -2
  42. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.DotNetToolsJson.cs +45 -1
  43. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.GlobalJson.cs +35 -1
  44. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Project.cs +0 -4
  45. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs +41 -0
  46. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/ExpectedDiscoveryResults.cs +1 -0
  47. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/SdkProjectDiscoveryTests.cs +1 -1
  48. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/MockNuGetPackage.cs +2 -1
  49. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/MiscellaneousTests.cs +85 -0
  50. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/RunWorkerTests.cs +7 -31
  51. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/SerializationTests.cs +340 -0
  52. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TemporaryDirectory.cs +18 -7
  53. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/PackagesConfigUpdaterTests.cs +24 -0
  54. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs +0 -12
  55. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.DotNetTools.cs +84 -0
  56. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.GlobalJson.cs +66 -0
  57. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackageReference.cs +55 -0
  58. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs +0 -6
  59. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/MSBuildHelperTests.cs +785 -755
  60. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/PathHelperTests.cs +2 -2
  61. data/lib/dependabot/nuget/analysis/analysis_json_reader.rb +1 -1
  62. data/lib/dependabot/nuget/analysis/dependency_analysis.rb +3 -3
  63. data/lib/dependabot/nuget/discovery/dependency_details.rb +10 -3
  64. data/lib/dependabot/nuget/discovery/dependency_file_discovery.rb +8 -12
  65. data/lib/dependabot/nuget/discovery/discovery_json_reader.rb +214 -29
  66. data/lib/dependabot/nuget/discovery/project_discovery.rb +41 -8
  67. data/lib/dependabot/nuget/discovery/workspace_discovery.rb +14 -19
  68. data/lib/dependabot/nuget/file_fetcher.rb +3 -3
  69. data/lib/dependabot/nuget/file_parser.rb +92 -3
  70. data/lib/dependabot/nuget/file_updater.rb +13 -13
  71. data/lib/dependabot/nuget/language.rb +82 -0
  72. data/lib/dependabot/nuget/native_helpers.rb +37 -5
  73. data/lib/dependabot/nuget/package_manager.rb +51 -0
  74. data/lib/dependabot/nuget/update_checker/requirements_updater.rb +23 -27
  75. data/lib/dependabot/nuget/update_checker.rb +116 -190
  76. metadata +20 -29
  77. data/lib/dependabot/nuget/discovery/directory_packages_props_discovery.rb +0 -43
  78. data/lib/dependabot/nuget/http_response_helpers.rb +0 -19
  79. data/lib/dependabot/nuget/native_discovery/native_dependency_details.rb +0 -102
  80. data/lib/dependabot/nuget/native_discovery/native_dependency_file_discovery.rb +0 -122
  81. data/lib/dependabot/nuget/native_discovery/native_discovery_json_reader.rb +0 -277
  82. data/lib/dependabot/nuget/native_discovery/native_evaluation_details.rb +0 -63
  83. data/lib/dependabot/nuget/native_discovery/native_project_discovery.rb +0 -104
  84. data/lib/dependabot/nuget/native_discovery/native_property_details.rb +0 -43
  85. data/lib/dependabot/nuget/native_discovery/native_workspace_discovery.rb +0 -61
  86. data/lib/dependabot/nuget/native_update_checker/native_requirements_updater.rb +0 -105
  87. data/lib/dependabot/nuget/native_update_checker/native_update_checker.rb +0 -214
  88. data/lib/dependabot/nuget/nuget_client.rb +0 -223
  89. data/lib/dependabot/nuget/update_checker/compatibility_checker.rb +0 -116
  90. data/lib/dependabot/nuget/update_checker/dependency_finder.rb +0 -297
  91. data/lib/dependabot/nuget/update_checker/nupkg_fetcher.rb +0 -221
  92. data/lib/dependabot/nuget/update_checker/nuspec_fetcher.rb +0 -110
  93. data/lib/dependabot/nuget/update_checker/property_updater.rb +0 -196
  94. data/lib/dependabot/nuget/update_checker/repository_finder.rb +0 -466
  95. data/lib/dependabot/nuget/update_checker/tfm_comparer.rb +0 -34
  96. data/lib/dependabot/nuget/update_checker/tfm_finder.rb +0 -30
  97. data/lib/dependabot/nuget/update_checker/version_finder.rb +0 -449
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 36551f131fff2d82f525e8eb3bd17f26da2d435f4c44484f2b91e0253f041e8f
4
- data.tar.gz: c97b1b5899bfac76abd674bf58f8853b7790b5e90d74089f2f663dd12f82fd89
3
+ metadata.gz: c3d38c911d42c1014432f79bd79e560129291135bb6f5039ff09e2e9229db253
4
+ data.tar.gz: a7417d90f096fb3de7a6a142b2b42c7aac61f299ba57d49ddbe1a1359d4dba3f
5
5
  SHA512:
6
- metadata.gz: '09e24d02174892b6d10f70bd7e26a200ff0f5d352ba3a69d826598a891d52990c3fd1e839088e4d797df0af6edb53fdb9f3ef9205352c2641cc818b3d603fb97'
7
- data.tar.gz: 3d9b2b81fee8ff8791796f9d7453f82cdd72a79d2ba3a103303475378fd387d9fb6caedb57688b322dffdb019172ca03910ae6256f79c392d99a233f110e585e
6
+ metadata.gz: b3cb757cc8d4a2ba7c0e3bc1f22e6d53e06e6de5bae39e460b86f9c697aaef7e95c0f62bf6583a63376c5367a6ec6e820389546f78dc3d7a190a331a1db720c6
7
+ data.tar.gz: f51885f03309f8e8d0f7359fffc41305c98e26f00a3e20af3ac67681f20c7e7d3f018e8093f89fe1591ac22a8f22453b49bb427d5a377aedb0a23f1cdfd1bffc
@@ -16,7 +16,7 @@
16
16
  <PackageVersion Include="Microsoft.Build.Framework" Version="$(MSBuildPackageVersion)" />
17
17
  <PackageVersion Include="Microsoft.Build.Tasks.Core" Version="$(MSBuildPackageVersion)" />
18
18
  <PackageVersion Include="Microsoft.Build.Utilities.Core" Version="$(MSBuildPackageVersion)" />
19
- <PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.11.0" />
19
+ <PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.12.0" />
20
20
  <PackageVersion Include="Microsoft.CSharp" Version="4.7.0" />
21
21
  <PackageVersion Include="Microsoft.Extensions.FileProviders.Abstractions" Version="9.0.0" />
22
22
  <PackageVersion Include="Microsoft.Extensions.FileSystemGlobbing" Version="9.0.0" />
@@ -7,6 +7,7 @@ namespace NuGetUpdater.Cli.Commands;
7
7
 
8
8
  internal static class AnalyzeCommand
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<FileInfo> DependencyFilePathOption = new("--dependency-file-path") { IsRequired = true };
12
13
  internal static readonly Option<FileInfo> DiscoveryFilePathOption = new("--discovery-file-path") { IsRequired = true };
@@ -16,6 +17,7 @@ internal static class AnalyzeCommand
16
17
  {
17
18
  Command command = new("analyze", "Determines how to update a dependency based on the workspace discovery information.")
18
19
  {
20
+ JobPathOption,
19
21
  RepoRootOption,
20
22
  DependencyFilePathOption,
21
23
  DiscoveryFilePathOption,
@@ -24,11 +26,13 @@ internal static class AnalyzeCommand
24
26
 
25
27
  command.TreatUnmatchedTokensAsErrors = true;
26
28
 
27
- command.SetHandler(async (repoRoot, discoveryPath, dependencyPath, analysisDirectory) =>
29
+ command.SetHandler(async (jobPath, repoRoot, discoveryPath, dependencyPath, analysisDirectory) =>
28
30
  {
29
- var worker = new AnalyzeWorker(new ConsoleLogger());
31
+ var logger = new ConsoleLogger();
32
+ var experimentsManager = await ExperimentsManager.FromJobFileAsync(jobPath.FullName, logger);
33
+ var worker = new AnalyzeWorker(experimentsManager, logger);
30
34
  await worker.RunAsync(repoRoot.FullName, discoveryPath.FullName, dependencyPath.FullName, analysisDirectory.FullName);
31
- }, RepoRootOption, DiscoveryFilePathOption, DependencyFilePathOption, AnalysisFolderOption);
35
+ }, JobPathOption, RepoRootOption, DiscoveryFilePathOption, DependencyFilePathOption, AnalysisFolderOption);
32
36
 
33
37
  return command;
34
38
  }
@@ -36,7 +36,7 @@ internal static class RunCommand
36
36
  var logger = new ConsoleLogger();
37
37
  var experimentsManager = await ExperimentsManager.FromJobFileAsync(jobPath.FullName, logger);
38
38
  var discoverWorker = new DiscoveryWorker(experimentsManager, logger);
39
- var analyzeWorker = new AnalyzeWorker(logger);
39
+ var analyzeWorker = new AnalyzeWorker(experimentsManager, logger);
40
40
  var updateWorker = new UpdaterWorker(experimentsManager, logger);
41
41
  var worker = new RunWorker(apiHandler, discoverWorker, analyzeWorker, updateWorker, logger);
42
42
  await worker.RunAsync(jobPath, repoContentsPath, baseCommitSha, outputPath);
@@ -26,6 +26,8 @@ public partial class EntryPointTests
26
26
  await RunAsync(path =>
27
27
  [
28
28
  "analyze",
29
+ "--job-path",
30
+ Path.Combine(path, "job.json"),
29
31
  "--repo-root",
30
32
  path,
31
33
  "--discovery-file-path",
@@ -144,6 +146,8 @@ public partial class EntryPointTests
144
146
  await RunAsync(path =>
145
147
  [
146
148
  "analyze",
149
+ "--job-path",
150
+ Path.Combine(path, "job.json"),
147
151
  "--repo-root",
148
152
  path,
149
153
  "--discovery-file-path",
@@ -231,6 +235,8 @@ public partial class EntryPointTests
231
235
  await RunAsync(path =>
232
236
  [
233
237
  "analyze",
238
+ "--job-path",
239
+ Path.Combine(path, "job.json"),
234
240
  "--repo-root",
235
241
  path,
236
242
  "--discovery-file-path",
@@ -308,8 +314,16 @@ public partial class EntryPointTests
308
314
  );
309
315
  }
310
316
 
311
- private static async Task RunAsync(Func<string, string[]> getArgs, string dependencyName, TestFile[] initialFiles, ExpectedAnalysisResult expectedResult, MockNuGetPackage[]? packages = null)
317
+ private static async Task RunAsync(
318
+ Func<string, string[]> getArgs,
319
+ string dependencyName,
320
+ TestFile[] initialFiles,
321
+ ExpectedAnalysisResult expectedResult,
322
+ MockNuGetPackage[]? packages = null,
323
+ ExperimentsManager? experimentsManager = null
324
+ )
312
325
  {
326
+ experimentsManager ??= new ExperimentsManager();
313
327
  var actualResult = await RunAnalyzerAsync(dependencyName, initialFiles, async path =>
314
328
  {
315
329
  var sb = new StringBuilder();
@@ -322,8 +336,19 @@ public partial class EntryPointTests
322
336
 
323
337
  try
324
338
  {
339
+ await UpdateWorkerTestBase.MockJobFileInDirectory(path, experimentsManager);
325
340
  await UpdateWorkerTestBase.MockNuGetPackagesInDirectory(packages, path);
326
341
  var args = getArgs(path);
342
+
343
+ // manually pull out the experiments manager for the validate step below
344
+ for (int i = 0; i < args.Length - 1; i++)
345
+ {
346
+ if (args[i] == "--job-path")
347
+ {
348
+ experimentsManager = await ExperimentsManager.FromJobFileAsync(args[i + 1], new TestLogger());
349
+ }
350
+ }
351
+
327
352
  var result = await Program.Main(args);
328
353
  if (result != 0)
329
354
  {
@@ -393,7 +393,8 @@ public partial class EntryPointTests
393
393
  TestFile[] initialFiles,
394
394
  ExpectedWorkspaceDiscoveryResult expectedResult,
395
395
  MockNuGetPackage[]? packages = null,
396
- ExperimentsManager? experimentsManager = null)
396
+ ExperimentsManager? experimentsManager = null
397
+ )
397
398
  {
398
399
  experimentsManager ??= new ExperimentsManager();
399
400
  var actualResult = await RunDiscoveryAsync(initialFiles, async path =>
@@ -41,12 +41,6 @@ public partial class EntryPointTests
41
41
  ],
42
42
  job: new Job()
43
43
  {
44
- AllowedUpdates = [
45
- new()
46
- {
47
- UpdateType = "all"
48
- }
49
- ],
50
44
  Source = new()
51
45
  {
52
46
  Provider = "github",
@@ -382,7 +382,7 @@ public partial class EntryPointTests
382
382
  workingDirectory = Path.Join(workingDirectory, workingDirectoryPath);
383
383
  }
384
384
 
385
- var (exitCode, output, error) = await ProcessEx.RunAsync("dotnet", executableArgs, workingDirectory: workingDirectory);
385
+ var (exitCode, output, error) = await ProcessEx.RunDotnetWithoutMSBuildEnvironmentVariablesAsync(executableArgs, workingDirectory, new ExperimentsManager() { InstallDotnetSdks = false });
386
386
  Assert.True(exitCode == 0, $"Error running update on unsupported SDK.\nSTDOUT:\n{output}\nSTDERR:\n{error}");
387
387
 
388
388
  // verify project update
@@ -16,6 +16,7 @@ public partial class AnalyzeWorker : IAnalyzeWorker
16
16
  {
17
17
  public const string AnalysisDirectoryName = "./.dependabot/analysis";
18
18
 
19
+ private readonly ExperimentsManager _experimentsManager;
19
20
  private readonly ILogger _logger;
20
21
 
21
22
  internal static readonly JsonSerializerOptions SerializerOptions = new()
@@ -24,8 +25,9 @@ public partial class AnalyzeWorker : IAnalyzeWorker
24
25
  Converters = { new JsonStringEnumConverter(), new RequirementArrayConverter() },
25
26
  };
26
27
 
27
- public AnalyzeWorker(ILogger logger)
28
+ public AnalyzeWorker(ExperimentsManager experimentsManager, ILogger logger)
28
29
  {
30
+ _experimentsManager = experimentsManager;
29
31
  _logger = logger;
30
32
  }
31
33
 
@@ -140,6 +142,7 @@ public partial class AnalyzeWorker : IAnalyzeWorker
140
142
  dependenciesToUpdate,
141
143
  updatedVersion,
142
144
  nugetContext,
145
+ _experimentsManager,
143
146
  _logger,
144
147
  CancellationToken.None);
145
148
  }
@@ -391,6 +394,7 @@ public partial class AnalyzeWorker : IAnalyzeWorker
391
394
  ImmutableHashSet<string> packageIds,
392
395
  NuGetVersion updatedVersion,
393
396
  NuGetContext nugetContext,
397
+ ExperimentsManager experimentsManager,
394
398
  ILogger logger,
395
399
  CancellationToken cancellationToken)
396
400
  {
@@ -430,6 +434,7 @@ public partial class AnalyzeWorker : IAnalyzeWorker
430
434
  packageIds,
431
435
  updatedVersion,
432
436
  nugetContext,
437
+ experimentsManager,
433
438
  logger,
434
439
  cancellationToken);
435
440
 
@@ -80,9 +80,9 @@ internal static class CompatibilityChecker
80
80
  NuGetContext nugetContext,
81
81
  CancellationToken cancellationToken)
82
82
  {
83
- var tempPackagePath = GetTempPackagePath(package, nugetContext);
84
- var readers = File.Exists(tempPackagePath)
85
- ? ReadPackage(tempPackagePath)
83
+ var packagePath = GetPackagePath(package, nugetContext);
84
+ var readers = File.Exists(packagePath)
85
+ ? ReadPackage(packagePath)
86
86
  : await DownloadPackageAsync(package, nugetContext, cancellationToken);
87
87
  return readers;
88
88
  }
@@ -134,10 +134,10 @@ internal static class CompatibilityChecker
134
134
  return (isDevDependency, tfms.ToImmutableArray());
135
135
  }
136
136
 
137
- internal static PackageReaders ReadPackage(string tempPackagePath)
137
+ internal static PackageReaders ReadPackage(string packagePath)
138
138
  {
139
139
  var stream = new FileStream(
140
- tempPackagePath,
140
+ packagePath,
141
141
  FileMode.Open,
142
142
  FileAccess.Read,
143
143
  FileShare.Read,
@@ -194,8 +194,8 @@ internal static class CompatibilityChecker
194
194
  context.Logger,
195
195
  cancellationToken);
196
196
 
197
- var tempPackagePath = GetTempPackagePath(package, context);
198
- var isDownloaded = await downloader.CopyNupkgFileToAsync(tempPackagePath, cancellationToken);
197
+ var packagePath = GetPackagePath(package, context);
198
+ var isDownloaded = await downloader.CopyNupkgFileToAsync(packagePath, cancellationToken);
199
199
  if (!isDownloaded)
200
200
  {
201
201
  continue;
@@ -207,6 +207,21 @@ internal static class CompatibilityChecker
207
207
  return null;
208
208
  }
209
209
 
210
- internal static string GetTempPackagePath(PackageIdentity package, NuGetContext context)
211
- => Path.Combine(context.TempPackageDirectory, package.Id + "." + package.Version + ".nupkg");
210
+ internal static string GetPackagePath(PackageIdentity package, NuGetContext context)
211
+ {
212
+ // https://learn.microsoft.com/en-us/nuget/consume-packages/managing-the-global-packages-and-cache-folders
213
+ var nugetPackagesPath = Environment.GetEnvironmentVariable("NUGET_PACKAGES");
214
+ if (nugetPackagesPath is null)
215
+ {
216
+ // n.b., this path should never be hit during a unit test
217
+ nugetPackagesPath = Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".nuget", "packages");
218
+ }
219
+
220
+ var normalizedName = package.Id.ToLowerInvariant();
221
+ var normalizedVersion = package.Version.ToNormalizedString().ToLowerInvariant();
222
+ var packageDirectory = Path.Join(nugetPackagesPath, normalizedName, normalizedVersion);
223
+ Directory.CreateDirectory(packageDirectory);
224
+ var packagePath = Path.Join(packageDirectory, $"{normalizedName}.{normalizedVersion}.nupkg");
225
+ return packagePath;
226
+ }
212
227
  }
@@ -14,6 +14,7 @@ internal static class DependencyFinder
14
14
  ImmutableHashSet<string> packageIds,
15
15
  NuGetVersion version,
16
16
  NuGetContext nugetContext,
17
+ ExperimentsManager experimentsManager,
17
18
  ILogger logger,
18
19
  CancellationToken cancellationToken)
19
20
  {
@@ -30,6 +31,7 @@ internal static class DependencyFinder
30
31
  projectPath,
31
32
  framework.ToString(),
32
33
  packages,
34
+ experimentsManager,
33
35
  logger);
34
36
  var updatedDependencies = new List<Dependency>();
35
37
  foreach (var dependency in dependencies)
@@ -20,7 +20,6 @@ internal record NuGetContext : IDisposable
20
20
  public IMachineWideSettings MachineWideSettings { get; }
21
21
  public ImmutableArray<PackageSource> PackageSources { get; }
22
22
  public NuGet.Common.ILogger Logger { get; }
23
- public string TempPackageDirectory { get; }
24
23
 
25
24
  public NuGetContext(string? currentDirectory = null, NuGet.Common.ILogger? logger = null)
26
25
  {
@@ -37,23 +36,11 @@ internal record NuGetContext : IDisposable
37
36
  .Where(p => p.IsEnabled)
38
37
  .ToImmutableArray();
39
38
  Logger = logger ?? NullLogger.Instance;
40
- TempPackageDirectory = Path.Combine(Path.GetTempPath(), $"dependabot-packages_{Guid.NewGuid():d}");
41
- Directory.CreateDirectory(TempPackageDirectory);
42
39
  }
43
40
 
44
41
  public void Dispose()
45
42
  {
46
43
  SourceCacheContext.Dispose();
47
- if (Directory.Exists(TempPackageDirectory))
48
- {
49
- try
50
- {
51
- Directory.Delete(TempPackageDirectory, recursive: true);
52
- }
53
- catch
54
- {
55
- }
56
- }
57
44
  }
58
45
 
59
46
  private readonly Dictionary<PackageIdentity, string?> _packageInfoUrlCache = new();
@@ -0,0 +1,17 @@
1
+ using System.Text.Json;
2
+ using System.Text.Json.Serialization;
3
+
4
+ namespace NuGetUpdater.Core.Analyze;
5
+
6
+ public class RequirementConverter : JsonConverter<Requirement>
7
+ {
8
+ public override Requirement? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
9
+ {
10
+ return Requirement.Parse(reader.GetString()!);
11
+ }
12
+
13
+ public override void Write(Utf8JsonWriter writer, Requirement value, JsonSerializerOptions options)
14
+ {
15
+ writer.WriteStringValue(value.ToString());
16
+ }
17
+ }
@@ -6,6 +6,7 @@ using System.Text.Json.Serialization;
6
6
  using Microsoft.Build.Construction;
7
7
  using Microsoft.Build.Definition;
8
8
  using Microsoft.Build.Evaluation;
9
+ using Microsoft.Build.Exceptions;
9
10
 
10
11
  using NuGetUpdater.Core.Analyze;
11
12
  using NuGetUpdater.Core.Utilities;
@@ -93,13 +94,31 @@ public partial class DiscoveryWorker : IDiscoveryWorker
93
94
  }
94
95
 
95
96
  // this next line should throw or something
96
- projectResults = await RunForDirectoryAsnyc(repoRootPath, workspacePath);
97
+ projectResults = await RunForDirectoryAsync(repoRootPath, workspacePath);
97
98
  }
98
99
  else
99
100
  {
100
101
  _logger.Info($"Workspace path [{workspacePath}] does not exist.");
101
102
  }
102
103
 
104
+ //if any projectResults are not successful, return a failed result
105
+ if (projectResults.Any(p => p.IsSuccess == false))
106
+ {
107
+ var failedProjectResult = projectResults.Where(p => p.IsSuccess == false).First();
108
+ var failedDiscoveryResult = new WorkspaceDiscoveryResult
109
+ {
110
+ Path = initialWorkspacePath,
111
+ DotNetToolsJson = null,
112
+ GlobalJson = null,
113
+ Projects = projectResults.Where(p => p.IsSuccess).OrderBy(p => p.FilePath).ToImmutableArray(),
114
+ ErrorType = failedProjectResult.ErrorType,
115
+ ErrorDetails = failedProjectResult.FilePath,
116
+ IsSuccess = false,
117
+ };
118
+
119
+ return failedDiscoveryResult;
120
+ }
121
+
103
122
  result = new WorkspaceDiscoveryResult
104
123
  {
105
124
  Path = initialWorkspacePath,
@@ -137,14 +156,34 @@ public partial class DiscoveryWorker : IDiscoveryWorker
137
156
 
138
157
  _logger.Info($" Restoring MSBuild SDKs: {string.Join(", ", keys)}");
139
158
 
140
- return await NuGetHelper.DownloadNuGetPackagesAsync(repoRootPath, workspacePath, msbuildSdks, logger);
159
+ return await NuGetHelper.DownloadNuGetPackagesAsync(repoRootPath, workspacePath, msbuildSdks, _experimentsManager, logger);
141
160
  }
142
161
 
143
- private async Task<ImmutableArray<ProjectDiscoveryResult>> RunForDirectoryAsnyc(string repoRootPath, string workspacePath)
162
+ private async Task<ImmutableArray<ProjectDiscoveryResult>> RunForDirectoryAsync(string repoRootPath, string workspacePath)
144
163
  {
145
164
  _logger.Info($" Discovering projects beneath [{Path.GetRelativePath(repoRootPath, workspacePath)}].");
146
165
  var entryPoints = FindEntryPoints(workspacePath);
147
- var projects = ExpandEntryPointsIntoProjects(entryPoints);
166
+ ImmutableArray<string> projects;
167
+ try
168
+ {
169
+ projects = ExpandEntryPointsIntoProjects(entryPoints);
170
+ }
171
+ catch (InvalidProjectFileException e)
172
+ {
173
+ var invalidProjectFile = Path.GetRelativePath(workspacePath, e.ProjectFile).NormalizePathToUnix();
174
+
175
+ _logger.Info("Error encountered during discovery: " + e.Message);
176
+ return [new ProjectDiscoveryResult
177
+ {
178
+ FilePath = invalidProjectFile,
179
+ Dependencies = ImmutableArray<Dependency>.Empty,
180
+ ImportedFiles = ImmutableArray<string>.Empty,
181
+ AdditionalFiles = ImmutableArray<string>.Empty,
182
+ IsSuccess = false,
183
+ ErrorType = ErrorType.DependencyFileNotParseable,
184
+ ErrorDetails = "Failed to parse project file found at " + invalidProjectFile,
185
+ }];
186
+ }
148
187
  if (projects.IsEmpty)
149
188
  {
150
189
  _logger.Info(" No project files found.");
@@ -286,7 +325,7 @@ public partial class DiscoveryWorker : IDiscoveryWorker
286
325
  _processedProjectPaths.Add(actualProjectPath);
287
326
 
288
327
  var relativeProjectPath = Path.GetRelativePath(workspacePath, actualProjectPath).NormalizePathToUnix();
289
- var packagesConfigResult = await PackagesConfigDiscovery.Discover(repoRootPath, workspacePath, actualProjectPath, _logger);
328
+ var packagesConfigResult = await PackagesConfigDiscovery.Discover(repoRootPath, workspacePath, actualProjectPath, _experimentsManager, _logger);
290
329
  var projectResults = await SdkProjectDiscovery.DiscoverAsync(repoRootPath, workspacePath, actualProjectPath, _experimentsManager, _logger);
291
330
 
292
331
  // Determine if there were unrestored MSBuildSdks
@@ -6,7 +6,7 @@ namespace NuGetUpdater.Core.Discover;
6
6
 
7
7
  internal static class PackagesConfigDiscovery
8
8
  {
9
- public static async Task<PackagesConfigDiscoveryResult?> Discover(string repoRootPath, string workspacePath, string projectPath, ILogger logger)
9
+ public static async Task<PackagesConfigDiscoveryResult?> Discover(string repoRootPath, string workspacePath, string projectPath, ExperimentsManager experimentsManager, ILogger logger)
10
10
  {
11
11
  var projectDirectory = Path.GetDirectoryName(projectPath)!;
12
12
  var additionalFiles = ProjectHelper.GetAllAdditionalFilesFromProject(projectPath, ProjectHelper.PathFormat.Full);
@@ -27,7 +27,7 @@ internal static class PackagesConfigDiscovery
27
27
  .ToImmutableArray();
28
28
 
29
29
  // generate `$(TargetFramework)` via MSBuild
30
- var tfms = await MSBuildHelper.GetTargetFrameworkValuesFromProject(repoRootPath, projectPath, logger);
30
+ var tfms = await MSBuildHelper.GetTargetFrameworkValuesFromProject(repoRootPath, projectPath, experimentsManager, logger);
31
31
 
32
32
  var additionalFilesRelative = additionalFiles.Select(p => Path.GetRelativePath(projectDirectory, p).NormalizePathToUnix()).ToImmutableArray();
33
33
  return new()
@@ -8,6 +8,8 @@ public record ProjectDiscoveryResult : IDiscoveryResultWithDependencies
8
8
  public required string FilePath { get; init; }
9
9
  public required ImmutableArray<Dependency> Dependencies { get; init; }
10
10
  public bool IsSuccess { get; init; } = true;
11
+ public string? ErrorDetails { get; init; }
12
+ public ErrorType? ErrorType { get; init; }
11
13
  public ImmutableArray<Property> Properties { get; init; } = [];
12
14
  public ImmutableArray<string> TargetFrameworks { get; init; } = [];
13
15
  public ImmutableArray<string> ReferencedProjectPaths { get; init; } = [];
@@ -48,15 +48,15 @@ internal static class SdkProjectDiscovery
48
48
  {
49
49
  if (experimentsManager.UseDirectDiscovery)
50
50
  {
51
- return await DiscoverWithBinLogAsync(repoRootPath, workspacePath, startingProjectPath, logger);
51
+ return await DiscoverWithBinLogAsync(repoRootPath, workspacePath, startingProjectPath, experimentsManager, logger);
52
52
  }
53
53
  else
54
54
  {
55
- return await DiscoverWithTempProjectAsync(repoRootPath, workspacePath, startingProjectPath, logger);
55
+ return await DiscoverWithTempProjectAsync(repoRootPath, workspacePath, startingProjectPath, experimentsManager, logger);
56
56
  }
57
57
  }
58
58
 
59
- public static async Task<ImmutableArray<ProjectDiscoveryResult>> DiscoverWithBinLogAsync(string repoRootPath, string workspacePath, string startingProjectPath, ILogger logger)
59
+ public static async Task<ImmutableArray<ProjectDiscoveryResult>> DiscoverWithBinLogAsync(string repoRootPath, string workspacePath, string startingProjectPath, ExperimentsManager experimentsManager, ILogger logger)
60
60
  {
61
61
  // N.b., there are many paths used in this function. The MSBuild binary log always reports fully qualified paths, so that's what will be used
62
62
  // throughout until the very end when the appropriate kind of relative path is returned.
@@ -84,7 +84,7 @@ internal static class SdkProjectDiscovery
84
84
  Dictionary<string, HashSet<string>> additionalFiles = new(PathComparer.Instance);
85
85
  // projectPath, additionalFiles
86
86
 
87
- var tfms = await MSBuildHelper.GetTargetFrameworkValuesFromProject(repoRootPath, startingProjectPath, logger);
87
+ var tfms = await MSBuildHelper.GetTargetFrameworkValuesFromProject(repoRootPath, startingProjectPath, experimentsManager, logger);
88
88
  foreach (var tfm in tfms)
89
89
  {
90
90
  // create a binlog
@@ -92,7 +92,7 @@ internal static class SdkProjectDiscovery
92
92
  try
93
93
  {
94
94
  // TODO: once the updater image has all relevant SDKs installed, we won't have to sideline global.json anymore
95
- var (exitCode, stdOut, stdErr) = await MSBuildHelper.SidelineGlobalJsonAsync(startingProjectDirectory, repoRootPath, async () =>
95
+ var (exitCode, stdOut, stdErr) = await MSBuildHelper.HandleGlobalJsonAsync(startingProjectDirectory, repoRootPath, experimentsManager, async () =>
96
96
  {
97
97
  // the built-in target `GenerateBuildDependencyFile` forces resolution of all NuGet packages, but doesn't invoke a full build
98
98
  var dependencyDiscoveryTargetsPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!, "DependencyDiscovery.targets");
@@ -102,10 +102,11 @@ internal static class SdkProjectDiscovery
102
102
  startingProjectPath,
103
103
  "/t:_DiscoverDependencies",
104
104
  $"/p:TargetFramework={tfm}",
105
- $"/p:CustomAfterMicrosoftCommonCrossTargetingTargets={dependencyDiscoveryTargetsPath};CustomAfterMicrosoftCommonTargets={dependencyDiscoveryTargetsPath}",
105
+ $"/p:CustomAfterMicrosoftCommonCrossTargetingTargets={dependencyDiscoveryTargetsPath}",
106
+ $"/p:CustomAfterMicrosoftCommonTargets={dependencyDiscoveryTargetsPath}",
106
107
  $"/bl:{binLogPath}"
107
108
  };
108
- var (exitCode, stdOut, stdErr) = await ProcessEx.RunAsync("dotnet", args, workingDirectory: startingProjectDirectory);
109
+ var (exitCode, stdOut, stdErr) = await ProcessEx.RunDotnetWithoutMSBuildEnvironmentVariablesAsync(args, startingProjectDirectory, experimentsManager);
109
110
  return (exitCode, stdOut, stdErr);
110
111
  }, logger, retainMSBuildSdks: true);
111
112
  MSBuildHelper.ThrowOnUnauthenticatedFeed(stdOut);
@@ -411,7 +412,7 @@ internal static class SdkProjectDiscovery
411
412
  return property.Value;
412
413
  }
413
414
 
414
- public static async Task<ImmutableArray<ProjectDiscoveryResult>> DiscoverWithTempProjectAsync(string repoRootPath, string workspacePath, string projectPath, ILogger logger)
415
+ public static async Task<ImmutableArray<ProjectDiscoveryResult>> DiscoverWithTempProjectAsync(string repoRootPath, string workspacePath, string projectPath, ExperimentsManager experimentsManager, ILogger logger)
415
416
  {
416
417
  // Determine which targets and props files contribute to the build.
417
418
  var (buildFiles, projectTargetFrameworks) = await MSBuildHelper.LoadBuildFilesAndTargetFrameworksAsync(repoRootPath, projectPath);
@@ -476,7 +477,7 @@ internal static class SdkProjectDiscovery
476
477
  dependencies = dependencies
477
478
  .Select(d => d with { TargetFrameworks = tfms })
478
479
  .ToImmutableArray();
479
- var transitiveDependencies = await GetTransitiveDependencies(repoRootPath, projectPath, tfms, dependencies, logger);
480
+ var transitiveDependencies = await GetTransitiveDependencies(repoRootPath, projectPath, tfms, dependencies, experimentsManager, logger);
480
481
  ImmutableArray<Dependency> allDependencies = dependencies.Concat(transitiveDependencies).Concat(sdkDependencies)
481
482
  .OrderBy(d => d.Name)
482
483
  .ToImmutableArray();
@@ -514,12 +515,19 @@ internal static class SdkProjectDiscovery
514
515
  return results.ToImmutable();
515
516
  }
516
517
 
517
- private static async Task<ImmutableArray<Dependency>> GetTransitiveDependencies(string repoRootPath, string projectPath, ImmutableArray<string> tfms, ImmutableArray<Dependency> directDependencies, ILogger logger)
518
+ private static async Task<ImmutableArray<Dependency>> GetTransitiveDependencies(
519
+ string repoRootPath,
520
+ string projectPath,
521
+ ImmutableArray<string> tfms,
522
+ ImmutableArray<Dependency> directDependencies,
523
+ ExperimentsManager experimentsManager,
524
+ ILogger logger
525
+ )
518
526
  {
519
527
  Dictionary<string, Dependency> transitiveDependencies = new(StringComparer.OrdinalIgnoreCase);
520
528
  foreach (var tfm in tfms)
521
529
  {
522
- var tfmDependencies = await MSBuildHelper.GetAllPackageDependenciesAsync(repoRootPath, projectPath, tfm, directDependencies, logger);
530
+ var tfmDependencies = await MSBuildHelper.GetAllPackageDependenciesAsync(repoRootPath, projectPath, tfm, directDependencies, experimentsManager, logger);
523
531
  foreach (var dependency in tfmDependencies.Where(d => d.IsTransitive))
524
532
  {
525
533
  if (!transitiveDependencies.TryGetValue(dependency.Name, out var existingDependency))
@@ -6,5 +6,6 @@ public enum ErrorType
6
6
  AuthenticationFailure,
7
7
  MissingFile,
8
8
  UpdateNotPossible,
9
+ DependencyFileNotParseable,
9
10
  Unknown,
10
11
  }
@@ -6,6 +6,7 @@ namespace NuGetUpdater.Core;
6
6
 
7
7
  public record ExperimentsManager
8
8
  {
9
+ public bool InstallDotnetSdks { get; init; } = false;
9
10
  public bool UseLegacyDependencySolver { get; init; } = false;
10
11
  public bool UseDirectDiscovery { get; init; } = false;
11
12
 
@@ -13,6 +14,7 @@ public record ExperimentsManager
13
14
  {
14
15
  return new()
15
16
  {
17
+ ["nuget_install_dotnet_sdks"] = InstallDotnetSdks,
16
18
  ["nuget_legacy_dependency_solver"] = UseLegacyDependencySolver,
17
19
  ["nuget_use_direct_discovery"] = UseDirectDiscovery,
18
20
  };
@@ -22,6 +24,7 @@ public record ExperimentsManager
22
24
  {
23
25
  return new ExperimentsManager()
24
26
  {
27
+ InstallDotnetSdks = IsEnabled(experiments, "nuget_install_dotnet_sdks"),
25
28
  UseLegacyDependencySolver = IsEnabled(experiments, "nuget_legacy_dependency_solver"),
26
29
  UseDirectDiscovery = IsEnabled(experiments, "nuget_use_direct_discovery"),
27
30
  };
@@ -0,0 +1,13 @@
1
+ using System.Collections.Immutable;
2
+
3
+ using NuGetUpdater.Core.Analyze;
4
+
5
+ namespace NuGetUpdater.Core.Run.ApiModel;
6
+
7
+ public record Advisory
8
+ {
9
+ public required string DependencyName { get; init; }
10
+ public ImmutableArray<Requirement>? AffectedVersions { get; init; } = null;
11
+ public ImmutableArray<Requirement>? PatchedVersions { get; init; } = null;
12
+ public ImmutableArray<Requirement>? UnaffectedVersions { get; init; } = null;
13
+ }
@@ -2,5 +2,22 @@ namespace NuGetUpdater.Core.Run.ApiModel;
2
2
 
3
3
  public sealed record AllowedUpdate
4
4
  {
5
- public string UpdateType { get; init; } = "all";
5
+ public DependencyType DependencyType { get; init; } = DependencyType.All;
6
+ public string? DependencyName { get; init; } = null;
7
+ public UpdateType UpdateType { get; init; } = UpdateType.All;
8
+ }
9
+
10
+ public enum DependencyType
11
+ {
12
+ All,
13
+ Direct,
14
+ Indirect,
15
+ Development,
16
+ Production,
17
+ }
18
+
19
+ public enum UpdateType
20
+ {
21
+ All,
22
+ Security,
6
23
  }
@@ -0,0 +1,8 @@
1
+ namespace NuGetUpdater.Core.Run.ApiModel;
2
+
3
+ public record CommitOptions
4
+ {
5
+ public string? Prefix { get; init; } = null;
6
+ public string? PrefixDevelopment { get; init; } = null;
7
+ public string? IncludeScope { get; init; } = null;
8
+ }
@@ -0,0 +1,19 @@
1
+ using System.Text.Json.Serialization;
2
+
3
+ using NuGetUpdater.Core.Analyze;
4
+
5
+ namespace NuGetUpdater.Core.Run.ApiModel;
6
+
7
+ public sealed record Condition
8
+ {
9
+ [JsonPropertyName("dependency-name")]
10
+ public required string DependencyName { get; init; }
11
+ [JsonPropertyName("source")]
12
+ public string? Source { get; init; } = null;
13
+ [JsonPropertyName("update-types")]
14
+ public string[] UpdateTypes { get; init; } = [];
15
+ [JsonPropertyName("updated-at")]
16
+ public DateTime? UpdatedAt { get; init; } = null;
17
+ [JsonPropertyName("version-requirement")]
18
+ public Requirement? VersionRequirement { get; init; } = null;
19
+ }