dependabot-nuget 0.292.0 → 0.293.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/.gitignore +1 -0
- data/helpers/lib/NuGetUpdater/Directory.Packages.props +1 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/Correlator.cs +197 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/DotNetPackageCorrelation.csproj +12 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/Model/PackageMapper.cs +68 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/Model/PackageSet.cs +11 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/Model/Release.cs +25 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/Model/ReleasesFile.cs +9 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/Model/RuntimePackages.cs +11 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/Model/Sdk.cs +13 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/Model/SemVerComparer.cs +16 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/Model/SemVersionConverter.cs +42 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation.Cli/DotNetPackageCorrelation.Cli.csproj +16 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation.Cli/Program.cs +32 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation.Test/CorrelatorTests.cs +99 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation.Test/DotNetPackageCorrelation.Test.csproj +18 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation.Test/EndToEndTests.cs +30 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation.Test/RuntimePackagesTests.cs +206 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/AnalyzeCommand.cs +6 -4
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/DiscoverCommand.cs +8 -7
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/RunCommand.cs +4 -4
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/UpdateCommand.cs +17 -5
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Analyze.cs +7 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Discover.cs +46 -6
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Update.cs +8 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/AnalyzeWorker.cs +8 -17
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/DependencyFinder.cs +4 -4
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/Extensions.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Clone/CloneWorker.cs +2 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/DependencyDiscovery.targets +2 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DiscoveryWorker.cs +7 -20
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/ProjectDiscoveryResult.cs +3 -3
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/SdkProjectDiscovery.cs +99 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/EnsureDotNetPackageCorrelation.targets +25 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ExperimentsManager.cs +9 -22
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/PackagesConfigBuildFile.cs +5 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/MissingFileException.cs +2 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/NativeResult.cs +3 -3
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/NuGetUpdater.Core.csproj +3 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/DependencyFileNotFound.cs +7 -3
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/DependencyFileNotParseable.cs +15 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/JobErrorBase.cs +24 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/RunWorker.cs +6 -21
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/UnparseableFileException.cs +12 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackageReferenceUpdater.cs +21 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdaterWorker.cs +6 -30
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/DotNetPackageCorrelationManager.cs +46 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +51 -27
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/NuGetHelper.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTestBase.cs +15 -4
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTests.cs +15 -9
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTestBase.cs +20 -12
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Project.cs +108 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs +16 -12
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/ExpectedDiscoveryResults.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/MockNuGetPackage.cs +15 -28
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/RunWorkerTests.cs +5 -4
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/SerializationTests.cs +9 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TestBase.cs +24 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/ExpectedUpdateOperationResult.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs +11 -15
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.DirsProj.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Mixed.cs +14 -8
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackageReference.cs +148 -3
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs +12 -14
- data/helpers/lib/NuGetUpdater/NuGetUpdater.sln +18 -1
- data/lib/dependabot/nuget/native_helpers.rb +41 -16
- metadata +25 -6
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ErrorType.cs +0 -12
@@ -3,6 +3,7 @@ using System.Text.Json;
|
|
3
3
|
using System.Text.Json.Serialization;
|
4
4
|
|
5
5
|
using NuGetUpdater.Core.Analyze;
|
6
|
+
using NuGetUpdater.Core.Run.ApiModel;
|
6
7
|
using NuGetUpdater.Core.Updater;
|
7
8
|
using NuGetUpdater.Core.Utilities;
|
8
9
|
|
@@ -10,6 +11,7 @@ namespace NuGetUpdater.Core;
|
|
10
11
|
|
11
12
|
public class UpdaterWorker : IUpdaterWorker
|
12
13
|
{
|
14
|
+
private readonly string _jobId;
|
13
15
|
private readonly ExperimentsManager _experimentsManager;
|
14
16
|
private readonly ILogger _logger;
|
15
17
|
private readonly HashSet<string> _processedProjectPaths = new(StringComparer.OrdinalIgnoreCase);
|
@@ -20,8 +22,9 @@ public class UpdaterWorker : IUpdaterWorker
|
|
20
22
|
Converters = { new JsonStringEnumConverter() },
|
21
23
|
};
|
22
24
|
|
23
|
-
public UpdaterWorker(ExperimentsManager experimentsManager, ILogger logger)
|
25
|
+
public UpdaterWorker(string jobId, ExperimentsManager experimentsManager, ILogger logger)
|
24
26
|
{
|
27
|
+
_jobId = jobId;
|
25
28
|
_experimentsManager = experimentsManager;
|
26
29
|
_logger = logger;
|
27
30
|
}
|
@@ -43,42 +46,15 @@ public class UpdaterWorker : IUpdaterWorker
|
|
43
46
|
{
|
44
47
|
result = await RunAsync(repoRootPath, workspacePath, dependencyName, previousDependencyVersion, newDependencyVersion, isTransitive);
|
45
48
|
}
|
46
|
-
catch (
|
47
|
-
when (ex.StatusCode == HttpStatusCode.Unauthorized || ex.StatusCode == HttpStatusCode.Forbidden)
|
49
|
+
catch (Exception ex)
|
48
50
|
{
|
49
51
|
if (!Path.IsPathRooted(workspacePath) || !File.Exists(workspacePath))
|
50
52
|
{
|
51
53
|
workspacePath = Path.GetFullPath(Path.Join(repoRootPath, workspacePath));
|
52
54
|
}
|
53
|
-
|
54
|
-
result = new()
|
55
|
-
{
|
56
|
-
ErrorType = ErrorType.AuthenticationFailure,
|
57
|
-
ErrorDetails = "(" + string.Join("|", NuGetContext.GetPackageSourceUrls(workspacePath)) + ")",
|
58
|
-
};
|
59
|
-
}
|
60
|
-
catch (MissingFileException ex)
|
61
|
-
{
|
62
|
-
result = new()
|
63
|
-
{
|
64
|
-
ErrorType = ErrorType.MissingFile,
|
65
|
-
ErrorDetails = ex.FilePath,
|
66
|
-
};
|
67
|
-
}
|
68
|
-
catch (UpdateNotPossibleException ex)
|
69
|
-
{
|
70
|
-
result = new()
|
71
|
-
{
|
72
|
-
ErrorType = ErrorType.UpdateNotPossible,
|
73
|
-
ErrorDetails = ex.Dependencies,
|
74
|
-
};
|
75
|
-
}
|
76
|
-
catch (Exception ex)
|
77
|
-
{
|
78
55
|
result = new()
|
79
56
|
{
|
80
|
-
|
81
|
-
ErrorDetails = ex.ToString(),
|
57
|
+
Error = JobErrorBase.ErrorFromException(ex, _jobId, workspacePath),
|
82
58
|
};
|
83
59
|
}
|
84
60
|
|
@@ -0,0 +1,46 @@
|
|
1
|
+
using System.Text.Json;
|
2
|
+
|
3
|
+
using DotNetPackageCorrelation;
|
4
|
+
|
5
|
+
using NuGetUpdater.Core.Discover;
|
6
|
+
|
7
|
+
namespace NuGetUpdater.Core.Utilities;
|
8
|
+
|
9
|
+
internal static class DotNetPackageCorrelationManager
|
10
|
+
{
|
11
|
+
private static readonly PackageMapper _packageMapper;
|
12
|
+
private static readonly Dictionary<string, PackageMapper> _packageMapperByOverrideFile = new();
|
13
|
+
|
14
|
+
static DotNetPackageCorrelationManager()
|
15
|
+
{
|
16
|
+
var packageCorrelationPath = Path.Combine(Path.GetDirectoryName(typeof(SdkProjectDiscovery).Assembly.Location)!, "dotnet-package-correlation.json");
|
17
|
+
var runtimePackages = LoadRuntimePackagesFromFile(packageCorrelationPath);
|
18
|
+
_packageMapper = PackageMapper.Load(runtimePackages);
|
19
|
+
}
|
20
|
+
|
21
|
+
public static PackageMapper GetPackageMapper()
|
22
|
+
{
|
23
|
+
var packageCorrelationFileOverride = Environment.GetEnvironmentVariable("DOTNET_PACKAGE_CORRELATION_FILE_PATH");
|
24
|
+
if (packageCorrelationFileOverride is not null)
|
25
|
+
{
|
26
|
+
// this is used as a test hook to allow unit tests to be SDK agnostic
|
27
|
+
if (_packageMapperByOverrideFile.TryGetValue(packageCorrelationFileOverride, out var packageMapper))
|
28
|
+
{
|
29
|
+
return packageMapper;
|
30
|
+
}
|
31
|
+
|
32
|
+
var runtimePackages = LoadRuntimePackagesFromFile(packageCorrelationFileOverride);
|
33
|
+
packageMapper = PackageMapper.Load(runtimePackages);
|
34
|
+
_packageMapperByOverrideFile[packageCorrelationFileOverride] = packageMapper;
|
35
|
+
return packageMapper;
|
36
|
+
}
|
37
|
+
|
38
|
+
return _packageMapper;
|
39
|
+
}
|
40
|
+
|
41
|
+
private static RuntimePackages LoadRuntimePackagesFromFile(string filePath)
|
42
|
+
{
|
43
|
+
var packageCorrelationJson = File.ReadAllText(filePath);
|
44
|
+
return JsonSerializer.Deserialize<RuntimePackages>(packageCorrelationJson, Correlator.SerializerOptions)!;
|
45
|
+
}
|
46
|
+
}
|
@@ -19,6 +19,7 @@ using NuGet.Frameworks;
|
|
19
19
|
using NuGet.Versioning;
|
20
20
|
|
21
21
|
using NuGetUpdater.Core.Analyze;
|
22
|
+
using NuGetUpdater.Core.Discover;
|
22
23
|
using NuGetUpdater.Core.Utilities;
|
23
24
|
|
24
25
|
namespace NuGetUpdater.Core;
|
@@ -342,7 +343,7 @@ internal static partial class MSBuildHelper
|
|
342
343
|
var tempDirectory = Directory.CreateTempSubdirectory("package-dependency-coherence_");
|
343
344
|
try
|
344
345
|
{
|
345
|
-
var tempProjectPath = await CreateTempProjectAsync(tempDirectory, repoRoot, projectPath, targetFramework, packages, logger);
|
346
|
+
var tempProjectPath = await CreateTempProjectAsync(tempDirectory, repoRoot, projectPath, targetFramework, packages, experimentsManager, logger);
|
346
347
|
var (exitCode, stdOut, stdErr) = await ProcessEx.RunDotnetWithoutMSBuildEnvironmentVariablesAsync(["restore", tempProjectPath], tempDirectory.FullName, experimentsManager);
|
347
348
|
|
348
349
|
// NU1608: Detected package version outside of dependency constraint
|
@@ -362,7 +363,7 @@ internal static partial class MSBuildHelper
|
|
362
363
|
|
363
364
|
try
|
364
365
|
{
|
365
|
-
string tempProjectPath = await CreateTempProjectAsync(tempDirectory, repoRoot, projectPath, targetFramework, packages, logger);
|
366
|
+
string tempProjectPath = await CreateTempProjectAsync(tempDirectory, repoRoot, projectPath, targetFramework, packages, experimentsManager, logger);
|
366
367
|
var (exitCode, stdOut, stdErr) = await ProcessEx.RunDotnetWithoutMSBuildEnvironmentVariablesAsync(["restore", tempProjectPath], tempDirectory.FullName, experimentsManager);
|
367
368
|
|
368
369
|
// Add Dependency[] packages to List<PackageToUpdate> existingPackages
|
@@ -518,7 +519,7 @@ internal static partial class MSBuildHelper
|
|
518
519
|
var tempDirectory = Directory.CreateTempSubdirectory("package-dependency-coherence_");
|
519
520
|
try
|
520
521
|
{
|
521
|
-
var tempProjectPath = await CreateTempProjectAsync(tempDirectory, repoRoot, projectPath, targetFramework, packages, logger);
|
522
|
+
var tempProjectPath = await CreateTempProjectAsync(tempDirectory, repoRoot, projectPath, targetFramework, packages, experimentsManager, logger);
|
522
523
|
var (exitCode, stdOut, stdErr) = await ProcessEx.RunDotnetWithoutMSBuildEnvironmentVariablesAsync(["restore", tempProjectPath], tempDirectory.FullName, experimentsManager);
|
523
524
|
ThrowOnUnauthenticatedFeed(stdOut);
|
524
525
|
|
@@ -668,12 +669,22 @@ internal static partial class MSBuildHelper
|
|
668
669
|
string projectPath,
|
669
670
|
string targetFramework,
|
670
671
|
IReadOnlyCollection<Dependency> packages,
|
672
|
+
ExperimentsManager experimentsManager,
|
671
673
|
ILogger logger,
|
672
674
|
bool usePackageDownload = false)
|
673
675
|
{
|
674
676
|
var projectDirectory = Path.GetDirectoryName(projectPath);
|
675
677
|
projectDirectory ??= repoRoot;
|
676
|
-
|
678
|
+
|
679
|
+
if (experimentsManager.InstallDotnetSdks)
|
680
|
+
{
|
681
|
+
var globalJsonPath = PathHelper.GetFileInDirectoryOrParent(projectPath, repoRoot, "global.json", caseSensitive: true);
|
682
|
+
if (globalJsonPath is not null)
|
683
|
+
{
|
684
|
+
File.Copy(globalJsonPath, Path.Combine(tempDir.FullName, "global.json"));
|
685
|
+
}
|
686
|
+
}
|
687
|
+
|
677
688
|
var nugetConfigPath = PathHelper.GetFileInDirectoryOrParent(projectPath, repoRoot, "NuGet.Config", caseSensitive: false);
|
678
689
|
if (nugetConfigPath is not null)
|
679
690
|
{
|
@@ -832,40 +843,53 @@ internal static partial class MSBuildHelper
|
|
832
843
|
string targetFramework,
|
833
844
|
IReadOnlyCollection<Dependency> packages,
|
834
845
|
ExperimentsManager experimentsManager,
|
835
|
-
ILogger logger
|
846
|
+
ILogger logger
|
847
|
+
)
|
836
848
|
{
|
837
849
|
var tempDirectory = Directory.CreateTempSubdirectory("package-dependency-resolution_");
|
838
850
|
try
|
839
851
|
{
|
840
852
|
var topLevelPackagesNames = packages.Select(p => p.Name).ToHashSet(StringComparer.OrdinalIgnoreCase);
|
841
|
-
var tempProjectPath = await CreateTempProjectAsync(tempDirectory, repoRoot, projectPath, targetFramework, packages, logger);
|
853
|
+
var tempProjectPath = await CreateTempProjectAsync(tempDirectory, repoRoot, projectPath, targetFramework, packages, experimentsManager, logger);
|
842
854
|
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
if (exitCode == 0)
|
855
|
+
Dependency[] allDependencies;
|
856
|
+
if (experimentsManager.UseDirectDiscovery)
|
847
857
|
{
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
.
|
853
|
-
.Where(match => match.Success)
|
854
|
-
.Select(match =>
|
855
|
-
{
|
856
|
-
var PackageName = match.Groups["PackageName"].Value;
|
857
|
-
var isTransitive = !topLevelPackagesNames.Contains(PackageName);
|
858
|
-
return new Dependency(PackageName, match.Groups["PackageVersion"].Value, DependencyType.Unknown, TargetFrameworks: tfms, IsTransitive: isTransitive);
|
859
|
-
})
|
860
|
-
.ToArray();
|
861
|
-
|
862
|
-
return allDependencies;
|
858
|
+
var projectDiscovery = await SdkProjectDiscovery.DiscoverAsync(repoRoot, tempDirectory.FullName, tempProjectPath, experimentsManager, logger);
|
859
|
+
allDependencies = projectDiscovery
|
860
|
+
.Where(p => p.FilePath == Path.GetFileName(tempProjectPath))
|
861
|
+
.FirstOrDefault()
|
862
|
+
?.Dependencies.ToArray() ?? [];
|
863
863
|
}
|
864
864
|
else
|
865
865
|
{
|
866
|
-
|
867
|
-
|
866
|
+
var (exitCode, stdout, stderr) = await ProcessEx.RunDotnetWithoutMSBuildEnvironmentVariablesAsync(["build", tempProjectPath, "/t:_ReportDependencies"], tempDirectory.FullName, experimentsManager);
|
867
|
+
ThrowOnUnauthenticatedFeed(stdout);
|
868
|
+
|
869
|
+
if (exitCode == 0)
|
870
|
+
{
|
871
|
+
ImmutableArray<string> tfms = [targetFramework];
|
872
|
+
var lines = stdout.Split('\n').Select(line => line.Trim());
|
873
|
+
var pattern = PackagePattern();
|
874
|
+
allDependencies = lines
|
875
|
+
.Select(line => pattern.Match(line))
|
876
|
+
.Where(match => match.Success)
|
877
|
+
.Select(match =>
|
878
|
+
{
|
879
|
+
var PackageName = match.Groups["PackageName"].Value;
|
880
|
+
var isTransitive = !topLevelPackagesNames.Contains(PackageName);
|
881
|
+
return new Dependency(PackageName, match.Groups["PackageVersion"].Value, DependencyType.Unknown, TargetFrameworks: tfms, IsTransitive: isTransitive);
|
882
|
+
})
|
883
|
+
.ToArray();
|
884
|
+
}
|
885
|
+
else
|
886
|
+
{
|
887
|
+
logger?.Warn($"dotnet build in {nameof(GetAllPackageDependenciesAsync)} failed. STDOUT: {stdout} STDERR: {stderr}");
|
888
|
+
allDependencies = [];
|
889
|
+
}
|
868
890
|
}
|
891
|
+
|
892
|
+
return allDependencies;
|
869
893
|
}
|
870
894
|
finally
|
871
895
|
{
|
@@ -9,7 +9,7 @@ internal static class NuGetHelper
|
|
9
9
|
var tempDirectory = Directory.CreateTempSubdirectory("msbuild_sdk_restore_");
|
10
10
|
try
|
11
11
|
{
|
12
|
-
var tempProjectPath = await MSBuildHelper.CreateTempProjectAsync(tempDirectory, repoRoot, projectPath, "netstandard2.0", packages, logger, usePackageDownload: true);
|
12
|
+
var tempProjectPath = await MSBuildHelper.CreateTempProjectAsync(tempDirectory, repoRoot, projectPath, "netstandard2.0", packages, experimentsManager, logger, usePackageDownload: true);
|
13
13
|
var (exitCode, stdOut, stdErr) = await ProcessEx.RunDotnetWithoutMSBuildEnvironmentVariablesAsync(["restore", tempProjectPath], tempDirectory.FullName, experimentsManager);
|
14
14
|
|
15
15
|
return exitCode == 0;
|
@@ -12,7 +12,7 @@ namespace NuGetUpdater.Core.Test.Analyze;
|
|
12
12
|
|
13
13
|
using TestFile = (string Path, string Content);
|
14
14
|
|
15
|
-
public class AnalyzeWorkerTestBase
|
15
|
+
public class AnalyzeWorkerTestBase : TestBase
|
16
16
|
{
|
17
17
|
protected static async Task TestAnalyzeAsync(
|
18
18
|
WorkspaceDiscoveryResult discovery,
|
@@ -39,7 +39,7 @@ public class AnalyzeWorkerTestBase
|
|
39
39
|
var discoveryPath = Path.GetFullPath(DiscoveryWorker.DiscoveryResultFileName, directoryPath);
|
40
40
|
var dependencyPath = Path.GetFullPath(relativeDependencyPath, directoryPath);
|
41
41
|
|
42
|
-
var worker = new AnalyzeWorker(experimentsManager, new TestLogger());
|
42
|
+
var worker = new AnalyzeWorker("TEST-JOB-ID", experimentsManager, new TestLogger());
|
43
43
|
var result = await worker.RunWithErrorHandlingAsync(directoryPath, discoveryPath, dependencyPath);
|
44
44
|
return result;
|
45
45
|
});
|
@@ -55,8 +55,7 @@ public class AnalyzeWorkerTestBase
|
|
55
55
|
Assert.Equal(expectedResult.VersionComesFromMultiDependencyProperty, actualResult.VersionComesFromMultiDependencyProperty);
|
56
56
|
ValidateDependencies(expectedResult.UpdatedDependencies, actualResult.UpdatedDependencies);
|
57
57
|
Assert.Equal(expectedResult.ExpectedUpdatedDependenciesCount ?? expectedResult.UpdatedDependencies.Length, actualResult.UpdatedDependencies.Length);
|
58
|
-
|
59
|
-
Assert.Equal(expectedResult.ErrorDetails, actualResult.ErrorDetails);
|
58
|
+
ValidateResult(expectedResult, actualResult);
|
60
59
|
|
61
60
|
return;
|
62
61
|
|
@@ -81,6 +80,18 @@ public class AnalyzeWorkerTestBase
|
|
81
80
|
}
|
82
81
|
}
|
83
82
|
|
83
|
+
protected static void ValidateResult(ExpectedAnalysisResult? expectedResult, AnalysisResult actualResult)
|
84
|
+
{
|
85
|
+
if (expectedResult?.Error is not null)
|
86
|
+
{
|
87
|
+
ValidateError(expectedResult.Error, actualResult.Error);
|
88
|
+
}
|
89
|
+
else
|
90
|
+
{
|
91
|
+
Assert.Null(actualResult.Error);
|
92
|
+
}
|
93
|
+
}
|
94
|
+
|
84
95
|
protected static async Task<AnalysisResult> RunAnalyzerAsync(string dependencyName, TestFile[] files, Func<string, Task<AnalysisResult>> action)
|
85
96
|
{
|
86
97
|
// write initial files
|
@@ -4,6 +4,7 @@ using System.Text.Json;
|
|
4
4
|
using NuGet;
|
5
5
|
|
6
6
|
using NuGetUpdater.Core.Analyze;
|
7
|
+
using NuGetUpdater.Core.Run.ApiModel;
|
7
8
|
|
8
9
|
using Xunit;
|
9
10
|
|
@@ -1015,8 +1016,7 @@ public partial class AnalyzeWorkerTests : AnalyzeWorkerTestBase
|
|
1015
1016
|
using var temporaryDirectory = await TemporaryDirectory.CreateWithContentsAsync([]);
|
1016
1017
|
await AnalyzeWorker.WriteResultsAsync(temporaryDirectory.DirectoryPath, "Some.Dependency", new()
|
1017
1018
|
{
|
1018
|
-
|
1019
|
-
ErrorDetails = "<some package feed>",
|
1019
|
+
Error = new PrivateSourceAuthenticationFailure(["<some package feed>"]),
|
1020
1020
|
UpdatedVersion = "",
|
1021
1021
|
UpdatedDependencies = [],
|
1022
1022
|
}, new TestLogger());
|
@@ -1025,16 +1025,23 @@ public partial class AnalyzeWorkerTests : AnalyzeWorkerTestBase
|
|
1025
1025
|
// raw result file should look like this:
|
1026
1026
|
// {
|
1027
1027
|
// ...
|
1028
|
-
// "
|
1028
|
+
// "Error": {
|
1029
|
+
// "error-type": "private_source_authentication_failure",
|
1030
|
+
// "error-details": {
|
1031
|
+
// "source": "(<some package feed>)"
|
1032
|
+
// }
|
1033
|
+
// }
|
1029
1034
|
// "ErrorDetails": "<some package feed>",
|
1030
1035
|
// ...
|
1031
1036
|
// }
|
1032
1037
|
var jsonDocument = JsonDocument.Parse(discoveryContents);
|
1033
|
-
var
|
1034
|
-
var
|
1038
|
+
var error = jsonDocument.RootElement.GetProperty("Error");
|
1039
|
+
var errorType = error.GetProperty("error-type");
|
1040
|
+
var errorDetails = error.GetProperty("error-details");
|
1041
|
+
var errorSource = errorDetails.GetProperty("source");
|
1035
1042
|
|
1036
|
-
Assert.Equal("
|
1037
|
-
Assert.Equal("<some package feed>",
|
1043
|
+
Assert.Equal("private_source_authentication_failure", errorType.GetString());
|
1044
|
+
Assert.Equal("(<some package feed>)", errorSource.GetString());
|
1038
1045
|
}
|
1039
1046
|
|
1040
1047
|
[Fact]
|
@@ -1110,8 +1117,7 @@ public partial class AnalyzeWorkerTests : AnalyzeWorkerTestBase
|
|
1110
1117
|
},
|
1111
1118
|
expectedResult: new()
|
1112
1119
|
{
|
1113
|
-
|
1114
|
-
ErrorDetails = $"({http.BaseUrl.TrimEnd('/')}/index.json)",
|
1120
|
+
Error = new PrivateSourceAuthenticationFailure([$"{http.BaseUrl.TrimEnd('/')}/index.json"]),
|
1115
1121
|
UpdatedVersion = string.Empty,
|
1116
1122
|
CanUpdate = false,
|
1117
1123
|
UpdatedDependencies = [],
|
@@ -5,7 +5,9 @@ using System.Text.Json;
|
|
5
5
|
|
6
6
|
using NuGetUpdater.Core.Discover;
|
7
7
|
using NuGetUpdater.Core.Test.Update;
|
8
|
+
using NuGetUpdater.Core.Test.Updater;
|
8
9
|
using NuGetUpdater.Core.Test.Utilities;
|
10
|
+
using NuGetUpdater.Core.Updater;
|
9
11
|
using NuGetUpdater.Core.Utilities;
|
10
12
|
|
11
13
|
using Xunit;
|
@@ -28,7 +30,7 @@ public class DiscoveryWorkerTestBase : TestBase
|
|
28
30
|
{
|
29
31
|
await UpdateWorkerTestBase.MockNuGetPackagesInDirectory(packages, directoryPath);
|
30
32
|
|
31
|
-
var worker = new DiscoveryWorker(experimentsManager, new TestLogger());
|
33
|
+
var worker = new DiscoveryWorker("TEST-JOB-ID", experimentsManager, new TestLogger());
|
32
34
|
var result = await worker.RunWithErrorHandlingAsync(directoryPath, workspacePath);
|
33
35
|
return result;
|
34
36
|
});
|
@@ -44,17 +46,7 @@ public class DiscoveryWorkerTestBase : TestBase
|
|
44
46
|
ValidateResultWithDependencies(expectedResult.DotNetToolsJson, actualResult.DotNetToolsJson);
|
45
47
|
ValidateProjectResults(expectedResult.Projects, actualResult.Projects, experimentsManager);
|
46
48
|
Assert.Equal(expectedResult.ExpectedProjectCount ?? expectedResult.Projects.Length, actualResult.Projects.Length);
|
47
|
-
|
48
|
-
if (expectedResult.ErrorDetailsPattern is not null)
|
49
|
-
{
|
50
|
-
var errorDetails = actualResult.ErrorDetails?.ToString();
|
51
|
-
Assert.NotNull(errorDetails);
|
52
|
-
Assert.Matches(expectedResult.ErrorDetailsPattern, errorDetails);
|
53
|
-
}
|
54
|
-
else
|
55
|
-
{
|
56
|
-
Assert.Equal(expectedResult.ErrorDetails, actualResult.ErrorDetails);
|
57
|
-
}
|
49
|
+
ValidateDiscoveryOperationResult(expectedResult, actualResult);
|
58
50
|
|
59
51
|
return;
|
60
52
|
|
@@ -76,6 +68,22 @@ public class DiscoveryWorkerTestBase : TestBase
|
|
76
68
|
}
|
77
69
|
}
|
78
70
|
|
71
|
+
protected static void ValidateDiscoveryOperationResult(ExpectedWorkspaceDiscoveryResult? expectedResult, WorkspaceDiscoveryResult actualResult)
|
72
|
+
{
|
73
|
+
if (expectedResult?.Error is not null)
|
74
|
+
{
|
75
|
+
ValidateError(expectedResult.Error, actualResult.Error);
|
76
|
+
}
|
77
|
+
else if (expectedResult?.ErrorRegex is not null)
|
78
|
+
{
|
79
|
+
ValidateErrorRegex(expectedResult.ErrorRegex, actualResult.Error);
|
80
|
+
}
|
81
|
+
else
|
82
|
+
{
|
83
|
+
Assert.Null(actualResult.Error);
|
84
|
+
}
|
85
|
+
}
|
86
|
+
|
79
87
|
internal static void ValidateProjectResults(ImmutableArray<ExpectedSdkProjectDiscoveryResult> expectedProjects, ImmutableArray<ProjectDiscoveryResult> actualProjects, ExperimentsManager experimentsManager)
|
80
88
|
{
|
81
89
|
if (expectedProjects.IsDefaultOrEmpty)
|
data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Project.cs
CHANGED
@@ -1263,5 +1263,113 @@ public partial class DiscoveryWorkerTests
|
|
1263
1263
|
}
|
1264
1264
|
);
|
1265
1265
|
}
|
1266
|
+
|
1267
|
+
[Fact]
|
1268
|
+
public async Task PackagesManagedAndRemovedByTheSdkAreReported()
|
1269
|
+
{
|
1270
|
+
// To avoid a unit test that's tightly coupled to the installed SDK, some files are faked.
|
1271
|
+
// First up, the `dotnet-package-correlation.json` is faked to have the appropriate shape to report a
|
1272
|
+
// package replacement. Doing this requires a temporary file and environment variable override.
|
1273
|
+
using var tempDirectory = new TemporaryDirectory();
|
1274
|
+
var packageCorrelationFile = Path.Combine(tempDirectory.DirectoryPath, "dotnet-package-correlation.json");
|
1275
|
+
await File.WriteAllTextAsync(packageCorrelationFile, """
|
1276
|
+
{
|
1277
|
+
"Runtimes": {
|
1278
|
+
"1.0.0": {
|
1279
|
+
"Packages": {
|
1280
|
+
"Dependabot.App.Core.Ref": "1.0.0",
|
1281
|
+
"Test.Only.Package": "1.0.0"
|
1282
|
+
}
|
1283
|
+
},
|
1284
|
+
"1.0.1": {
|
1285
|
+
"Packages": {
|
1286
|
+
"Dependabot.App.Core.Ref": "1.0.1",
|
1287
|
+
"Test.Only.Package": "1.0.99"
|
1288
|
+
}
|
1289
|
+
}
|
1290
|
+
}
|
1291
|
+
}
|
1292
|
+
""");
|
1293
|
+
using var tempEnvironment = new TemporaryEnvironment([("DOTNET_PACKAGE_CORRELATION_FILE_PATH", packageCorrelationFile)]);
|
1294
|
+
|
1295
|
+
// The SDK package handling is detected in a very specific circumstance; an assembly being removed from the
|
1296
|
+
// `@(References)` item group in the `_HandlePackageFileConflicts` target. Since we don't want to involve
|
1297
|
+
// the real SDK, we fake some required targets.
|
1298
|
+
await TestDiscoveryAsync(
|
1299
|
+
experimentsManager: new ExperimentsManager() { InstallDotnetSdks = true, UseDirectDiscovery = true },
|
1300
|
+
packages: [],
|
1301
|
+
workspacePath: "",
|
1302
|
+
files:
|
1303
|
+
[
|
1304
|
+
("project.csproj", """
|
1305
|
+
<Project>
|
1306
|
+
<!-- note that the attribute `Sdk="Microsoft.NET.Sdk"` is missing because we don't want the real SDK interfering -->
|
1307
|
+
|
1308
|
+
<!-- this allows custom targets to be injected for dependency detection -->
|
1309
|
+
<Import Project="$(CustomAfterMicrosoftCommonTargets)" Condition="Exists('$(CustomAfterMicrosoftCommonTargets)')" />
|
1310
|
+
|
1311
|
+
<PropertyGroup>
|
1312
|
+
<TargetFramework>net8.0</TargetFramework>
|
1313
|
+
</PropertyGroup>
|
1314
|
+
|
1315
|
+
<ItemGroup>
|
1316
|
+
<!-- we need a value in this item group with the appropriate metadata to simulate it having been added by NuGet -->
|
1317
|
+
<RuntimeCopyLocalItems Include="TestOnlyAssembly.dll" NuGetPackageId="Test.Only.Package" NuGetPackageVersion="1.0.0" />
|
1318
|
+
|
1319
|
+
<!-- this represents the assemblies being extracted from the package -->
|
1320
|
+
<Reference Include="@(RuntimeCopyLocalItems)" />
|
1321
|
+
</ItemGroup>
|
1322
|
+
|
1323
|
+
<Target Name="_HandlePackageFileConflicts">
|
1324
|
+
<!-- this target needs to exist for discovery to work -->
|
1325
|
+
<ItemGroup>
|
1326
|
+
<!-- this removal is what triggers the package lookup in the correlation file -->
|
1327
|
+
<Reference Remove="TestOnlyAssembly.dll" />
|
1328
|
+
|
1329
|
+
<!-- this addition is what's used for the lookup -->
|
1330
|
+
<Reference Include="TestOnlyAssembly.dll" NuGetPackageId="Dependabot.App.Core.Ref" NuGetPackageVersion="1.0.1" />
|
1331
|
+
</ItemGroup>
|
1332
|
+
</Target>
|
1333
|
+
|
1334
|
+
<Target Name="ResolveAssemblyReferences" DependsOnTargets="_HandlePackageFileConflicts">
|
1335
|
+
<!-- this target needs to exist for discovery to work -->
|
1336
|
+
</Target>
|
1337
|
+
|
1338
|
+
<Target Name="GenerateBuildDependencyFile">
|
1339
|
+
<!-- this target needs to exist for discovery to work -->
|
1340
|
+
<ItemGroup>
|
1341
|
+
<!-- this removal is what removes the regular package reference from the project -->
|
1342
|
+
<RuntimeCopyLocalItems Remove="TestOnlyAssembly.dll" />
|
1343
|
+
</ItemGroup>
|
1344
|
+
</Target>
|
1345
|
+
|
1346
|
+
<Target Name="ResolvePackageAssets">
|
1347
|
+
<!-- this target needs to exist for discovery to work -->
|
1348
|
+
</Target>
|
1349
|
+
</Project>
|
1350
|
+
""")
|
1351
|
+
],
|
1352
|
+
expectedResult: new()
|
1353
|
+
{
|
1354
|
+
Path = "",
|
1355
|
+
Projects = [
|
1356
|
+
new()
|
1357
|
+
{
|
1358
|
+
FilePath = "project.csproj",
|
1359
|
+
Dependencies = [
|
1360
|
+
new("Test.Only.Package", "1.0.99", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true)
|
1361
|
+
],
|
1362
|
+
Properties = [
|
1363
|
+
new("TargetFramework", "net8.0", "project.csproj")
|
1364
|
+
],
|
1365
|
+
TargetFrameworks = ["net8.0"],
|
1366
|
+
ReferencedProjectPaths = [],
|
1367
|
+
ImportedFiles = [],
|
1368
|
+
AdditionalFiles = [],
|
1369
|
+
}
|
1370
|
+
]
|
1371
|
+
}
|
1372
|
+
);
|
1373
|
+
}
|
1266
1374
|
}
|
1267
1375
|
}
|
@@ -3,6 +3,7 @@ using System.Runtime.InteropServices;
|
|
3
3
|
using System.Text.Json;
|
4
4
|
|
5
5
|
using NuGetUpdater.Core.Discover;
|
6
|
+
using NuGetUpdater.Core.Run.ApiModel;
|
6
7
|
|
7
8
|
using Xunit;
|
8
9
|
|
@@ -1130,8 +1131,7 @@ public partial class DiscoveryWorkerTests : DiscoveryWorkerTestBase
|
|
1130
1131
|
{
|
1131
1132
|
Path = "",
|
1132
1133
|
Projects = [],
|
1133
|
-
|
1134
|
-
ErrorDetails = "project2.csproj",
|
1134
|
+
Error = new DependencyFileNotParseable("project2.csproj"),
|
1135
1135
|
});
|
1136
1136
|
}
|
1137
1137
|
|
@@ -1142,8 +1142,7 @@ public partial class DiscoveryWorkerTests : DiscoveryWorkerTestBase
|
|
1142
1142
|
var discoveryResultPath = Path.Combine(temporaryDirectory.DirectoryPath, DiscoveryWorker.DiscoveryResultFileName);
|
1143
1143
|
await DiscoveryWorker.WriteResultsAsync(temporaryDirectory.DirectoryPath, discoveryResultPath, new()
|
1144
1144
|
{
|
1145
|
-
|
1146
|
-
ErrorDetails = "<some package feed>",
|
1145
|
+
Error = new PrivateSourceAuthenticationFailure(["<some package feed>"]),
|
1147
1146
|
Path = "/",
|
1148
1147
|
Projects = [],
|
1149
1148
|
});
|
@@ -1152,16 +1151,22 @@ public partial class DiscoveryWorkerTests : DiscoveryWorkerTestBase
|
|
1152
1151
|
// raw result file should look like this:
|
1153
1152
|
// {
|
1154
1153
|
// ...
|
1155
|
-
// "
|
1156
|
-
//
|
1154
|
+
// "Error": {
|
1155
|
+
// "error-type": "private_source_authentication_failure",
|
1156
|
+
// "error-detail": {
|
1157
|
+
// "source": "(<some package feed>)"
|
1158
|
+
// }
|
1159
|
+
// }
|
1157
1160
|
// ...
|
1158
1161
|
// }
|
1159
1162
|
var jsonDocument = JsonDocument.Parse(discoveryContents);
|
1160
|
-
var
|
1161
|
-
var
|
1163
|
+
var error = jsonDocument.RootElement.GetProperty("Error");
|
1164
|
+
var errorType = error.GetProperty("error-type");
|
1165
|
+
var errorDetail = error.GetProperty("error-details");
|
1166
|
+
var errorSource = errorDetail.GetProperty("source");
|
1162
1167
|
|
1163
|
-
Assert.Equal("
|
1164
|
-
Assert.Equal("<some package feed>",
|
1168
|
+
Assert.Equal("private_source_authentication_failure", errorType.GetString());
|
1169
|
+
Assert.Equal("(<some package feed>)", errorSource.GetString());
|
1165
1170
|
}
|
1166
1171
|
|
1167
1172
|
[Theory]
|
@@ -1236,8 +1241,7 @@ public partial class DiscoveryWorkerTests : DiscoveryWorkerTestBase
|
|
1236
1241
|
],
|
1237
1242
|
expectedResult: new()
|
1238
1243
|
{
|
1239
|
-
|
1240
|
-
ErrorDetails = $"({http.BaseUrl.TrimEnd('/')}/index.json)",
|
1244
|
+
Error = new PrivateSourceAuthenticationFailure([$"{http.BaseUrl.TrimEnd('/')}/index.json"]),
|
1241
1245
|
Path = "",
|
1242
1246
|
Projects = [],
|
1243
1247
|
}
|
@@ -12,7 +12,7 @@ public record ExpectedWorkspaceDiscoveryResult : NativeResult
|
|
12
12
|
public int? ExpectedProjectCount { get; init; }
|
13
13
|
public ExpectedDependencyDiscoveryResult? GlobalJson { get; init; }
|
14
14
|
public ExpectedDependencyDiscoveryResult? DotNetToolsJson { get; init; }
|
15
|
-
public string?
|
15
|
+
public string? ErrorRegex { get; init; } = null;
|
16
16
|
}
|
17
17
|
|
18
18
|
public record ExpectedSdkProjectDiscoveryResult : ExpectedDependencyDiscoveryResult
|