dependabot-nuget 0.278.0 → 0.280.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/helpers/build +1 -1
  3. data/helpers/lib/NuGetUpdater/.editorconfig +1 -0
  4. data/helpers/lib/NuGetUpdater/Directory.Build.props +1 -0
  5. data/helpers/lib/NuGetUpdater/Directory.Common.props +1 -1
  6. data/helpers/lib/NuGetUpdater/Directory.Packages.props +6 -1
  7. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Analyze.cs +7 -0
  8. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Discover.cs +6 -0
  9. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Update.cs +2 -3
  10. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/AnalyzeWorker.cs +95 -84
  11. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/Requirement.cs +2 -2
  12. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DiscoveryWorker.cs +53 -46
  13. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ErrorType.cs +1 -0
  14. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/NativeResult.cs +1 -1
  15. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/DependencyFileNotFound.cs +6 -0
  16. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/JobErrorBase.cs +11 -0
  17. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/PrivateSourceAuthenticationFailure.cs +6 -0
  18. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/UnknownError.cs +6 -0
  19. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/UpdateNotPossible.cs +6 -0
  20. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/HttpApiHandler.cs +5 -0
  21. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/IApiHandler.cs +1 -0
  22. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/RunWorker.cs +67 -15
  23. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/UpdateNotPossibleException.cs +11 -0
  24. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/LockFileUpdater.cs +1 -1
  25. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackagesConfigUpdater.cs +2 -0
  26. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/SdkPackageUpdater.cs +2 -2
  27. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdaterWorker.cs +58 -39
  28. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +16 -5
  29. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/NuGetHelper.cs +1 -1
  30. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ProcessExtensions.cs +2 -4
  31. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTestBase.cs +5 -9
  32. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/RequirementTests.cs +4 -1
  33. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTestBase.cs +5 -8
  34. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/MockNuGetPackage.cs +10 -1
  35. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/RunWorkerTests.cs +92 -0
  36. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/TestApiHandler.cs +10 -4
  37. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs +10 -15
  38. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs +79 -1
  39. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Sdk.cs +10 -1
  40. data/helpers/lib/NuGetUpdater/global.json +1 -1
  41. data/lib/dependabot/nuget/file_updater.rb +5 -1
  42. data/lib/dependabot/nuget/native_helpers.rb +9 -4
  43. data/lib/dependabot/nuget/requirement.rb +2 -0
  44. data/lib/dependabot/nuget/update_checker/repository_finder.rb +26 -2
  45. metadata +16 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d29298584fd13989b51d63574bc462c199b1db8144a2a28b6c893ae90bf41dec
4
- data.tar.gz: f2fc3a71de6471f5cca05fe294ce492bb4dbb1837ce2feb03bf40cfcec9ff4cb
3
+ metadata.gz: 2728d8749a316ac4ecbd46826beffaefc51e5101c1154d0fdef5ad756158c256
4
+ data.tar.gz: 3ec34208b76ed22dbef3ae0e49511e77f85d73aea1b980180292b5225e26367a
5
5
  SHA512:
6
- metadata.gz: 80ad942cbaf12ad2bec0eacf04124a26cb37b4a8f54cda4f3290f9a4b8c776f16a907cd963099634be43d925c64f0bef54ef5247632360954e9e28064bcda676
7
- data.tar.gz: f413dfafd425032365e31d9c0969a94c6c8ac8195efe0de8b922ab464575fac246276012a6ceca8b1f9f55b10e3d8fb49d9cd5c4390f281674782a04a91b15ca
6
+ metadata.gz: 4cf2906e79a866fb5c4d89807e893d6486f1fae08b9b951da9a049fbd546cc59d522d6b8ace80fe0ee59353eb93224b648370b404bf69ff845d89fafd70894ba
7
+ data.tar.gz: '05801823dee91eba1e490ee4fef1d44a2e83f632c7823c5ae6bd9cd3955d085c8c6c5e015023c4a6a0e34ed453e2e3d956c9399f955d608fd87381ef2ff620d7'
data/helpers/build CHANGED
@@ -32,7 +32,7 @@ cd "$install_dir/lib/NuGetUpdater/NuGetUpdater.Cli"
32
32
  dotnet publish \
33
33
  --configuration Release \
34
34
  --output "$install_dir/NuGetUpdater" \
35
- --framework net8.0 \
35
+ --framework net9.0 \
36
36
  --runtime "$os-$arch"
37
37
  dotnet clean
38
38
 
@@ -20,6 +20,7 @@ tab_width = 4
20
20
 
21
21
  # New line preferences
22
22
  insert_final_newline = true
23
+ end_of_line = lf
23
24
 
24
25
  #### .NET Coding Conventions ####
25
26
  [*.{cs,vb}]
@@ -1,6 +1,7 @@
1
1
  <Project>
2
2
 
3
3
  <PropertyGroup>
4
+ <CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
4
5
  <NoWarn>$(NoWarn);NU1701</NoWarn>
5
6
  <Nullable>enable</Nullable>
6
7
  </PropertyGroup>
@@ -9,7 +9,7 @@
9
9
  NuGetUpdater\NuGetUpdater.Core\FrameworkChecker\SupportedFrameworks.cs
10
10
  2. Update tests as needed at `NuGetUpdater\NuGetUpdater.Core.Test\FrameworkChecker\CompatibilityCheckerFacts.cs`
11
11
  -->
12
- <CommonTargetFramework>net8.0</CommonTargetFramework>
12
+ <CommonTargetFramework>net9.0</CommonTargetFramework>
13
13
  <ImplicitUsings>enable</ImplicitUsings>
14
14
  <UseArtifactsOutput>true</UseArtifactsOutput>
15
15
  <ArtifactsPath>$(MSBuildThisFileDirectory)artifacts</ArtifactsPath>
@@ -7,7 +7,7 @@
7
7
  <ItemGroup>
8
8
  <PackageVersion Include="DiffPlex" Version="1.7.1" />
9
9
 
10
- <PackageVersion Include="GuiLabs.Language.Xml" Version="1.2.60" />
10
+ <PackageVersion Include="GuiLabs.Language.Xml" Version="1.2.93" />
11
11
 
12
12
  <PackageVersion Include="Microsoft.Build.Locator" Version="1.6.1" />
13
13
  <PackageVersion Include="Microsoft.Build" Version="17.5.0" ExcludeAssets="Runtime" PrivateAssets="All" />
@@ -20,6 +20,11 @@
20
20
  <PackageVersion Include="NuGet.Core" Version="2.14.0-rtm-832" Aliases="CoreV2" />
21
21
 
22
22
  <PackageVersion Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
23
+ <PackageVersion Include="System.Net.Http" Version="4.3.4" />
24
+ <PackageVersion Include="System.Formats.Asn1" Version="8.0.1" />
25
+ <PackageVersion Include="System.Security.Cryptography.Pkcs" Version="8.0.0" />
26
+ <PackageVersion Include="System.Text.Json" Version="8.0.4" />
27
+ <PackageVersion Include="System.Text.RegularExpressions" Version="4.3.1" />
23
28
 
24
29
  <PackageVersion Include="xunit" Version="2.4.2" />
25
30
  <PackageVersion Include="xunit.runner.visualstudio" Version="2.4.5" />
@@ -1,8 +1,10 @@
1
1
  using System.Text;
2
+ using System.Text.Json;
2
3
  using System.Xml.Linq;
3
4
 
4
5
  using NuGetUpdater.Core;
5
6
  using NuGetUpdater.Core.Analyze;
7
+ using NuGetUpdater.Core.Discover;
6
8
  using NuGetUpdater.Core.Test;
7
9
  using NuGetUpdater.Core.Test.Analyze;
8
10
  using NuGetUpdater.Core.Test.Update;
@@ -334,6 +336,11 @@ public partial class EntryPointTests
334
336
  Console.SetOut(originalOut);
335
337
  Console.SetError(originalErr);
336
338
  }
339
+
340
+ var resultPath = Path.Join(path, AnalyzeWorker.AnalysisDirectoryName, $"{dependencyName}.json");
341
+ var resultJson = await File.ReadAllTextAsync(resultPath);
342
+ var resultObject = JsonSerializer.Deserialize<AnalysisResult>(resultJson, DiscoveryWorker.SerializerOptions);
343
+ return resultObject!;
337
344
  });
338
345
 
339
346
  ValidateAnalysisResult(expectedResult, actualResult);
@@ -1,4 +1,5 @@
1
1
  using System.Text;
2
+ using System.Text.Json;
2
3
 
3
4
  using NuGetUpdater.Core;
4
5
  using NuGetUpdater.Core.Discover;
@@ -390,6 +391,11 @@ public partial class EntryPointTests
390
391
  Console.SetOut(originalOut);
391
392
  Console.SetError(originalErr);
392
393
  }
394
+
395
+ var resultPath = Path.Join(path, DiscoveryWorker.DiscoveryResultFileName);
396
+ var resultJson = await File.ReadAllTextAsync(resultPath);
397
+ var resultObject = JsonSerializer.Deserialize<WorkspaceDiscoveryResult>(resultJson, DiscoveryWorker.SerializerOptions);
398
+ return resultObject!;
393
399
  });
394
400
 
395
401
  ValidateWorkspaceResult(expectedResult, actualResult);
@@ -352,8 +352,7 @@ public partial class EntryPointTests
352
352
  </Project>
353
353
  """);
354
354
  var executableName = Path.Join(Path.GetDirectoryName(GetType().Assembly.Location), "NuGetUpdater.Cli.dll");
355
- var executableArgs = string.Join(" ",
356
- [
355
+ IEnumerable<string> executableArgs = [
357
356
  executableName,
358
357
  "update",
359
358
  "--repo-root",
@@ -367,7 +366,7 @@ public partial class EntryPointTests
367
366
  "--previous-version",
368
367
  "7.0.1",
369
368
  "--verbose"
370
- ]);
369
+ ];
371
370
 
372
371
  // verify base run
373
372
  var workingDirectory = tempDir.DirectoryPath;
@@ -31,12 +31,39 @@ public partial class AnalyzeWorker
31
31
 
32
32
  public async Task RunAsync(string repoRoot, string discoveryPath, string dependencyPath, string analysisDirectory)
33
33
  {
34
- var discovery = await DeserializeJsonFileAsync<WorkspaceDiscoveryResult>(discoveryPath, nameof(WorkspaceDiscoveryResult));
34
+ var analysisResult = await RunWithErrorHandlingAsync(repoRoot, discoveryPath, dependencyPath);
35
35
  var dependencyInfo = await DeserializeJsonFileAsync<DependencyInfo>(dependencyPath, nameof(DependencyInfo));
36
- var analysisResult = await RunAsync(repoRoot, discovery, dependencyInfo);
37
36
  await WriteResultsAsync(analysisDirectory, dependencyInfo.Name, analysisResult, _logger);
38
37
  }
39
38
 
39
+ internal async Task<AnalysisResult> RunWithErrorHandlingAsync(string repoRoot, string discoveryPath, string dependencyPath)
40
+ {
41
+ AnalysisResult analysisResult;
42
+ var discovery = await DeserializeJsonFileAsync<WorkspaceDiscoveryResult>(discoveryPath, nameof(WorkspaceDiscoveryResult));
43
+ var dependencyInfo = await DeserializeJsonFileAsync<DependencyInfo>(dependencyPath, nameof(DependencyInfo));
44
+
45
+ try
46
+ {
47
+ analysisResult = await RunAsync(repoRoot, discovery, dependencyInfo);
48
+ }
49
+ catch (HttpRequestException ex)
50
+ when (ex.StatusCode == HttpStatusCode.Unauthorized || ex.StatusCode == HttpStatusCode.Forbidden)
51
+ {
52
+ var localPath = PathHelper.JoinPath(repoRoot, discovery.Path);
53
+ var nugetContext = new NuGetContext(localPath);
54
+ analysisResult = new AnalysisResult
55
+ {
56
+ ErrorType = ErrorType.AuthenticationFailure,
57
+ ErrorDetails = "(" + string.Join("|", nugetContext.PackageSources.Select(s => s.Source)) + ")",
58
+ UpdatedVersion = string.Empty,
59
+ CanUpdate = false,
60
+ UpdatedDependencies = [],
61
+ };
62
+ }
63
+
64
+ return analysisResult;
65
+ }
66
+
40
67
  public async Task<AnalysisResult> RunAsync(string repoRoot, WorkspaceDiscoveryResult discovery, DependencyInfo dependencyInfo)
41
68
  {
42
69
  var startingDirectory = PathHelper.JoinPath(repoRoot, discovery.Path);
@@ -68,100 +95,84 @@ public partial class AnalyzeWorker
68
95
  var isUpdateNecessary = isProjectUpdateNecessary || dotnetToolsHasDependency || globalJsonHasDependency;
69
96
  using var nugetContext = new NuGetContext(startingDirectory);
70
97
  AnalysisResult analysisResult;
71
- try
98
+ if (isUpdateNecessary)
72
99
  {
73
- if (isUpdateNecessary)
100
+ _logger.Log($" Determining multi-dependency property.");
101
+ var multiDependencies = DetermineMultiDependencyDetails(
102
+ discovery,
103
+ dependencyInfo.Name,
104
+ propertyBasedDependencies);
105
+
106
+ usesMultiDependencyProperty = multiDependencies.Any(md => md.DependencyNames.Count > 1);
107
+ var dependenciesToUpdate = usesMultiDependencyProperty
108
+ ? multiDependencies
109
+ .SelectMany(md => md.DependencyNames)
110
+ .ToImmutableHashSet(StringComparer.OrdinalIgnoreCase)
111
+ : [dependencyInfo.Name];
112
+ var applicableTargetFrameworks = usesMultiDependencyProperty
113
+ ? multiDependencies
114
+ .SelectMany(md => md.TargetFrameworks)
115
+ .ToImmutableHashSet(StringComparer.OrdinalIgnoreCase)
116
+ .Select(NuGetFramework.Parse)
117
+ .ToImmutableArray()
118
+ : projectFrameworks;
119
+
120
+ _logger.Log($" Finding updated version.");
121
+ updatedVersion = await FindUpdatedVersionAsync(
122
+ startingDirectory,
123
+ dependencyInfo,
124
+ dependenciesToUpdate,
125
+ applicableTargetFrameworks,
126
+ nugetContext,
127
+ _logger,
128
+ CancellationToken.None);
129
+
130
+ _logger.Log($" Finding updated peer dependencies.");
131
+ if (updatedVersion is null)
132
+ {
133
+ updatedDependencies = [];
134
+ }
135
+ else if (isProjectUpdateNecessary)
74
136
  {
75
- _logger.Log($" Determining multi-dependency property.");
76
- var multiDependencies = DetermineMultiDependencyDetails(
137
+ updatedDependencies = await FindUpdatedDependenciesAsync(
138
+ repoRoot,
77
139
  discovery,
78
- dependencyInfo.Name,
79
- propertyBasedDependencies);
80
-
81
- usesMultiDependencyProperty = multiDependencies.Any(md => md.DependencyNames.Count > 1);
82
- var dependenciesToUpdate = usesMultiDependencyProperty
83
- ? multiDependencies
84
- .SelectMany(md => md.DependencyNames)
85
- .ToImmutableHashSet(StringComparer.OrdinalIgnoreCase)
86
- : [dependencyInfo.Name];
87
- var applicableTargetFrameworks = usesMultiDependencyProperty
88
- ? multiDependencies
89
- .SelectMany(md => md.TargetFrameworks)
90
- .ToImmutableHashSet(StringComparer.OrdinalIgnoreCase)
91
- .Select(NuGetFramework.Parse)
92
- .ToImmutableArray()
93
- : projectFrameworks;
94
-
95
- _logger.Log($" Finding updated version.");
96
- updatedVersion = await FindUpdatedVersionAsync(
97
- startingDirectory,
98
- dependencyInfo,
99
140
  dependenciesToUpdate,
100
- applicableTargetFrameworks,
141
+ updatedVersion,
101
142
  nugetContext,
102
143
  _logger,
103
144
  CancellationToken.None);
104
-
105
- _logger.Log($" Finding updated peer dependencies.");
106
- if (updatedVersion is null)
107
- {
108
- updatedDependencies = [];
109
- }
110
- else if (isProjectUpdateNecessary)
111
- {
112
- updatedDependencies = await FindUpdatedDependenciesAsync(
113
- repoRoot,
114
- discovery,
115
- dependenciesToUpdate,
116
- updatedVersion,
117
- nugetContext,
118
- _logger,
119
- CancellationToken.None);
120
- }
121
- else if (dotnetToolsHasDependency)
122
- {
123
- var infoUrl = await nugetContext.GetPackageInfoUrlAsync(dependencyInfo.Name, updatedVersion.ToNormalizedString(), CancellationToken.None);
124
- updatedDependencies = [new Dependency(dependencyInfo.Name, updatedVersion.ToNormalizedString(), DependencyType.DotNetTool, IsDirect: true, InfoUrl: infoUrl)];
125
- }
126
- else if (globalJsonHasDependency)
127
- {
128
- var infoUrl = await nugetContext.GetPackageInfoUrlAsync(dependencyInfo.Name, updatedVersion.ToNormalizedString(), CancellationToken.None);
129
- updatedDependencies = [new Dependency(dependencyInfo.Name, updatedVersion.ToNormalizedString(), DependencyType.MSBuildSdk, IsDirect: true, InfoUrl: infoUrl)];
130
- }
131
- else
132
- {
133
- throw new InvalidOperationException("Unreachable.");
134
- }
135
-
136
- //TODO: At this point we should add the peer dependencies to a queue where
137
- // we will analyze them one by one to see if they themselves are part of a
138
- // multi-dependency property. Basically looping this if-body until we have
139
- // emptied the queue and have a complete list of updated dependencies. We
140
- // should track the dependenciesToUpdate as they have already been analyzed.
141
145
  }
142
-
143
- analysisResult = new AnalysisResult
146
+ else if (dotnetToolsHasDependency)
144
147
  {
145
- UpdatedVersion = updatedVersion?.ToNormalizedString() ?? dependencyInfo.Version,
146
- CanUpdate = updatedVersion is not null,
147
- VersionComesFromMultiDependencyProperty = usesMultiDependencyProperty,
148
- UpdatedDependencies = updatedDependencies,
149
- };
150
- }
151
- catch (HttpRequestException ex)
152
- when (ex.StatusCode == HttpStatusCode.Unauthorized || ex.StatusCode == HttpStatusCode.Forbidden)
153
- {
154
- // TODO: consolidate this error handling between AnalyzeWorker, DiscoveryWorker, and UpdateWorker
155
- analysisResult = new AnalysisResult
148
+ var infoUrl = await nugetContext.GetPackageInfoUrlAsync(dependencyInfo.Name, updatedVersion.ToNormalizedString(), CancellationToken.None);
149
+ updatedDependencies = [new Dependency(dependencyInfo.Name, updatedVersion.ToNormalizedString(), DependencyType.DotNetTool, IsDirect: true, InfoUrl: infoUrl)];
150
+ }
151
+ else if (globalJsonHasDependency)
156
152
  {
157
- ErrorType = ErrorType.AuthenticationFailure,
158
- ErrorDetails = "(" + string.Join("|", nugetContext.PackageSources.Select(s => s.Source)) + ")",
159
- UpdatedVersion = string.Empty,
160
- CanUpdate = false,
161
- UpdatedDependencies = [],
162
- };
153
+ var infoUrl = await nugetContext.GetPackageInfoUrlAsync(dependencyInfo.Name, updatedVersion.ToNormalizedString(), CancellationToken.None);
154
+ updatedDependencies = [new Dependency(dependencyInfo.Name, updatedVersion.ToNormalizedString(), DependencyType.MSBuildSdk, IsDirect: true, InfoUrl: infoUrl)];
155
+ }
156
+ else
157
+ {
158
+ throw new InvalidOperationException("Unreachable.");
159
+ }
160
+
161
+ //TODO: At this point we should add the peer dependencies to a queue where
162
+ // we will analyze them one by one to see if they themselves are part of a
163
+ // multi-dependency property. Basically looping this if-body until we have
164
+ // emptied the queue and have a complete list of updated dependencies. We
165
+ // should track the dependenciesToUpdate as they have already been analyzed.
163
166
  }
164
167
 
168
+ analysisResult = new AnalysisResult
169
+ {
170
+ UpdatedVersion = updatedVersion?.ToNormalizedString() ?? dependencyInfo.Version,
171
+ CanUpdate = updatedVersion is not null,
172
+ VersionComesFromMultiDependencyProperty = usesMultiDependencyProperty,
173
+ UpdatedDependencies = updatedDependencies,
174
+ };
175
+
165
176
  _logger.Log($"Analysis complete.");
166
177
  return analysisResult;
167
178
  }
@@ -52,10 +52,10 @@ public abstract class Requirement
52
52
 
53
53
  public static Requirement Parse(string requirement)
54
54
  {
55
- var specificParts = requirement.Split(',');
55
+ var specificParts = requirement.Split(',').Where(p => !string.IsNullOrWhiteSpace(p)).ToArray();
56
56
  if (specificParts.Length == 1)
57
57
  {
58
- return IndividualRequirement.ParseIndividual(requirement);
58
+ return IndividualRequirement.ParseIndividual(specificParts[0]);
59
59
  }
60
60
 
61
61
  var specificRequirements = specificParts.Select(IndividualRequirement.ParseIndividual).ToArray();
@@ -30,7 +30,35 @@ public partial class DiscoveryWorker
30
30
  _logger = logger;
31
31
  }
32
32
 
33
- public async Task<WorkspaceDiscoveryResult> RunAsync(string repoRootPath, string workspacePath)
33
+ public async Task RunAsync(string repoRootPath, string workspacePath, string outputPath)
34
+ {
35
+ var result = await RunWithErrorHandlingAsync(repoRootPath, workspacePath);
36
+ await WriteResultsAsync(repoRootPath, outputPath, result);
37
+ }
38
+
39
+ internal async Task<WorkspaceDiscoveryResult> RunWithErrorHandlingAsync(string repoRootPath, string workspacePath)
40
+ {
41
+ WorkspaceDiscoveryResult result;
42
+ try
43
+ {
44
+ result = await RunAsync(repoRootPath, workspacePath);
45
+ }
46
+ catch (HttpRequestException ex)
47
+ when (ex.StatusCode == HttpStatusCode.Unauthorized || ex.StatusCode == HttpStatusCode.Forbidden)
48
+ {
49
+ result = new WorkspaceDiscoveryResult
50
+ {
51
+ ErrorType = ErrorType.AuthenticationFailure,
52
+ ErrorDetails = "(" + string.Join("|", NuGetContext.GetPackageSourceUrls(PathHelper.JoinPath(repoRootPath, workspacePath))) + ")",
53
+ Path = workspacePath,
54
+ Projects = [],
55
+ };
56
+ }
57
+
58
+ return result;
59
+ }
60
+
61
+ internal async Task<WorkspaceDiscoveryResult> RunAsync(string repoRootPath, string workspacePath)
34
62
  {
35
63
  MSBuildHelper.RegisterMSBuild(Environment.CurrentDirectory, repoRootPath);
36
64
 
@@ -51,69 +79,48 @@ public partial class DiscoveryWorker
51
79
  ImmutableArray<ProjectDiscoveryResult> projectResults = [];
52
80
  WorkspaceDiscoveryResult result;
53
81
 
54
- try
82
+ if (Directory.Exists(workspacePath))
55
83
  {
56
- if (Directory.Exists(workspacePath))
57
- {
58
- _logger.Log($"Discovering build files in workspace [{workspacePath}].");
84
+ _logger.Log($"Discovering build files in workspace [{workspacePath}].");
59
85
 
60
- dotNetToolsJsonDiscovery = DotNetToolsJsonDiscovery.Discover(repoRootPath, workspacePath, _logger);
61
- globalJsonDiscovery = GlobalJsonDiscovery.Discover(repoRootPath, workspacePath, _logger);
86
+ dotNetToolsJsonDiscovery = DotNetToolsJsonDiscovery.Discover(repoRootPath, workspacePath, _logger);
87
+ globalJsonDiscovery = GlobalJsonDiscovery.Discover(repoRootPath, workspacePath, _logger);
62
88
 
63
- if (globalJsonDiscovery is not null)
64
- {
65
- await TryRestoreMSBuildSdksAsync(repoRootPath, workspacePath, globalJsonDiscovery.Dependencies, _logger);
66
- }
89
+ if (globalJsonDiscovery is not null)
90
+ {
91
+ await TryRestoreMSBuildSdksAsync(repoRootPath, workspacePath, globalJsonDiscovery.Dependencies, _logger);
92
+ }
67
93
 
68
- // this next line should throw or something
69
- projectResults = await RunForDirectoryAsnyc(repoRootPath, workspacePath);
94
+ // this next line should throw or something
95
+ projectResults = await RunForDirectoryAsnyc(repoRootPath, workspacePath);
70
96
 
71
- directoryPackagesPropsDiscovery = DirectoryPackagesPropsDiscovery.Discover(repoRootPath, workspacePath, projectResults, _logger);
97
+ directoryPackagesPropsDiscovery = DirectoryPackagesPropsDiscovery.Discover(repoRootPath, workspacePath, projectResults, _logger);
72
98
 
73
- if (directoryPackagesPropsDiscovery is not null)
74
- {
75
- projectResults = projectResults.Remove(projectResults.First(p => p.FilePath.Equals(directoryPackagesPropsDiscovery.FilePath, StringComparison.OrdinalIgnoreCase)));
76
- }
77
- }
78
- else
99
+ if (directoryPackagesPropsDiscovery is not null)
79
100
  {
80
- _logger.Log($"Workspace path [{workspacePath}] does not exist.");
101
+ projectResults = projectResults.Remove(projectResults.First(p => p.FilePath.Equals(directoryPackagesPropsDiscovery.FilePath, StringComparison.OrdinalIgnoreCase)));
81
102
  }
82
-
83
- result = new WorkspaceDiscoveryResult
84
- {
85
- Path = initialWorkspacePath,
86
- DotNetToolsJson = dotNetToolsJsonDiscovery,
87
- GlobalJson = globalJsonDiscovery,
88
- DirectoryPackagesProps = directoryPackagesPropsDiscovery,
89
- Projects = projectResults.OrderBy(p => p.FilePath).ToImmutableArray(),
90
- };
91
103
  }
92
- catch (HttpRequestException ex)
93
- when (ex.StatusCode == HttpStatusCode.Unauthorized || ex.StatusCode == HttpStatusCode.Forbidden)
104
+ else
94
105
  {
95
- // TODO: consolidate this error handling between AnalyzeWorker, DiscoveryWorker, and UpdateWorker
96
- result = new WorkspaceDiscoveryResult
97
- {
98
- ErrorType = ErrorType.AuthenticationFailure,
99
- ErrorDetails = "(" + string.Join("|", NuGetContext.GetPackageSourceUrls(workspacePath)) + ")",
100
- Path = initialWorkspacePath,
101
- Projects = [],
102
- };
106
+ _logger.Log($"Workspace path [{workspacePath}] does not exist.");
103
107
  }
104
108
 
109
+ result = new WorkspaceDiscoveryResult
110
+ {
111
+ Path = initialWorkspacePath,
112
+ DotNetToolsJson = dotNetToolsJsonDiscovery,
113
+ GlobalJson = globalJsonDiscovery,
114
+ DirectoryPackagesProps = directoryPackagesPropsDiscovery,
115
+ Projects = projectResults.OrderBy(p => p.FilePath).ToImmutableArray(),
116
+ };
117
+
105
118
  _logger.Log("Discovery complete.");
106
119
  _processedProjectPaths.Clear();
107
120
 
108
121
  return result;
109
122
  }
110
123
 
111
- public async Task RunAsync(string repoRootPath, string workspacePath, string outputPath)
112
- {
113
- var result = await RunAsync(repoRootPath, workspacePath);
114
- await WriteResultsAsync(repoRootPath, outputPath, result);
115
- }
116
-
117
124
  /// <summary>
118
125
  /// Restores MSBuild SDKs from the given dependencies.
119
126
  /// </summary>
@@ -6,4 +6,5 @@ public enum ErrorType
6
6
  None,
7
7
  AuthenticationFailure,
8
8
  MissingFile,
9
+ UpdateNotPossible,
9
10
  }
@@ -4,5 +4,5 @@ public record NativeResult
4
4
  {
5
5
  // TODO: nullable not required, `ErrorType.None` is the default anyway
6
6
  public ErrorType? ErrorType { get; init; }
7
- public string? ErrorDetails { get; init; }
7
+ public object? ErrorDetails { get; init; }
8
8
  }
@@ -0,0 +1,6 @@
1
+ namespace NuGetUpdater.Core.Run.ApiModel;
2
+
3
+ public record DependencyFileNotFound : JobErrorBase
4
+ {
5
+ public override string Type => "dependency_file_not_found";
6
+ }
@@ -0,0 +1,11 @@
1
+ using System.Text.Json.Serialization;
2
+
3
+ namespace NuGetUpdater.Core.Run.ApiModel;
4
+
5
+ public abstract record JobErrorBase
6
+ {
7
+ [JsonPropertyName("error-type")]
8
+ public abstract string Type { get; }
9
+ [JsonPropertyName("error-details")]
10
+ public required object Details { get; init; }
11
+ }
@@ -0,0 +1,6 @@
1
+ namespace NuGetUpdater.Core.Run.ApiModel;
2
+
3
+ public record PrivateSourceAuthenticationFailure : JobErrorBase
4
+ {
5
+ public override string Type => "private_source_authentication_failure";
6
+ }
@@ -0,0 +1,6 @@
1
+ namespace NuGetUpdater.Core.Run.ApiModel;
2
+
3
+ public record UnknownError : JobErrorBase
4
+ {
5
+ public override string Type => "unknown_error";
6
+ }
@@ -0,0 +1,6 @@
1
+ namespace NuGetUpdater.Core.Run.ApiModel;
2
+
3
+ public record UpdateNotPossible : JobErrorBase
4
+ {
5
+ public override string Type => "update_not_possible";
6
+ }
@@ -25,6 +25,11 @@ public class HttpApiHandler : IApiHandler
25
25
  _jobId = jobId;
26
26
  }
27
27
 
28
+ public async Task RecordUpdateJobError(JobErrorBase error)
29
+ {
30
+ await PostAsJson("record_update_job_error", error);
31
+ }
32
+
28
33
  public async Task UpdateDependencyList(UpdatedDependencyList updatedDependencyList)
29
34
  {
30
35
  await PostAsJson("update_dependency_list", updatedDependencyList);
@@ -4,6 +4,7 @@ namespace NuGetUpdater.Core.Run;
4
4
 
5
5
  public interface IApiHandler
6
6
  {
7
+ Task RecordUpdateJobError(JobErrorBase error);
7
8
  Task UpdateDependencyList(UpdatedDependencyList updatedDependencyList);
8
9
  Task IncrementMetric(IncrementMetric incrementMetric);
9
10
  Task CreatePullRequest(CreatePullRequest createPullRequest);