dependabot-nuget 0.265.0 → 0.267.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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/UpdateCommand.cs +6 -6
  3. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Analyze.cs +173 -0
  4. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/AnalysisResult.cs +1 -1
  5. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/AnalyzeWorker.cs +92 -79
  6. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/CompatabilityChecker.cs +21 -8
  7. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/NuGetContext.cs +36 -9
  8. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/Requirement.cs +88 -45
  9. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/VersionFinder.cs +33 -16
  10. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DiscoveryWorker.cs +44 -25
  11. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/WorkspaceDiscoveryResult.cs +1 -1
  12. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ErrorType.cs +9 -0
  13. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/ProjectBuildFile.cs +2 -2
  14. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/MissingFileException.cs +11 -0
  15. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/NativeResult.cs +8 -0
  16. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/BindingRedirectManager.cs +45 -42
  17. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackagesConfigUpdater.cs +19 -1
  18. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/SdkPackageUpdater.cs +2 -1
  19. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdateOperationResult.cs +5 -0
  20. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdaterWorker.cs +70 -22
  21. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +29 -1
  22. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTestBase.cs +6 -2
  23. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTests.cs +450 -0
  24. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/CompatibilityCheckerTests.cs +23 -0
  25. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/RequirementTests.cs +1 -0
  26. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTestBase.cs +2 -0
  27. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs +148 -0
  28. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/ExpectedDiscoveryResults.cs +1 -1
  29. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/MockNuGetPackage.cs +17 -22
  30. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TestHttpServer.cs +81 -0
  31. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs +27 -7
  32. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Mixed.cs +32 -0
  33. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs +447 -2
  34. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Sdk.cs +88 -0
  35. data/lib/dependabot/nuget/analysis/dependency_analysis.rb +3 -0
  36. data/lib/dependabot/nuget/file_fetcher.rb +30 -11
  37. data/lib/dependabot/nuget/file_updater.rb +2 -0
  38. data/lib/dependabot/nuget/metadata_finder.rb +160 -2
  39. data/lib/dependabot/nuget/native_discovery/native_workspace_discovery.rb +3 -0
  40. data/lib/dependabot/nuget/native_helpers.rb +36 -3
  41. data/lib/dependabot/nuget/native_update_checker/native_update_checker.rb +1 -0
  42. data/lib/dependabot/nuget/nuget_config_credential_helpers.rb +3 -0
  43. metadata +12 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0c8985bae397230599aee116240d6569573ea126c70bc39a37a568935aaf3649
4
- data.tar.gz: b137e9983b1ce14c86235b898a70039c53aadf9eb7a4389b94631bc787ba7914
3
+ metadata.gz: 19fd9d2635d3d1f5737870ebe8bcd155fb5e90557c7eec2b6832233bb0573b29
4
+ data.tar.gz: d1bd4ff99ae3fd8319a796cf04ba3a859c084cd465013cd5a1c8b106969a8183
5
5
  SHA512:
6
- metadata.gz: bbcf0d5509e6bad8ea0af998c7ee6ea6047c13153c4111b2f9e46d568b559bcbe93eb21e8a200ee9deabb4c41bad10e789d236bb6fb30a34ed8c072a47537ced
7
- data.tar.gz: 21ffbb1f7c7ff6a40d8db845b6e175c0f9478d5b99cadd969b127bbed07171b2b120bb3c6a107a1a41d59245906a7276f4006f0cdef4a2f01105d218596bfc6e
6
+ metadata.gz: 4b1c5c0ed9ca379e3c209c21dbc047e7364a9c3f7eda956ebd11a6f0f44b5a3a3e5a7fe9493ccafe82ac98bad132ab2323a56817c2f234c135814282cd229c30
7
+ data.tar.gz: c0f297752cb28d6c32df1261ab10199a5f39e17af23f3c3e46ed76aafd59785e79cd43c81e1a164b8fe92b9f7763f50e3d2c4a8d34c9bb59a4976d0e6eb44be4
@@ -1,6 +1,4 @@
1
- using System;
2
1
  using System.CommandLine;
3
- using System.IO;
4
2
 
5
3
  using NuGetUpdater.Core;
6
4
 
@@ -15,6 +13,7 @@ internal static class UpdateCommand
15
13
  internal static readonly Option<string> PreviousVersionOption = new("--previous-version") { IsRequired = true };
16
14
  internal static readonly Option<bool> IsTransitiveOption = new("--transitive", getDefaultValue: () => false);
17
15
  internal static readonly Option<bool> VerboseOption = new("--verbose", getDefaultValue: () => false);
16
+ internal static readonly Option<string?> ResultOutputPathOption = new("--result-output-path", getDefaultValue: () => null);
18
17
 
19
18
  internal static Command GetCommand(Action<int> setExitCode)
20
19
  {
@@ -26,17 +25,18 @@ internal static class UpdateCommand
26
25
  NewVersionOption,
27
26
  PreviousVersionOption,
28
27
  IsTransitiveOption,
29
- VerboseOption
28
+ VerboseOption,
29
+ ResultOutputPathOption
30
30
  };
31
31
 
32
32
  command.TreatUnmatchedTokensAsErrors = true;
33
33
 
34
- command.SetHandler(async (repoRoot, solutionOrProjectFile, dependencyName, newVersion, previousVersion, isTransitive, verbose) =>
34
+ command.SetHandler(async (repoRoot, solutionOrProjectFile, dependencyName, newVersion, previousVersion, isTransitive, verbose, resultOutputPath) =>
35
35
  {
36
36
  var worker = new UpdaterWorker(new Logger(verbose));
37
- await worker.RunAsync(repoRoot.FullName, solutionOrProjectFile.FullName, dependencyName, previousVersion, newVersion, isTransitive);
37
+ await worker.RunAsync(repoRoot.FullName, solutionOrProjectFile.FullName, dependencyName, previousVersion, newVersion, isTransitive, resultOutputPath);
38
38
  setExitCode(0);
39
- }, RepoRootOption, SolutionOrProjectFileOption, DependencyNameOption, NewVersionOption, PreviousVersionOption, IsTransitiveOption, VerboseOption);
39
+ }, RepoRootOption, SolutionOrProjectFileOption, DependencyNameOption, NewVersionOption, PreviousVersionOption, IsTransitiveOption, VerboseOption, ResultOutputPathOption);
40
40
 
41
41
  return command;
42
42
  }
@@ -134,6 +134,179 @@ public partial class EntryPointTests
134
134
  );
135
135
  }
136
136
 
137
+ [Fact]
138
+ public async Task DotNetToolsJsonCanBeAnalyzed()
139
+ {
140
+ var repoMetadata = XElement.Parse("""<repository type="git" url="https://nuget.example.com/some-global-tool" />""");
141
+ await RunAsync(path =>
142
+ [
143
+ "analyze",
144
+ "--repo-root",
145
+ path,
146
+ "--discovery-file-path",
147
+ Path.Join(path, "discovery.json"),
148
+ "--dependency-file-path",
149
+ Path.Join(path, "some-global-tool.json"),
150
+ "--analysis-folder-path",
151
+ Path.Join(path, AnalyzeWorker.AnalysisDirectoryName),
152
+ "--verbose",
153
+ ],
154
+ packages:
155
+ [
156
+ MockNuGetPackage.CreateDotNetToolPackage("some-global-tool", "1.0.0", "net8.0", additionalMetadata: [repoMetadata]),
157
+ MockNuGetPackage.CreateDotNetToolPackage("some-global-tool", "1.1.0", "net8.0", additionalMetadata: [repoMetadata]),
158
+ ],
159
+ dependencyName: "some-global-tool",
160
+ initialFiles:
161
+ [
162
+ (".config/dotnet-tools.json", """
163
+ {
164
+ "version": 1,
165
+ "isRoot": true,
166
+ "tools": {
167
+ "some-global-tool": {
168
+ "version": "1.0.0",
169
+ "commands": [
170
+ "some-global-tool"
171
+ ]
172
+ }
173
+ }
174
+ }
175
+ """),
176
+ ("discovery.json", """
177
+ {
178
+ "Path": "",
179
+ "IsSuccess": true,
180
+ "Projects": [],
181
+ "DotNetToolsJson": {
182
+ "FilePath": ".config/dotnet-tools.json",
183
+ "IsSuccess": true,
184
+ "Dependencies": [
185
+ {
186
+ "Name": "some-global-tool",
187
+ "Version": "1.0.0",
188
+ "Type": "DotNetTool",
189
+ "EvaluationResult": null,
190
+ "TargetFrameworks": null,
191
+ "IsDevDependency": false,
192
+ "IsDirect": false,
193
+ "IsTransitive": false,
194
+ "IsOverride": false,
195
+ "IsUpdate": false,
196
+ "InfoUrl": null
197
+ }
198
+ ]
199
+ }
200
+ }
201
+ """),
202
+ ("some-global-tool.json", """
203
+ {
204
+ "Name": "some-global-tool",
205
+ "Version": "1.0.0",
206
+ "IsVulnerable": false,
207
+ "IgnoredVersions": [],
208
+ "Vulnerabilities": []
209
+ }
210
+ """),
211
+ ],
212
+ expectedResult: new()
213
+ {
214
+ UpdatedVersion = "1.1.0",
215
+ CanUpdate = true,
216
+ VersionComesFromMultiDependencyProperty = false,
217
+ UpdatedDependencies =
218
+ [
219
+ new Dependency("some-global-tool", "1.1.0", DependencyType.DotNetTool, TargetFrameworks: null, IsDirect: true, InfoUrl: "https://nuget.example.com/some-global-tool")
220
+ ],
221
+ }
222
+ );
223
+ }
224
+
225
+ [Fact]
226
+ public async Task GlobalJsonCanBeAnalyzed()
227
+ {
228
+ var repoMetadata = XElement.Parse("""<repository type="git" url="https://nuget.example.com/some.msbuild.sdk" />""");
229
+ await RunAsync(path =>
230
+ [
231
+ "analyze",
232
+ "--repo-root",
233
+ path,
234
+ "--discovery-file-path",
235
+ Path.Join(path, "discovery.json"),
236
+ "--dependency-file-path",
237
+ Path.Join(path, "Some.MSBuild.Sdk.json"),
238
+ "--analysis-folder-path",
239
+ Path.Join(path, AnalyzeWorker.AnalysisDirectoryName),
240
+ "--verbose",
241
+ ],
242
+ packages:
243
+ [
244
+ MockNuGetPackage.CreateMSBuildSdkPackage("Some.MSBuild.Sdk", "1.0.0", "net8.0", additionalMetadata: [repoMetadata]),
245
+ MockNuGetPackage.CreateMSBuildSdkPackage("Some.MSBuild.Sdk", "1.1.0", "net8.0", additionalMetadata: [repoMetadata]),
246
+ ],
247
+ dependencyName: "Some.MSBuild.Sdk",
248
+ initialFiles:
249
+ [
250
+ ("global.json", """
251
+ {
252
+ "sdk": {
253
+ "version": "8.0.300",
254
+ "rollForward": "latestPatch"
255
+ },
256
+ "msbuild-sdks": {
257
+ "Some.MSBuild.Sdk": "1.0.0"
258
+ }
259
+ }
260
+ """),
261
+ ("discovery.json", """
262
+ {
263
+ "Path": "",
264
+ "IsSuccess": true,
265
+ "Projects": [],
266
+ "GlobalJson": {
267
+ "FilePath": "global.json",
268
+ "IsSuccess": true,
269
+ "Dependencies": [
270
+ {
271
+ "Name": "Some.MSBuild.Sdk",
272
+ "Version": "1.0.0",
273
+ "Type": "MSBuildSdk",
274
+ "EvaluationResult": null,
275
+ "TargetFrameworks": null,
276
+ "IsDevDependency": false,
277
+ "IsDirect": false,
278
+ "IsTransitive": false,
279
+ "IsOverride": false,
280
+ "IsUpdate": false,
281
+ "InfoUrl": null
282
+ }
283
+ ]
284
+ }
285
+ }
286
+ """),
287
+ ("Some.MSBuild.Sdk.json", """
288
+ {
289
+ "Name": "Some.MSBuild.Sdk",
290
+ "Version": "1.0.0",
291
+ "IsVulnerable": false,
292
+ "IgnoredVersions": [],
293
+ "Vulnerabilities": []
294
+ }
295
+ """),
296
+ ],
297
+ expectedResult: new()
298
+ {
299
+ UpdatedVersion = "1.1.0",
300
+ CanUpdate = true,
301
+ VersionComesFromMultiDependencyProperty = false,
302
+ UpdatedDependencies =
303
+ [
304
+ new Dependency("Some.MSBuild.Sdk", "1.1.0", DependencyType.MSBuildSdk, TargetFrameworks: null, IsDirect: true, InfoUrl: "https://nuget.example.com/some.msbuild.sdk")
305
+ ],
306
+ }
307
+ );
308
+ }
309
+
137
310
  private static async Task RunAsync(Func<string, string[]> getArgs, string dependencyName, TestFile[] initialFiles, ExpectedAnalysisResult expectedResult, MockNuGetPackage[]? packages = null)
138
311
  {
139
312
  var actualResult = await RunAnalyzerAsync(dependencyName, initialFiles, async path =>
@@ -2,7 +2,7 @@ using System.Collections.Immutable;
2
2
 
3
3
  namespace NuGetUpdater.Core.Analyze;
4
4
 
5
- public record AnalysisResult
5
+ public record AnalysisResult : NativeResult
6
6
  {
7
7
  public required string UpdatedVersion { get; init; }
8
8
  public bool CanUpdate { get; init; }
@@ -1,8 +1,8 @@
1
1
  using System.Collections.Immutable;
2
+ using System.Net;
2
3
  using System.Text.Json;
3
4
  using System.Text.Json.Serialization;
4
5
 
5
- using NuGet.Configuration;
6
6
  using NuGet.Frameworks;
7
7
  using NuGet.Versioning;
8
8
 
@@ -51,76 +51,110 @@ public partial class AnalyzeWorker
51
51
  => p.Dependencies.Where(d => !d.IsTransitive &&
52
52
  d.EvaluationResult?.RootPropertyName is not null)
53
53
  ).ToImmutableArray();
54
+ var dotnetToolsHasDependency = discovery.DotNetToolsJson?.Dependencies.Any(d => d.Name.Equals(dependencyInfo.Name, StringComparison.OrdinalIgnoreCase)) == true;
55
+ var globalJsonHasDependency = discovery.GlobalJson?.Dependencies.Any(d => d.Name.Equals(dependencyInfo.Name, StringComparison.OrdinalIgnoreCase)) == true;
54
56
 
55
57
  bool usesMultiDependencyProperty = false;
56
58
  NuGetVersion? updatedVersion = null;
57
59
  ImmutableArray<Dependency> updatedDependencies = [];
58
60
 
59
- bool isUpdateNecessary = IsUpdateNecessary(dependencyInfo, projectsWithDependency);
60
- if (isUpdateNecessary)
61
+ bool isProjectUpdateNecessary = IsUpdateNecessary(dependencyInfo, projectsWithDependency);
62
+ var isUpdateNecessary = isProjectUpdateNecessary || dotnetToolsHasDependency || globalJsonHasDependency;
63
+ using var nugetContext = new NuGetContext(startingDirectory);
64
+ AnalysisResult result;
65
+ try
61
66
  {
62
- var nugetContext = new NuGetContext(startingDirectory);
63
- if (!Directory.Exists(nugetContext.TempPackageDirectory))
67
+ if (isUpdateNecessary)
64
68
  {
65
- Directory.CreateDirectory(nugetContext.TempPackageDirectory);
66
- }
67
-
68
- _logger.Log($" Determining multi-dependency property.");
69
- var multiDependencies = DetermineMultiDependencyDetails(
70
- discovery,
71
- dependencyInfo.Name,
72
- propertyBasedDependencies);
73
-
74
- usesMultiDependencyProperty = multiDependencies.Any(md => md.DependencyNames.Count > 1);
75
- var dependenciesToUpdate = usesMultiDependencyProperty
76
- ? multiDependencies
77
- .SelectMany(md => md.DependencyNames)
78
- .ToImmutableHashSet(StringComparer.OrdinalIgnoreCase)
79
- : [dependencyInfo.Name];
80
- var applicableTargetFrameworks = usesMultiDependencyProperty
81
- ? multiDependencies
82
- .SelectMany(md => md.TargetFrameworks)
83
- .ToImmutableHashSet(StringComparer.OrdinalIgnoreCase)
84
- .Select(NuGetFramework.Parse)
85
- .ToImmutableArray()
86
- : projectFrameworks;
87
-
88
- _logger.Log($" Finding updated version.");
89
- updatedVersion = await FindUpdatedVersionAsync(
90
- startingDirectory,
91
- dependencyInfo,
92
- dependenciesToUpdate,
93
- applicableTargetFrameworks,
94
- nugetContext,
95
- _logger,
96
- CancellationToken.None);
97
-
98
- _logger.Log($" Finding updated peer dependencies.");
99
- updatedDependencies = updatedVersion is not null
100
- ? await FindUpdatedDependenciesAsync(
101
- repoRoot,
69
+ _logger.Log($" Determining multi-dependency property.");
70
+ var multiDependencies = DetermineMultiDependencyDetails(
102
71
  discovery,
72
+ dependencyInfo.Name,
73
+ propertyBasedDependencies);
74
+
75
+ usesMultiDependencyProperty = multiDependencies.Any(md => md.DependencyNames.Count > 1);
76
+ var dependenciesToUpdate = usesMultiDependencyProperty
77
+ ? multiDependencies
78
+ .SelectMany(md => md.DependencyNames)
79
+ .ToImmutableHashSet(StringComparer.OrdinalIgnoreCase)
80
+ : [dependencyInfo.Name];
81
+ var applicableTargetFrameworks = usesMultiDependencyProperty
82
+ ? multiDependencies
83
+ .SelectMany(md => md.TargetFrameworks)
84
+ .ToImmutableHashSet(StringComparer.OrdinalIgnoreCase)
85
+ .Select(NuGetFramework.Parse)
86
+ .ToImmutableArray()
87
+ : projectFrameworks;
88
+
89
+ _logger.Log($" Finding updated version.");
90
+ updatedVersion = await FindUpdatedVersionAsync(
91
+ startingDirectory,
92
+ dependencyInfo,
103
93
  dependenciesToUpdate,
104
- updatedVersion,
94
+ applicableTargetFrameworks,
105
95
  nugetContext,
106
96
  _logger,
107
- CancellationToken.None)
108
- : [];
109
-
110
- //TODO: At this point we should add the peer dependencies to a queue where
111
- // we will analyze them one by one to see if they themselves are part of a
112
- // multi-dependency property. Basically looping this if-body until we have
113
- // emptied the queue and have a complete list of updated dependencies. We
114
- // should track the dependenciesToUpdate as they have already been analyzed.
115
- }
97
+ CancellationToken.None);
98
+
99
+ _logger.Log($" Finding updated peer dependencies.");
100
+ if (updatedVersion is null)
101
+ {
102
+ updatedDependencies = [];
103
+ }
104
+ else if (isProjectUpdateNecessary)
105
+ {
106
+ updatedDependencies = await FindUpdatedDependenciesAsync(
107
+ repoRoot,
108
+ discovery,
109
+ dependenciesToUpdate,
110
+ updatedVersion,
111
+ nugetContext,
112
+ _logger,
113
+ CancellationToken.None);
114
+ }
115
+ else if (dotnetToolsHasDependency)
116
+ {
117
+ var infoUrl = await nugetContext.GetPackageInfoUrlAsync(dependencyInfo.Name, updatedVersion.ToNormalizedString(), CancellationToken.None);
118
+ updatedDependencies = [new Dependency(dependencyInfo.Name, updatedVersion.ToNormalizedString(), DependencyType.DotNetTool, IsDirect: true, InfoUrl: infoUrl)];
119
+ }
120
+ else if (globalJsonHasDependency)
121
+ {
122
+ var infoUrl = await nugetContext.GetPackageInfoUrlAsync(dependencyInfo.Name, updatedVersion.ToNormalizedString(), CancellationToken.None);
123
+ updatedDependencies = [new Dependency(dependencyInfo.Name, updatedVersion.ToNormalizedString(), DependencyType.MSBuildSdk, IsDirect: true, InfoUrl: infoUrl)];
124
+ }
125
+ else
126
+ {
127
+ throw new InvalidOperationException("Unreachable.");
128
+ }
129
+
130
+ //TODO: At this point we should add the peer dependencies to a queue where
131
+ // we will analyze them one by one to see if they themselves are part of a
132
+ // multi-dependency property. Basically looping this if-body until we have
133
+ // emptied the queue and have a complete list of updated dependencies. We
134
+ // should track the dependenciesToUpdate as they have already been analyzed.
135
+ }
116
136
 
117
- var result = new AnalysisResult
137
+ result = new AnalysisResult
138
+ {
139
+ UpdatedVersion = updatedVersion?.ToNormalizedString() ?? dependencyInfo.Version,
140
+ CanUpdate = updatedVersion is not null,
141
+ VersionComesFromMultiDependencyProperty = usesMultiDependencyProperty,
142
+ UpdatedDependencies = updatedDependencies,
143
+ };
144
+ }
145
+ catch (HttpRequestException ex)
146
+ when (ex.StatusCode == HttpStatusCode.Unauthorized || ex.StatusCode == HttpStatusCode.Forbidden)
118
147
  {
119
- UpdatedVersion = updatedVersion?.ToNormalizedString() ?? dependencyInfo.Version,
120
- CanUpdate = updatedVersion is not null,
121
- VersionComesFromMultiDependencyProperty = usesMultiDependencyProperty,
122
- UpdatedDependencies = updatedDependencies,
123
- };
148
+ // TODO: consolidate this error handling between AnalyzeWorker, DiscoveryWorker, and UpdateWorker
149
+ result = new AnalysisResult
150
+ {
151
+ ErrorType = ErrorType.AuthenticationFailure,
152
+ ErrorDetails = "(" + string.Join("|", nugetContext.PackageSources.Select(s => s.Source)) + ")",
153
+ UpdatedVersion = string.Empty,
154
+ CanUpdate = false,
155
+ UpdatedDependencies = [],
156
+ };
157
+ }
124
158
 
125
159
  await WriteResultsAsync(analysisDirectory, dependencyInfo.Name, result, _logger);
126
160
 
@@ -314,27 +348,6 @@ public partial class AnalyzeWorker
314
348
  return true;
315
349
  }
316
350
 
317
- internal static async Task<ImmutableDictionary<NuGetFramework, ImmutableArray<Dependency>>> GetDependenciesAsync(
318
- string workspacePath,
319
- string projectPath,
320
- IEnumerable<NuGetFramework> frameworks,
321
- Dependency package,
322
- Logger logger)
323
- {
324
- var result = ImmutableDictionary.CreateBuilder<NuGetFramework, ImmutableArray<Dependency>>();
325
- foreach (var framework in frameworks)
326
- {
327
- var dependencies = await MSBuildHelper.GetAllPackageDependenciesAsync(
328
- workspacePath,
329
- projectPath,
330
- framework.ToString(),
331
- [package],
332
- logger);
333
- result.Add(framework, [.. dependencies]);
334
- }
335
- return result.ToImmutable();
336
- }
337
-
338
351
  internal static async Task<ImmutableArray<Dependency>> FindUpdatedDependenciesAsync(
339
352
  string repoRoot,
340
353
  WorkspaceDiscoveryResult discovery,
@@ -54,6 +54,11 @@ internal static class CompatibilityChecker
54
54
 
55
55
  var compatibilityService = new FrameworkCompatibilityService();
56
56
  var compatibleFrameworks = compatibilityService.GetCompatibleFrameworks(packageFrameworks);
57
+ var packageSupportsAny = compatibleFrameworks.Any(f => f.IsAny);
58
+ if (packageSupportsAny)
59
+ {
60
+ return true;
61
+ }
57
62
 
58
63
  var incompatibleFrameworks = projectFrameworks.Where(f => !compatibleFrameworks.Contains(f)).ToArray();
59
64
  if (incompatibleFrameworks.Length > 0)
@@ -141,15 +146,23 @@ internal static class CompatibilityChecker
141
146
  throw new NotSupportedException($"Failed to get FindPackageByIdResource for {source.SourceUri}");
142
147
  }
143
148
 
144
- var exists = await feed.DoesPackageExistAsync(
145
- package.Id,
146
- package.Version,
147
- context.SourceCacheContext,
148
- NullLogger.Instance,
149
- cancellationToken);
150
-
151
- if (!exists)
149
+ try
150
+ {
151
+ // a non-compliant v2 API returning 404 can cause this to throw
152
+ var exists = await feed.DoesPackageExistAsync(
153
+ package.Id,
154
+ package.Version,
155
+ context.SourceCacheContext,
156
+ NullLogger.Instance,
157
+ cancellationToken);
158
+ if (!exists)
159
+ {
160
+ continue;
161
+ }
162
+ }
163
+ catch (FatalProtocolException)
152
164
  {
165
+ // if anything goes wrong here, the package source obviously doesn't contain the requested package
153
166
  continue;
154
167
  }
155
168
 
@@ -37,16 +37,34 @@ internal record NuGetContext : IDisposable
37
37
  .Where(p => p.IsEnabled)
38
38
  .ToImmutableArray();
39
39
  Logger = logger ?? NullLogger.Instance;
40
- TempPackageDirectory = Path.Combine(Path.GetTempPath(), ".dependabot", "packages");
40
+ TempPackageDirectory = Path.Combine(Path.GetTempPath(), $"dependabot-packages_{Guid.NewGuid():d}");
41
+ Directory.CreateDirectory(TempPackageDirectory);
41
42
  }
42
43
 
43
44
  public void Dispose()
44
45
  {
45
46
  SourceCacheContext.Dispose();
47
+ if (Directory.Exists(TempPackageDirectory))
48
+ {
49
+ try
50
+ {
51
+ Directory.Delete(TempPackageDirectory, recursive: true);
52
+ }
53
+ catch
54
+ {
55
+ }
56
+ }
46
57
  }
47
58
 
48
59
  private readonly Dictionary<PackageIdentity, string?> _packageInfoUrlCache = new();
49
60
 
61
+ public static string[] GetPackageSourceUrls(string currentDirectory)
62
+ {
63
+ using var context = new NuGetContext(currentDirectory);
64
+ var sourceUrls = context.PackageSources.Select(s => s.Source).ToArray();
65
+ return sourceUrls;
66
+ }
67
+
50
68
  public async Task<string?> GetPackageInfoUrlAsync(string packageId, string packageVersion, CancellationToken cancellationToken)
51
69
  {
52
70
  var packageIdentity = new PackageIdentity(packageId, NuGetVersion.Parse(packageVersion));
@@ -86,15 +104,24 @@ internal record NuGetContext : IDisposable
86
104
  continue;
87
105
  }
88
106
 
89
- var existsInFeed = await feed.Exists(
90
- packageIdentity,
91
- includeUnlisted: false,
92
- SourceCacheContext,
93
- NullLogger.Instance,
94
- cancellationToken);
95
- if (!existsInFeed)
107
+ try
108
+ {
109
+ // a non-compliant v2 API returning 404 can cause this to throw
110
+ var existsInFeed = await feed.Exists(
111
+ packageIdentity,
112
+ includeUnlisted: false,
113
+ SourceCacheContext,
114
+ NullLogger.Instance,
115
+ cancellationToken);
116
+ if (!existsInFeed)
117
+ {
118
+ message.AppendLine($" package {packageIdentity} does not exist in {source.Name}");
119
+ continue;
120
+ }
121
+ }
122
+ catch (FatalProtocolException)
96
123
  {
97
- message.AppendLine($" package {packageIdentity} does not exist in {source.Name}");
124
+ // if anything goes wrong here, the package source obviously doesn't contain the requested package
98
125
  continue;
99
126
  }
100
127