dependabot-nuget 0.290.0 → 0.292.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/.editorconfig +1 -0
- data/helpers/lib/NuGetUpdater/Directory.Build.props +1 -0
- data/helpers/lib/NuGetUpdater/Directory.Packages.props +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/AnalyzeCommand.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/CloneCommand.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/DiscoverCommand.cs +15 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/RunCommand.cs +2 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/UpdateCommand.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Analyze.cs +2 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Discover.cs +87 -3
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Update.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/AnalyzeWorker.cs +14 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/DependencyFinder.cs +2 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/RequirementConverter.cs +19 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/BadRequirementException.cs +9 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Clone/CloneWorker.cs +39 -8
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DiscoveryWorker.cs +111 -17
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/PackagesConfigDiscovery.cs +2 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/ProjectDiscoveryResult.cs +2 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/SdkProjectDiscovery.cs +19 -11
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ErrorType.cs +2 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ExperimentsManager.cs +31 -5
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/NuGetUpdater.Core.csproj +1 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/BadRequirement.cs +10 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/CommitOptions.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/DependencyFileNotFound.cs +3 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/JobErrorBase.cs +1 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/JobRepoNotFound.cs +1 -4
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/PrivateSourceAuthenticationFailure.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/UnknownError.cs +6 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/UpdateNotPossible.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/RunWorker.cs +9 -3
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/LockFileUpdater.cs +3 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackageReferenceUpdater.cs +43 -18
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdaterWorker.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/WebApplicationTargetsConditionPatcher.cs +12 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/DependencyConflictResolver.cs +0 -7
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +48 -17
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/NuGetHelper.cs +2 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ProcessExtensions.cs +45 -7
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ProjectHelper.cs +4 -4
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Clone/CloneWorkerTests.cs +60 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTestBase.cs +10 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.PackagesConfig.cs +56 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs +41 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/ExpectedDiscoveryResults.cs +2 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/SdkProjectDiscoveryTests.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/MockNuGetPackage.cs +2 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/RunWorkerTests.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/SerializationTests.cs +76 -40
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs +20 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.GlobalJson.cs +2 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.LockFile.cs +251 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackageReference.cs +6 -6
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs +63 -5
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/MSBuildHelperTests.cs +277 -73
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/ProjectHelperTests.cs +65 -0
- data/helpers/lib/NuGetUpdater/global.json +1 -1
- data/lib/dependabot/nuget/file_fetcher.rb +1 -0
- data/lib/dependabot/nuget/file_parser.rb +90 -0
- data/lib/dependabot/nuget/language.rb +98 -0
- data/lib/dependabot/nuget/native_helpers.rb +25 -0
- data/lib/dependabot/nuget/package_manager.rb +51 -0
- metadata +12 -6
@@ -34,7 +34,8 @@ internal static partial class MSBuildHelper
|
|
34
34
|
// Ensure MSBuild types are registered before calling a method that loads the types
|
35
35
|
if (!IsMSBuildRegistered)
|
36
36
|
{
|
37
|
-
|
37
|
+
var experimentsManager = new ExperimentsManager() { InstallDotnetSdks = false }; // `global.json` definitely needs to be moved for this operation
|
38
|
+
HandleGlobalJsonAsync(currentDirectory, rootDirectory, experimentsManager, () =>
|
38
39
|
{
|
39
40
|
var defaultInstance = MSBuildLocator.QueryVisualStudioInstances().First();
|
40
41
|
MSBuildPath = defaultInstance.MSBuildPath;
|
@@ -44,9 +45,23 @@ internal static partial class MSBuildHelper
|
|
44
45
|
}
|
45
46
|
}
|
46
47
|
|
47
|
-
public static async Task<T>
|
48
|
+
public static async Task<T> HandleGlobalJsonAsync<T>(
|
49
|
+
string currentDirectory,
|
50
|
+
string rootDirectory,
|
51
|
+
ExperimentsManager experimentsManager,
|
52
|
+
Func<Task<T>> action,
|
53
|
+
ILogger? logger = null,
|
54
|
+
bool retainMSBuildSdks = false
|
55
|
+
)
|
48
56
|
{
|
49
57
|
logger ??= new ConsoleLogger();
|
58
|
+
if (experimentsManager.InstallDotnetSdks)
|
59
|
+
{
|
60
|
+
logger.Info($"{nameof(ExperimentsManager.InstallDotnetSdks)} == true; retaining `global.json` contents.");
|
61
|
+
var result = await action();
|
62
|
+
return result;
|
63
|
+
}
|
64
|
+
|
50
65
|
var candidateDirectories = PathHelper.GetAllDirectoriesToRoot(currentDirectory, rootDirectory);
|
51
66
|
var globalJsonPaths = candidateDirectories.Select(d => Path.Combine(d, "global.json")).Where(File.Exists).Select(p => (p, p + Guid.NewGuid().ToString())).ToArray();
|
52
67
|
foreach (var (globalJsonPath, tempGlobalJsonPath) in globalJsonPaths)
|
@@ -322,13 +337,13 @@ internal static partial class MSBuildHelper
|
|
322
337
|
return false;
|
323
338
|
}
|
324
339
|
|
325
|
-
internal static async Task<bool> DependenciesAreCoherentAsync(string repoRoot, string projectPath, string targetFramework, Dependency[] packages, ILogger logger)
|
340
|
+
internal static async Task<bool> DependenciesAreCoherentAsync(string repoRoot, string projectPath, string targetFramework, Dependency[] packages, ExperimentsManager experimentsManager, ILogger logger)
|
326
341
|
{
|
327
342
|
var tempDirectory = Directory.CreateTempSubdirectory("package-dependency-coherence_");
|
328
343
|
try
|
329
344
|
{
|
330
345
|
var tempProjectPath = await CreateTempProjectAsync(tempDirectory, repoRoot, projectPath, targetFramework, packages, logger);
|
331
|
-
var (exitCode, stdOut, stdErr) = await ProcessEx.
|
346
|
+
var (exitCode, stdOut, stdErr) = await ProcessEx.RunDotnetWithoutMSBuildEnvironmentVariablesAsync(["restore", tempProjectPath], tempDirectory.FullName, experimentsManager);
|
332
347
|
|
333
348
|
// NU1608: Detected package version outside of dependency constraint
|
334
349
|
|
@@ -340,7 +355,7 @@ internal static partial class MSBuildHelper
|
|
340
355
|
}
|
341
356
|
}
|
342
357
|
|
343
|
-
internal static async Task<Dependency[]?> ResolveDependencyConflicts(string repoRoot, string projectPath, string targetFramework, Dependency[] packages, Dependency[] update, ILogger logger)
|
358
|
+
internal static async Task<Dependency[]?> ResolveDependencyConflicts(string repoRoot, string projectPath, string targetFramework, Dependency[] packages, Dependency[] update, ExperimentsManager experimentsManager, ILogger logger)
|
344
359
|
{
|
345
360
|
var tempDirectory = Directory.CreateTempSubdirectory("package-dependency-coherence_");
|
346
361
|
PackageManager packageManager = new PackageManager(repoRoot, projectPath);
|
@@ -348,7 +363,7 @@ internal static partial class MSBuildHelper
|
|
348
363
|
try
|
349
364
|
{
|
350
365
|
string tempProjectPath = await CreateTempProjectAsync(tempDirectory, repoRoot, projectPath, targetFramework, packages, logger);
|
351
|
-
var (exitCode, stdOut, stdErr) = await ProcessEx.
|
366
|
+
var (exitCode, stdOut, stdErr) = await ProcessEx.RunDotnetWithoutMSBuildEnvironmentVariablesAsync(["restore", tempProjectPath], tempDirectory.FullName, experimentsManager);
|
352
367
|
|
353
368
|
// Add Dependency[] packages to List<PackageToUpdate> existingPackages
|
354
369
|
List<PackageToUpdate> existingPackages = packages
|
@@ -498,13 +513,13 @@ internal static partial class MSBuildHelper
|
|
498
513
|
}
|
499
514
|
}
|
500
515
|
|
501
|
-
internal static async Task<Dependency[]?> ResolveDependencyConflictsWithBruteForce(string repoRoot, string projectPath, string targetFramework, Dependency[] packages, ILogger logger)
|
516
|
+
internal static async Task<Dependency[]?> ResolveDependencyConflictsWithBruteForce(string repoRoot, string projectPath, string targetFramework, Dependency[] packages, ExperimentsManager experimentsManager, ILogger logger)
|
502
517
|
{
|
503
518
|
var tempDirectory = Directory.CreateTempSubdirectory("package-dependency-coherence_");
|
504
519
|
try
|
505
520
|
{
|
506
521
|
var tempProjectPath = await CreateTempProjectAsync(tempDirectory, repoRoot, projectPath, targetFramework, packages, logger);
|
507
|
-
var (exitCode, stdOut, stdErr) = await ProcessEx.
|
522
|
+
var (exitCode, stdOut, stdErr) = await ProcessEx.RunDotnetWithoutMSBuildEnvironmentVariablesAsync(["restore", tempProjectPath], tempDirectory.FullName, experimentsManager);
|
508
523
|
ThrowOnUnauthenticatedFeed(stdOut);
|
509
524
|
|
510
525
|
// simple cases first
|
@@ -529,6 +544,7 @@ internal static partial class MSBuildHelper
|
|
529
544
|
foreach ((string PackageName, NuGetVersion packageVersion) in badPackagesAndVersions)
|
530
545
|
{
|
531
546
|
// this command dumps a JSON object with all versions of the specified package from all package sources
|
547
|
+
// not using the `dotnet` execution method because we want to force the latest MSBuild and SDK to be used
|
532
548
|
(exitCode, stdOut, stdErr) = await ProcessEx.RunAsync("dotnet", ["package", "search", PackageName, "--exact-match", "--format", "json"], workingDirectory: tempDirectory.FullName);
|
533
549
|
if (exitCode != 0)
|
534
550
|
{
|
@@ -591,7 +607,7 @@ internal static partial class MSBuildHelper
|
|
591
607
|
return p;
|
592
608
|
}).ToArray();
|
593
609
|
|
594
|
-
if (await DependenciesAreCoherentAsync(repoRoot, projectPath, targetFramework, candidatePackages, logger))
|
610
|
+
if (await DependenciesAreCoherentAsync(repoRoot, projectPath, targetFramework, candidatePackages, experimentsManager, logger))
|
595
611
|
{
|
596
612
|
// return as soon as we find a coherent set
|
597
613
|
return candidatePackages;
|
@@ -749,14 +765,23 @@ internal static partial class MSBuildHelper
|
|
749
765
|
return tempProjectPath;
|
750
766
|
}
|
751
767
|
|
752
|
-
internal static async Task<ImmutableArray<string>> GetTargetFrameworkValuesFromProject(string repoRoot, string projectPath, ILogger logger)
|
768
|
+
internal static async Task<ImmutableArray<string>> GetTargetFrameworkValuesFromProject(string repoRoot, string projectPath, ExperimentsManager experimentsManager, ILogger logger)
|
753
769
|
{
|
754
|
-
// TODO: once the updater image has all relevant SDKs installed, we won't have to sideline global.json anymore
|
755
770
|
var projectDirectory = Path.GetDirectoryName(projectPath)!;
|
756
|
-
var (exitCode, stdOut, stdErr) = await
|
771
|
+
var (exitCode, stdOut, stdErr) = await HandleGlobalJsonAsync(projectDirectory, repoRoot, experimentsManager, async () =>
|
757
772
|
{
|
758
773
|
var targetsHelperPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!, "TargetFrameworkReporter.targets");
|
759
|
-
var (exitCode, stdOut, stdErr) = await ProcessEx.
|
774
|
+
var (exitCode, stdOut, stdErr) = await ProcessEx.RunDotnetWithoutMSBuildEnvironmentVariablesAsync(
|
775
|
+
[
|
776
|
+
"build",
|
777
|
+
projectPath,
|
778
|
+
"/t:ReportTargetFramework",
|
779
|
+
$"/p:CustomAfterMicrosoftCommonCrossTargetingTargets={targetsHelperPath}",
|
780
|
+
$"/p:CustomAfterMicrosoftCommonTargets={targetsHelperPath}"
|
781
|
+
],
|
782
|
+
projectDirectory,
|
783
|
+
experimentsManager
|
784
|
+
);
|
760
785
|
return (exitCode, stdOut, stdErr);
|
761
786
|
});
|
762
787
|
ThrowOnUnauthenticatedFeed(stdOut);
|
@@ -806,6 +831,7 @@ internal static partial class MSBuildHelper
|
|
806
831
|
string projectPath,
|
807
832
|
string targetFramework,
|
808
833
|
IReadOnlyCollection<Dependency> packages,
|
834
|
+
ExperimentsManager experimentsManager,
|
809
835
|
ILogger logger)
|
810
836
|
{
|
811
837
|
var tempDirectory = Directory.CreateTempSubdirectory("package-dependency-resolution_");
|
@@ -814,7 +840,7 @@ internal static partial class MSBuildHelper
|
|
814
840
|
var topLevelPackagesNames = packages.Select(p => p.Name).ToHashSet(StringComparer.OrdinalIgnoreCase);
|
815
841
|
var tempProjectPath = await CreateTempProjectAsync(tempDirectory, repoRoot, projectPath, targetFramework, packages, logger);
|
816
842
|
|
817
|
-
var (exitCode, stdout, stderr) = await ProcessEx.
|
843
|
+
var (exitCode, stdout, stderr) = await ProcessEx.RunDotnetWithoutMSBuildEnvironmentVariablesAsync(["build", tempProjectPath, "/t:_ReportDependencies"], tempDirectory.FullName, experimentsManager);
|
818
844
|
ThrowOnUnauthenticatedFeed(stdout);
|
819
845
|
|
820
846
|
if (exitCode == 0)
|
@@ -860,6 +886,7 @@ internal static partial class MSBuildHelper
|
|
860
886
|
"The plugin credential provider could not acquire credentials",
|
861
887
|
"401 (Unauthorized)",
|
862
888
|
"error NU1301: Unable to load the service index for source",
|
889
|
+
"Response status code does not indicate success: 403",
|
863
890
|
};
|
864
891
|
if (unauthorizedMessageSnippets.Any(stdout.Contains))
|
865
892
|
{
|
@@ -869,9 +896,13 @@ internal static partial class MSBuildHelper
|
|
869
896
|
|
870
897
|
internal static string? GetMissingFile(string output)
|
871
898
|
{
|
872
|
-
var
|
873
|
-
|
874
|
-
|
899
|
+
var missingFilePatterns = new[]
|
900
|
+
{
|
901
|
+
new Regex(@"The imported project \""(?<FilePath>.*)\"" was not found"),
|
902
|
+
new Regex(@"The imported file \""(?<FilePath>.*)\"" does not exist"),
|
903
|
+
};
|
904
|
+
var match = missingFilePatterns.Select(p => p.Match(output)).Where(m => m.Success).FirstOrDefault();
|
905
|
+
if (match is not null)
|
875
906
|
{
|
876
907
|
return match.Groups["FilePath"].Value;
|
877
908
|
}
|
@@ -4,13 +4,13 @@ namespace NuGetUpdater.Core;
|
|
4
4
|
|
5
5
|
internal static class NuGetHelper
|
6
6
|
{
|
7
|
-
internal static async Task<bool> DownloadNuGetPackagesAsync(string repoRoot, string projectPath, IReadOnlyCollection<Dependency> packages, ILogger logger)
|
7
|
+
internal static async Task<bool> DownloadNuGetPackagesAsync(string repoRoot, string projectPath, IReadOnlyCollection<Dependency> packages, ExperimentsManager experimentsManager, ILogger logger)
|
8
8
|
{
|
9
9
|
var tempDirectory = Directory.CreateTempSubdirectory("msbuild_sdk_restore_");
|
10
10
|
try
|
11
11
|
{
|
12
12
|
var tempProjectPath = await MSBuildHelper.CreateTempProjectAsync(tempDirectory, repoRoot, projectPath, "netstandard2.0", packages, logger, usePackageDownload: true);
|
13
|
-
var (exitCode, stdOut, stdErr) = await ProcessEx.
|
13
|
+
var (exitCode, stdOut, stdErr) = await ProcessEx.RunDotnetWithoutMSBuildEnvironmentVariablesAsync(["restore", tempProjectPath], tempDirectory.FullName, experimentsManager);
|
14
14
|
|
15
15
|
return exitCode == 0;
|
16
16
|
}
|
@@ -5,19 +5,57 @@ namespace NuGetUpdater.Core;
|
|
5
5
|
|
6
6
|
public static class ProcessEx
|
7
7
|
{
|
8
|
-
|
8
|
+
/// <summary>
|
9
|
+
/// Run the `dotnet` command with the given values. This will exclude all `MSBuild*` environment variables from the execution.
|
10
|
+
/// </summary>
|
11
|
+
public static Task<(int ExitCode, string Output, string Error)> RunDotnetWithoutMSBuildEnvironmentVariablesAsync(IEnumerable<string> arguments, string workingDirectory, ExperimentsManager experimentsManager)
|
12
|
+
{
|
13
|
+
var environmentVariablesToUnset = new List<string>();
|
14
|
+
if (experimentsManager.InstallDotnetSdks)
|
15
|
+
{
|
16
|
+
// If using the SDK specified by a `global.json` file, these environment variables need to be unset to
|
17
|
+
// allow the new process to discover the correct MSBuild binaries to load, and not load the ones that
|
18
|
+
// this process is using.
|
19
|
+
environmentVariablesToUnset.Add("MSBuildExtensionsPath");
|
20
|
+
environmentVariablesToUnset.Add("MSBuildLoadMicrosoftTargetsReadOnly");
|
21
|
+
environmentVariablesToUnset.Add("MSBUILDLOGIMPORTS");
|
22
|
+
environmentVariablesToUnset.Add("MSBuildSDKsPath");
|
23
|
+
environmentVariablesToUnset.Add("MSBUILDTARGETOUTPUTLOGGING");
|
24
|
+
environmentVariablesToUnset.Add("MSBUILD_EXE_PATH");
|
25
|
+
}
|
26
|
+
|
27
|
+
var environmentVariableOverrides = environmentVariablesToUnset.Select(name => (name, (string?)null));
|
28
|
+
return RunAsync("dotnet",
|
29
|
+
arguments,
|
30
|
+
workingDirectory,
|
31
|
+
environmentVariableOverrides
|
32
|
+
);
|
33
|
+
}
|
34
|
+
|
35
|
+
public static Task<(int ExitCode, string Output, string Error)> RunAsync(
|
36
|
+
string fileName,
|
37
|
+
IEnumerable<string>? arguments = null,
|
38
|
+
string? workingDirectory = null,
|
39
|
+
IEnumerable<(string Name, string? Value)>? environmentVariableOverrides = null
|
40
|
+
)
|
9
41
|
{
|
10
42
|
var tcs = new TaskCompletionSource<(int, string, string)>();
|
11
43
|
|
12
44
|
var redirectInitiated = new ManualResetEventSlim();
|
45
|
+
var psi = new ProcessStartInfo(fileName, arguments ?? [])
|
46
|
+
{
|
47
|
+
UseShellExecute = false, // required to redirect output and set environment variables
|
48
|
+
RedirectStandardOutput = true,
|
49
|
+
RedirectStandardError = true,
|
50
|
+
};
|
51
|
+
foreach (var (name, value) in environmentVariableOverrides ?? [])
|
52
|
+
{
|
53
|
+
psi.EnvironmentVariables[name] = value;
|
54
|
+
}
|
55
|
+
|
13
56
|
var process = new Process
|
14
57
|
{
|
15
|
-
StartInfo =
|
16
|
-
{
|
17
|
-
UseShellExecute = false, // required to redirect output
|
18
|
-
RedirectStandardOutput = true,
|
19
|
-
RedirectStandardError = true,
|
20
|
-
},
|
58
|
+
StartInfo = psi,
|
21
59
|
EnableRaisingEvents = true
|
22
60
|
};
|
23
61
|
|
@@ -77,11 +77,11 @@ internal static class ProjectHelper
|
|
77
77
|
var itemPath = projectRootElement.Items
|
78
78
|
.Where(i => i.ElementName.Equals("None", StringComparison.OrdinalIgnoreCase) ||
|
79
79
|
i.ElementName.Equals("Content", StringComparison.OrdinalIgnoreCase))
|
80
|
-
.Where(i =>
|
81
|
-
.Select(i => Path.GetFullPath(Path.Combine(projectDirectory, i.Include)))
|
80
|
+
.Where(i => !string.IsNullOrEmpty(i.Include))
|
81
|
+
.Select(i => Path.GetFullPath(Path.Combine(projectDirectory, i.Include.NormalizePathToUnix())))
|
82
|
+
.Where(p => Path.GetFileName(p).Equals(itemFileName, StringComparison.OrdinalIgnoreCase))
|
82
83
|
.Where(File.Exists)
|
83
|
-
.FirstOrDefault()
|
84
|
-
?.NormalizePathToUnix();
|
84
|
+
.FirstOrDefault();
|
85
85
|
return itemPath;
|
86
86
|
}
|
87
87
|
|
@@ -95,6 +95,65 @@ public class CloneWorkerTests
|
|
95
95
|
);
|
96
96
|
}
|
97
97
|
|
98
|
+
[Fact]
|
99
|
+
public async Task JobFileParseErrorIsReported_InvalidJson()
|
100
|
+
{
|
101
|
+
// arrange
|
102
|
+
var testApiHandler = new TestApiHandler();
|
103
|
+
var testGitCommandHandler = new TestGitCommandHandler();
|
104
|
+
var cloneWorker = new CloneWorker("JOB-ID", testApiHandler, testGitCommandHandler);
|
105
|
+
using var testDirectory = new TemporaryDirectory();
|
106
|
+
var jobFilePath = Path.Combine(testDirectory.DirectoryPath, "job.json");
|
107
|
+
await File.WriteAllTextAsync(jobFilePath, "not json");
|
108
|
+
|
109
|
+
// act
|
110
|
+
var result = await cloneWorker.RunAsync(new FileInfo(jobFilePath), new DirectoryInfo(testDirectory.DirectoryPath));
|
111
|
+
|
112
|
+
// assert
|
113
|
+
Assert.Equal(1, result);
|
114
|
+
var expectedParseErrorObject = testApiHandler.ReceivedMessages.Single(m => m.Type == typeof(UnknownError));
|
115
|
+
var unknownError = (UnknownError)expectedParseErrorObject.Object;
|
116
|
+
Assert.Equal("JsonException", unknownError.Details["error-class"]);
|
117
|
+
}
|
118
|
+
|
119
|
+
[Fact]
|
120
|
+
public async Task JobFileParseErrorIsReported_BadRequirement()
|
121
|
+
{
|
122
|
+
// arrange
|
123
|
+
var testApiHandler = new TestApiHandler();
|
124
|
+
var testGitCommandHandler = new TestGitCommandHandler();
|
125
|
+
var cloneWorker = new CloneWorker("JOB-ID", testApiHandler, testGitCommandHandler);
|
126
|
+
using var testDirectory = new TemporaryDirectory();
|
127
|
+
var jobFilePath = Path.Combine(testDirectory.DirectoryPath, "job.json");
|
128
|
+
|
129
|
+
// write a job file with a valid shape, but invalid requirement
|
130
|
+
await File.WriteAllTextAsync(jobFilePath, """
|
131
|
+
{
|
132
|
+
"job": {
|
133
|
+
"source": {
|
134
|
+
"provider": "github",
|
135
|
+
"repo": "test/repo"
|
136
|
+
},
|
137
|
+
"security-advisories": [
|
138
|
+
{
|
139
|
+
"dependency-name": "Some.Dependency",
|
140
|
+
"affected-versions": ["not a valid requirement"]
|
141
|
+
}
|
142
|
+
]
|
143
|
+
}
|
144
|
+
}
|
145
|
+
""");
|
146
|
+
|
147
|
+
// act
|
148
|
+
var result = await cloneWorker.RunAsync(new FileInfo(jobFilePath), new DirectoryInfo(testDirectory.DirectoryPath));
|
149
|
+
|
150
|
+
// assert
|
151
|
+
Assert.Equal(1, result);
|
152
|
+
var expectedParseErrorObject = testApiHandler.ReceivedMessages.Single(m => m.Type == typeof(BadRequirement));
|
153
|
+
var badRequirement = (BadRequirement)expectedParseErrorObject.Object;
|
154
|
+
Assert.Equal("not a valid requirement", badRequirement.Details["message"]);
|
155
|
+
}
|
156
|
+
|
98
157
|
private class TestGitCommandHandlerWithOutputs : TestGitCommandHandler
|
99
158
|
{
|
100
159
|
private readonly string _stdout;
|
@@ -134,8 +193,7 @@ public class CloneWorkerTests
|
|
134
193
|
// arrange
|
135
194
|
var testApiHandler = new TestApiHandler();
|
136
195
|
testGitCommandHandler ??= new TestGitCommandHandler();
|
137
|
-
var
|
138
|
-
var worker = new CloneWorker(testApiHandler, testGitCommandHandler, testLogger);
|
196
|
+
var worker = new CloneWorker("TEST-JOB-ID", testApiHandler, testGitCommandHandler);
|
139
197
|
|
140
198
|
// act
|
141
199
|
var job = new Job()
|
@@ -45,7 +45,16 @@ public class DiscoveryWorkerTestBase : TestBase
|
|
45
45
|
ValidateProjectResults(expectedResult.Projects, actualResult.Projects, experimentsManager);
|
46
46
|
Assert.Equal(expectedResult.ExpectedProjectCount ?? expectedResult.Projects.Length, actualResult.Projects.Length);
|
47
47
|
Assert.Equal(expectedResult.ErrorType, actualResult.ErrorType);
|
48
|
-
|
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
58
|
|
50
59
|
return;
|
51
60
|
|
data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.PackagesConfig.cs
CHANGED
@@ -115,5 +115,61 @@ public partial class DiscoveryWorkerTests
|
|
115
115
|
}
|
116
116
|
);
|
117
117
|
}
|
118
|
+
|
119
|
+
[Theory]
|
120
|
+
[InlineData(true)]
|
121
|
+
[InlineData(false)]
|
122
|
+
public async Task DiscoveryIsMergedWithPackageReferences(bool useDirectDiscovery)
|
123
|
+
{
|
124
|
+
await TestDiscoveryAsync(
|
125
|
+
experimentsManager: new ExperimentsManager() { UseDirectDiscovery = useDirectDiscovery },
|
126
|
+
packages:
|
127
|
+
[
|
128
|
+
MockNuGetPackage.CreateSimplePackage("Package.A", "1.0.0", "net46"),
|
129
|
+
MockNuGetPackage.CreateSimplePackage("Package.B", "2.0.0", "net46"),
|
130
|
+
],
|
131
|
+
workspacePath: "src",
|
132
|
+
files: [
|
133
|
+
("src/myproj.csproj", """
|
134
|
+
<Project Sdk="Microsoft.NET.Sdk">
|
135
|
+
<PropertyGroup>
|
136
|
+
<TargetFramework>net46</TargetFramework>
|
137
|
+
</PropertyGroup>
|
138
|
+
<ItemGroup>
|
139
|
+
<None Include="..\unexpected-directory\packages.config" />
|
140
|
+
<PackageReference Include="Package.B" Version="2.0.0" />
|
141
|
+
</ItemGroup>
|
142
|
+
</Project>
|
143
|
+
"""),
|
144
|
+
("unexpected-directory/packages.config", """
|
145
|
+
<?xml version="1.0" encoding="utf-8"?>
|
146
|
+
<packages>
|
147
|
+
<package id="Package.A" version="1.0.0" targetFramework="net46" />
|
148
|
+
</packages>
|
149
|
+
"""),
|
150
|
+
],
|
151
|
+
expectedResult: new()
|
152
|
+
{
|
153
|
+
Path = "src",
|
154
|
+
Projects = [
|
155
|
+
new()
|
156
|
+
{
|
157
|
+
FilePath = "myproj.csproj",
|
158
|
+
Properties = [new("TargetFramework", "net46", "src/myproj.csproj")],
|
159
|
+
TargetFrameworks = ["net46"],
|
160
|
+
Dependencies = [
|
161
|
+
new("Package.A", "1.0.0", DependencyType.PackagesConfig, TargetFrameworks: ["net46"]),
|
162
|
+
new("Package.B", "2.0.0", DependencyType.PackageReference, IsDirect: true, TargetFrameworks: ["net46"]),
|
163
|
+
],
|
164
|
+
ReferencedProjectPaths = [],
|
165
|
+
ImportedFiles = [],
|
166
|
+
AdditionalFiles = [
|
167
|
+
"../unexpected-directory/packages.config"
|
168
|
+
],
|
169
|
+
}
|
170
|
+
],
|
171
|
+
}
|
172
|
+
);
|
173
|
+
}
|
118
174
|
}
|
119
175
|
}
|
@@ -1094,6 +1094,47 @@ public partial class DiscoveryWorkerTests : DiscoveryWorkerTestBase
|
|
1094
1094
|
);
|
1095
1095
|
}
|
1096
1096
|
|
1097
|
+
[Theory]
|
1098
|
+
[InlineData(true)]
|
1099
|
+
[InlineData(false)]
|
1100
|
+
public async Task DiscoveryReportsDependencyFileNotParseable(bool useDirectDiscovery)
|
1101
|
+
{
|
1102
|
+
var experimentsManager = new ExperimentsManager() { UseDirectDiscovery = useDirectDiscovery };
|
1103
|
+
await TestDiscoveryAsync(
|
1104
|
+
experimentsManager: experimentsManager,
|
1105
|
+
workspacePath: "",
|
1106
|
+
files:
|
1107
|
+
[
|
1108
|
+
("project.csproj", """
|
1109
|
+
<Project Sdk="Microsoft.NET.Sdk">
|
1110
|
+
<PropertyGroup>
|
1111
|
+
<TargetFramework>net8.0</TargetFramework>
|
1112
|
+
</PropertyGroup>
|
1113
|
+
<ItemGroup>
|
1114
|
+
<PackageReference Include="Some.Package" Version="1.2.3" />
|
1115
|
+
</ItemGroup>
|
1116
|
+
</Project>
|
1117
|
+
"""),
|
1118
|
+
("project2.csproj", """
|
1119
|
+
<Project Sdk="Microsoft.NET.Sdk">
|
1120
|
+
<PropertyGroup>
|
1121
|
+
<TargetFramework>net8.0</TargetFramework>
|
1122
|
+
</PropertyGroup>
|
1123
|
+
<ItemGroup>
|
1124
|
+
<PackageReference: Include="Some.Package2" Version="1.2.3" />
|
1125
|
+
</ItemGroup>
|
1126
|
+
</Project>
|
1127
|
+
"""),
|
1128
|
+
],
|
1129
|
+
expectedResult: new()
|
1130
|
+
{
|
1131
|
+
Path = "",
|
1132
|
+
Projects = [],
|
1133
|
+
ErrorType = ErrorType.DependencyFileNotParseable,
|
1134
|
+
ErrorDetails = "project2.csproj",
|
1135
|
+
});
|
1136
|
+
}
|
1137
|
+
|
1097
1138
|
[Fact]
|
1098
1139
|
public async Task ResultFileHasCorrectShapeForAuthenticationFailure()
|
1099
1140
|
{
|
@@ -12,6 +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? ErrorDetailsPattern { get; init; } = null;
|
15
16
|
}
|
16
17
|
|
17
18
|
public record ExpectedSdkProjectDiscoveryResult : ExpectedDependencyDiscoveryResult
|
@@ -21,6 +22,7 @@ public record ExpectedSdkProjectDiscoveryResult : ExpectedDependencyDiscoveryRes
|
|
21
22
|
public required ImmutableArray<string> ReferencedProjectPaths { get; init; }
|
22
23
|
public required ImmutableArray<string> ImportedFiles { get; init; }
|
23
24
|
public required ImmutableArray<string> AdditionalFiles { get; init; }
|
25
|
+
public string? ErrorDetails { get; init; }
|
24
26
|
}
|
25
27
|
|
26
28
|
public record ExpectedDependencyDiscoveryResult : IDiscoveryResultWithDependencies
|
@@ -488,7 +488,7 @@ public class SdkProjectDiscoveryTests : DiscoveryWorkerTestBase
|
|
488
488
|
var logger = new TestLogger();
|
489
489
|
var fullProjectPath = Path.Combine(testDirectory.DirectoryPath, projectPath);
|
490
490
|
var experimentsManager = new ExperimentsManager() { UseDirectDiscovery = true }; // the following method is direct discovery; this just makes the call to Validate... happy
|
491
|
-
var projectDiscovery = await SdkProjectDiscovery.DiscoverWithBinLogAsync(testDirectory.DirectoryPath, Path.GetDirectoryName(fullProjectPath)!, fullProjectPath, logger);
|
491
|
+
var projectDiscovery = await SdkProjectDiscovery.DiscoverWithBinLogAsync(testDirectory.DirectoryPath, Path.GetDirectoryName(fullProjectPath)!, fullProjectPath, experimentsManager, logger);
|
492
492
|
ValidateProjectResults(expectedProjects, projectDiscovery, experimentsManager);
|
493
493
|
}
|
494
494
|
}
|
@@ -318,7 +318,8 @@ namespace NuGetUpdater.Core.Test
|
|
318
318
|
</Project>
|
319
319
|
"""
|
320
320
|
);
|
321
|
-
var
|
321
|
+
var experimentsManager = new ExperimentsManager();
|
322
|
+
var (exitCode, stdout, stderr) = ProcessEx.RunDotnetWithoutMSBuildEnvironmentVariablesAsync(["msbuild", projectPath, "/t:_ReportCurrentSdkVersion"], projectDir.FullName, experimentsManager).Result;
|
322
323
|
if (exitCode != 0)
|
323
324
|
{
|
324
325
|
throw new Exception($"Failed to report the current SDK version:\n{stdout}\n{stderr}");
|
@@ -1733,7 +1733,7 @@ public class RunWorkerTests
|
|
1733
1733
|
analyzeWorker ??= new AnalyzeWorker(experimentsManager, logger);
|
1734
1734
|
updaterWorker ??= new UpdaterWorker(experimentsManager, logger);
|
1735
1735
|
|
1736
|
-
var worker = new RunWorker(testApiHandler, discoveryWorker, analyzeWorker, updaterWorker, logger);
|
1736
|
+
var worker = new RunWorker("TEST-JOB-ID", testApiHandler, discoveryWorker, analyzeWorker, updaterWorker, logger);
|
1737
1737
|
var repoContentsPathDirectoryInfo = new DirectoryInfo(tempDirectory.DirectoryPath);
|
1738
1738
|
var actualResult = await worker.RunAsync(job, repoContentsPathDirectoryInfo, "TEST-COMMIT-SHA");
|
1739
1739
|
var actualApiMessages = testApiHandler.ReceivedMessages.ToArray();
|