dependabot-nuget 0.289.0 → 0.291.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }