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.
- checksums.yaml +4 -4
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/UpdateCommand.cs +6 -6
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Analyze.cs +173 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/AnalysisResult.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/AnalyzeWorker.cs +92 -79
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/CompatabilityChecker.cs +21 -8
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/NuGetContext.cs +36 -9
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/Requirement.cs +88 -45
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/VersionFinder.cs +33 -16
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DiscoveryWorker.cs +44 -25
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/WorkspaceDiscoveryResult.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ErrorType.cs +9 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/ProjectBuildFile.cs +2 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/MissingFileException.cs +11 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/NativeResult.cs +8 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/BindingRedirectManager.cs +45 -42
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackagesConfigUpdater.cs +19 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/SdkPackageUpdater.cs +2 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdateOperationResult.cs +5 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdaterWorker.cs +70 -22
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +29 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTestBase.cs +6 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTests.cs +450 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/CompatibilityCheckerTests.cs +23 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/RequirementTests.cs +1 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTestBase.cs +2 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs +148 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/ExpectedDiscoveryResults.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/MockNuGetPackage.cs +17 -22
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TestHttpServer.cs +81 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs +27 -7
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Mixed.cs +32 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs +447 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Sdk.cs +88 -0
- data/lib/dependabot/nuget/analysis/dependency_analysis.rb +3 -0
- data/lib/dependabot/nuget/file_fetcher.rb +30 -11
- data/lib/dependabot/nuget/file_updater.rb +2 -0
- data/lib/dependabot/nuget/metadata_finder.rb +160 -2
- data/lib/dependabot/nuget/native_discovery/native_workspace_discovery.rb +3 -0
- data/lib/dependabot/nuget/native_helpers.rb +36 -3
- data/lib/dependabot/nuget/native_update_checker/native_update_checker.rb +1 -0
- data/lib/dependabot/nuget/nuget_config_credential_helpers.rb +3 -0
- metadata +12 -7
@@ -1,3 +1,10 @@
|
|
1
|
+
using System.Net;
|
2
|
+
using System.Text.Json;
|
3
|
+
using System.Text.Json.Serialization;
|
4
|
+
|
5
|
+
using NuGetUpdater.Core.Analyze;
|
6
|
+
using NuGetUpdater.Core.Updater;
|
7
|
+
|
1
8
|
namespace NuGetUpdater.Core;
|
2
9
|
|
3
10
|
public class UpdaterWorker
|
@@ -5,48 +12,89 @@ public class UpdaterWorker
|
|
5
12
|
private readonly Logger _logger;
|
6
13
|
private readonly HashSet<string> _processedProjectPaths = new(StringComparer.OrdinalIgnoreCase);
|
7
14
|
|
15
|
+
internal static readonly JsonSerializerOptions SerializerOptions = new()
|
16
|
+
{
|
17
|
+
WriteIndented = true,
|
18
|
+
Converters = { new JsonStringEnumConverter() },
|
19
|
+
};
|
20
|
+
|
8
21
|
public UpdaterWorker(Logger logger)
|
9
22
|
{
|
10
23
|
_logger = logger;
|
11
24
|
}
|
12
25
|
|
13
|
-
public async Task RunAsync(string repoRootPath, string workspacePath, string dependencyName, string previousDependencyVersion, string newDependencyVersion, bool isTransitive)
|
26
|
+
public async Task RunAsync(string repoRootPath, string workspacePath, string dependencyName, string previousDependencyVersion, string newDependencyVersion, bool isTransitive, string? resultOutputPath = null)
|
14
27
|
{
|
15
28
|
MSBuildHelper.RegisterMSBuild(Environment.CurrentDirectory, repoRootPath);
|
29
|
+
UpdateOperationResult result;
|
16
30
|
|
17
31
|
if (!Path.IsPathRooted(workspacePath) || !File.Exists(workspacePath))
|
18
32
|
{
|
19
33
|
workspacePath = Path.GetFullPath(Path.Join(repoRootPath, workspacePath));
|
20
34
|
}
|
21
35
|
|
22
|
-
|
36
|
+
try
|
37
|
+
{
|
38
|
+
if (!isTransitive)
|
39
|
+
{
|
40
|
+
await DotNetToolsJsonUpdater.UpdateDependencyAsync(repoRootPath, workspacePath, dependencyName, previousDependencyVersion, newDependencyVersion, _logger);
|
41
|
+
await GlobalJsonUpdater.UpdateDependencyAsync(repoRootPath, workspacePath, dependencyName, previousDependencyVersion, newDependencyVersion, _logger);
|
42
|
+
}
|
43
|
+
|
44
|
+
var extension = Path.GetExtension(workspacePath).ToLowerInvariant();
|
45
|
+
switch (extension)
|
46
|
+
{
|
47
|
+
case ".sln":
|
48
|
+
await RunForSolutionAsync(repoRootPath, workspacePath, dependencyName, previousDependencyVersion, newDependencyVersion, isTransitive);
|
49
|
+
break;
|
50
|
+
case ".proj":
|
51
|
+
await RunForProjFileAsync(repoRootPath, workspacePath, dependencyName, previousDependencyVersion, newDependencyVersion, isTransitive);
|
52
|
+
break;
|
53
|
+
case ".csproj":
|
54
|
+
case ".fsproj":
|
55
|
+
case ".vbproj":
|
56
|
+
await RunForProjectAsync(repoRootPath, workspacePath, dependencyName, previousDependencyVersion, newDependencyVersion, isTransitive);
|
57
|
+
break;
|
58
|
+
default:
|
59
|
+
_logger.Log($"File extension [{extension}] is not supported.");
|
60
|
+
break;
|
61
|
+
}
|
62
|
+
|
63
|
+
result = new(); // all ok
|
64
|
+
_logger.Log("Update complete.");
|
65
|
+
}
|
66
|
+
catch (HttpRequestException ex)
|
67
|
+
when (ex.StatusCode == HttpStatusCode.Unauthorized || ex.StatusCode == HttpStatusCode.Forbidden)
|
68
|
+
{
|
69
|
+
// TODO: consolidate this error handling between AnalyzeWorker, DiscoveryWorker, and UpdateWorker
|
70
|
+
result = new()
|
71
|
+
{
|
72
|
+
ErrorType = ErrorType.AuthenticationFailure,
|
73
|
+
ErrorDetails = "(" + string.Join("|", NuGetContext.GetPackageSourceUrls(workspacePath)) + ")",
|
74
|
+
};
|
75
|
+
}
|
76
|
+
catch (MissingFileException ex)
|
23
77
|
{
|
24
|
-
|
25
|
-
|
78
|
+
result = new()
|
79
|
+
{
|
80
|
+
ErrorType = ErrorType.MissingFile,
|
81
|
+
ErrorDetails = ex.FilePath,
|
82
|
+
};
|
26
83
|
}
|
27
84
|
|
28
|
-
|
29
|
-
|
85
|
+
_processedProjectPaths.Clear();
|
86
|
+
if (resultOutputPath is { })
|
30
87
|
{
|
31
|
-
|
32
|
-
await RunForSolutionAsync(repoRootPath, workspacePath, dependencyName, previousDependencyVersion, newDependencyVersion, isTransitive);
|
33
|
-
break;
|
34
|
-
case ".proj":
|
35
|
-
await RunForProjFileAsync(repoRootPath, workspacePath, dependencyName, previousDependencyVersion, newDependencyVersion, isTransitive);
|
36
|
-
break;
|
37
|
-
case ".csproj":
|
38
|
-
case ".fsproj":
|
39
|
-
case ".vbproj":
|
40
|
-
await RunForProjectAsync(repoRootPath, workspacePath, dependencyName, previousDependencyVersion, newDependencyVersion, isTransitive);
|
41
|
-
break;
|
42
|
-
default:
|
43
|
-
_logger.Log($"File extension [{extension}] is not supported.");
|
44
|
-
break;
|
88
|
+
await WriteResultFile(result, resultOutputPath, _logger);
|
45
89
|
}
|
90
|
+
}
|
46
91
|
|
47
|
-
|
92
|
+
internal static async Task WriteResultFile(UpdateOperationResult result, string resultOutputPath, Logger logger)
|
93
|
+
{
|
94
|
+
logger.Log($" Writing update result to [{resultOutputPath}].");
|
48
95
|
|
49
|
-
|
96
|
+
var resultJson = JsonSerializer.Serialize(result, SerializerOptions);
|
97
|
+
await File.WriteAllTextAsync(resultOutputPath, resultJson);
|
50
98
|
}
|
51
99
|
|
52
100
|
private async Task RunForSolutionAsync(
|
@@ -185,8 +185,9 @@ internal static partial class MSBuildHelper
|
|
185
185
|
var versionSpecification = packageItem.Metadata.FirstOrDefault(m => m.Name.Equals("Version", StringComparison.OrdinalIgnoreCase))?.Value
|
186
186
|
?? packageItem.Metadata.FirstOrDefault(m => m.Name.Equals("VersionOverride", StringComparison.OrdinalIgnoreCase))?.Value
|
187
187
|
?? string.Empty;
|
188
|
-
foreach (var
|
188
|
+
foreach (var rawAttributeValue in new[] { packageItem.Include, packageItem.Update })
|
189
189
|
{
|
190
|
+
var attributeValue = rawAttributeValue?.Trim();
|
190
191
|
if (!string.IsNullOrWhiteSpace(attributeValue))
|
191
192
|
{
|
192
193
|
if (packageInfo.TryGetValue(attributeValue, out var existingInfo))
|
@@ -312,6 +313,7 @@ internal static partial class MSBuildHelper
|
|
312
313
|
{
|
313
314
|
var tempProjectPath = await CreateTempProjectAsync(tempDirectory, repoRoot, projectPath, targetFramework, packages);
|
314
315
|
var (exitCode, stdOut, stdErr) = await ProcessEx.RunAsync("dotnet", $"restore \"{tempProjectPath}\"", workingDirectory: tempDirectory.FullName);
|
316
|
+
ThrowOnUnauthenticatedFeed(stdOut);
|
315
317
|
|
316
318
|
// simple cases first
|
317
319
|
// if restore failed, nothing we can do
|
@@ -506,6 +508,7 @@ internal static partial class MSBuildHelper
|
|
506
508
|
<TargetFramework>{targetFramework}</TargetFramework>
|
507
509
|
<GenerateDependencyFile>true</GenerateDependencyFile>
|
508
510
|
<RunAnalyzers>false</RunAnalyzers>
|
511
|
+
<NuGetInteractive>false</NuGetInteractive>
|
509
512
|
</PropertyGroup>
|
510
513
|
<ItemGroup>
|
511
514
|
{packageReferences}
|
@@ -565,6 +568,7 @@ internal static partial class MSBuildHelper
|
|
565
568
|
var tempProjectPath = await CreateTempProjectAsync(tempDirectory, repoRoot, projectPath, targetFramework, packages);
|
566
569
|
|
567
570
|
var (exitCode, stdout, stderr) = await ProcessEx.RunAsync("dotnet", $"build \"{tempProjectPath}\" /t:_ReportDependencies", workingDirectory: tempDirectory.FullName);
|
571
|
+
ThrowOnUnauthenticatedFeed(stdout);
|
568
572
|
|
569
573
|
if (exitCode == 0)
|
570
574
|
{
|
@@ -602,6 +606,30 @@ internal static partial class MSBuildHelper
|
|
602
606
|
}
|
603
607
|
}
|
604
608
|
|
609
|
+
internal static void ThrowOnUnauthenticatedFeed(string stdout)
|
610
|
+
{
|
611
|
+
var unauthorizedMessageSnippets = new string[]
|
612
|
+
{
|
613
|
+
"The plugin credential provider could not acquire credentials",
|
614
|
+
"401 (Unauthorized)",
|
615
|
+
"error NU1301: Unable to load the service index for source",
|
616
|
+
};
|
617
|
+
if (unauthorizedMessageSnippets.Any(stdout.Contains))
|
618
|
+
{
|
619
|
+
throw new HttpRequestException(message: stdout, inner: null, statusCode: System.Net.HttpStatusCode.Unauthorized);
|
620
|
+
}
|
621
|
+
}
|
622
|
+
|
623
|
+
internal static void ThrowOnMissingFile(string output)
|
624
|
+
{
|
625
|
+
var missingFilePattern = new Regex(@"The imported project \""(?<FilePath>.*)\"" was not found");
|
626
|
+
var match = missingFilePattern.Match(output);
|
627
|
+
if (match.Success)
|
628
|
+
{
|
629
|
+
throw new MissingFileException(match.Groups["FilePath"].Value);
|
630
|
+
}
|
631
|
+
}
|
632
|
+
|
605
633
|
internal static bool TryGetGlobalJsonPath(string repoRootPath, string workspacePath, [NotNullWhen(returnValue: true)] out string? globalJsonPath)
|
606
634
|
{
|
607
635
|
globalJsonPath = PathHelper.GetFileInDirectoryOrParent(workspacePath, repoRootPath, "global.json", caseSensitive: false);
|
@@ -18,7 +18,8 @@ public class AnalyzeWorkerTestBase
|
|
18
18
|
WorkspaceDiscoveryResult discovery,
|
19
19
|
DependencyInfo dependencyInfo,
|
20
20
|
ExpectedAnalysisResult expectedResult,
|
21
|
-
MockNuGetPackage[]? packages = null
|
21
|
+
MockNuGetPackage[]? packages = null,
|
22
|
+
TestFile[]? extraFiles = null)
|
22
23
|
{
|
23
24
|
var relativeDependencyPath = $"./dependabot/dependency/{dependencyInfo.Name}.json";
|
24
25
|
|
@@ -27,7 +28,8 @@ public class AnalyzeWorkerTestBase
|
|
27
28
|
(relativeDependencyPath, JsonSerializer.Serialize(dependencyInfo, AnalyzeWorker.SerializerOptions)),
|
28
29
|
];
|
29
30
|
|
30
|
-
var
|
31
|
+
var allFiles = files.Concat(extraFiles ?? []).ToArray();
|
32
|
+
var actualResult = await RunAnalyzerAsync(dependencyInfo.Name, allFiles, async directoryPath =>
|
31
33
|
{
|
32
34
|
await UpdateWorkerTestBase.MockNuGetPackagesInDirectory(packages, directoryPath);
|
33
35
|
|
@@ -50,6 +52,8 @@ public class AnalyzeWorkerTestBase
|
|
50
52
|
Assert.Equal(expectedResult.VersionComesFromMultiDependencyProperty, actualResult.VersionComesFromMultiDependencyProperty);
|
51
53
|
ValidateDependencies(expectedResult.UpdatedDependencies, actualResult.UpdatedDependencies);
|
52
54
|
Assert.Equal(expectedResult.ExpectedUpdatedDependenciesCount ?? expectedResult.UpdatedDependencies.Length, actualResult.UpdatedDependencies.Length);
|
55
|
+
Assert.Equal(expectedResult.ErrorType, actualResult.ErrorType);
|
56
|
+
Assert.Equal(expectedResult.ErrorDetails, actualResult.ErrorDetails);
|
53
57
|
|
54
58
|
return;
|
55
59
|
|