dependabot-nuget 0.291.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.Core/Analyze/AnalyzeWorker.cs +11 -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 +67 -12
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ErrorType.cs +1 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ExperimentsManager.cs +28 -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 +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 +8 -3
- 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/ExpectedDiscoveryResults.cs +1 -0
- 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 +38 -20
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/ProjectHelperTests.cs +65 -0
- data/helpers/lib/NuGetUpdater/global.json +1 -1
- data/lib/dependabot/nuget/language.rb +21 -5
- data/lib/dependabot/nuget/native_helpers.rb +2 -0
- data/lib/dependabot/nuget/package_manager.rb +4 -4
- metadata +10 -6
@@ -12,6 +12,7 @@ namespace NuGetUpdater.Core.Run;
|
|
12
12
|
|
13
13
|
public class RunWorker
|
14
14
|
{
|
15
|
+
private readonly string _jobId;
|
15
16
|
private readonly IApiHandler _apiHandler;
|
16
17
|
private readonly ILogger _logger;
|
17
18
|
private readonly IDiscoveryWorker _discoveryWorker;
|
@@ -25,8 +26,9 @@ public class RunWorker
|
|
25
26
|
Converters = { new JsonStringEnumConverter(), new RequirementConverter(), new VersionConverter() },
|
26
27
|
};
|
27
28
|
|
28
|
-
public RunWorker(IApiHandler apiHandler, IDiscoveryWorker discoverWorker, IAnalyzeWorker analyzeWorker, IUpdaterWorker updateWorker, ILogger logger)
|
29
|
+
public RunWorker(string jobId, IApiHandler apiHandler, IDiscoveryWorker discoverWorker, IAnalyzeWorker analyzeWorker, IUpdaterWorker updateWorker, ILogger logger)
|
29
30
|
{
|
31
|
+
_jobId = jobId;
|
30
32
|
_apiHandler = apiHandler;
|
31
33
|
_logger = logger;
|
32
34
|
_discoveryWorker = discoverWorker;
|
@@ -87,9 +89,13 @@ public class RunWorker
|
|
87
89
|
{
|
88
90
|
error = new PrivateSourceAuthenticationFailure(lastUsedPackageSourceUrls);
|
89
91
|
}
|
92
|
+
catch (BadRequirementException ex)
|
93
|
+
{
|
94
|
+
error = new BadRequirement(ex.Message);
|
95
|
+
}
|
90
96
|
catch (MissingFileException ex)
|
91
97
|
{
|
92
|
-
error = new DependencyFileNotFound(ex.FilePath);
|
98
|
+
error = new DependencyFileNotFound("file not found", ex.FilePath);
|
93
99
|
}
|
94
100
|
catch (UpdateNotPossibleException ex)
|
95
101
|
{
|
@@ -97,7 +103,7 @@ public class RunWorker
|
|
97
103
|
}
|
98
104
|
catch (Exception ex)
|
99
105
|
{
|
100
|
-
error = new UnknownError(ex
|
106
|
+
error = new UnknownError(ex, _jobId);
|
101
107
|
}
|
102
108
|
|
103
109
|
if (error is not null)
|
@@ -11,7 +11,7 @@ internal static class LockFileUpdater
|
|
11
11
|
var projectDirectory = Path.GetDirectoryName(projectPath)!;
|
12
12
|
await MSBuildHelper.HandleGlobalJsonAsync(projectDirectory, repoRootPath, experimentsManager, async () =>
|
13
13
|
{
|
14
|
-
var (exitCode, stdout, stderr) = await ProcessEx.RunDotnetWithoutMSBuildEnvironmentVariablesAsync(["restore", "--force-evaluate", projectPath], projectDirectory, experimentsManager);
|
14
|
+
var (exitCode, stdout, stderr) = await ProcessEx.RunDotnetWithoutMSBuildEnvironmentVariablesAsync(["restore", "--force-evaluate", "-p:EnableWindowsTargeting=true", projectPath], projectDirectory, experimentsManager);
|
15
15
|
if (exitCode != 0)
|
16
16
|
{
|
17
17
|
logger.Error($" Lock file update failed.\nSTDOUT:\n{stdout}\nSTDERR:\n{stderr}");
|
data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/WebApplicationTargetsConditionPatcher.cs
CHANGED
@@ -13,7 +13,18 @@ namespace NuGetUpdater.Core.Updater
|
|
13
13
|
getContent: () => File.ReadAllText(projectFilePath),
|
14
14
|
setContent: s => File.WriteAllText(projectFilePath, s),
|
15
15
|
nodeFinder: doc => doc.Descendants()
|
16
|
-
.
|
16
|
+
.Where(e => e.Name == "Import")
|
17
|
+
.FirstOrDefault(e =>
|
18
|
+
{
|
19
|
+
var projectPath = e.GetAttributeValue("Project");
|
20
|
+
if (projectPath is not null)
|
21
|
+
{
|
22
|
+
var projectFileName = Path.GetFileName(projectPath.NormalizePathToUnix());
|
23
|
+
return projectFileName.Equals("Microsoft.WebApplication.targets", StringComparison.OrdinalIgnoreCase);
|
24
|
+
}
|
25
|
+
|
26
|
+
return false;
|
27
|
+
})
|
17
28
|
as XmlNodeSyntax,
|
18
29
|
preProcessor: n =>
|
19
30
|
{
|
@@ -395,7 +395,6 @@ public class PackageManager
|
|
395
395
|
if (await AreAllParentsCompatibleAsync(existingPackages, existingPackage, targetFramework, projectDirectory, logger) == true)
|
396
396
|
{
|
397
397
|
existingPackage.CurrentVersion = dependencyOldVersion;
|
398
|
-
string NewVersion = dependency.CurrentVersion;
|
399
398
|
existingPackage.NewVersion = dependency.CurrentVersion;
|
400
399
|
await UpdateVersion(existingPackages, existingPackage, targetFramework, projectDirectory, logger);
|
401
400
|
}
|
@@ -593,12 +592,6 @@ public class PackageManager
|
|
593
592
|
return null;
|
594
593
|
}
|
595
594
|
|
596
|
-
// If the current version of the parent is less than the current version of the dependency
|
597
|
-
else if (CurrentVersion < currentVersionDependency)
|
598
|
-
{
|
599
|
-
return currentVersionDependency;
|
600
|
-
}
|
601
|
-
|
602
595
|
// Loop from the current version to the latest version, use next patch as a limit (unless there's a limit) so it doesn't look for versions that don't exist
|
603
596
|
for (NuGetVersion version = CurrentVersion; version <= latestVersion; version = NextPatch(version, versions))
|
604
597
|
{
|
@@ -886,6 +886,7 @@ internal static partial class MSBuildHelper
|
|
886
886
|
"The plugin credential provider could not acquire credentials",
|
887
887
|
"401 (Unauthorized)",
|
888
888
|
"error NU1301: Unable to load the service index for source",
|
889
|
+
"Response status code does not indicate success: 403",
|
889
890
|
};
|
890
891
|
if (unauthorizedMessageSnippets.Any(stdout.Contains))
|
891
892
|
{
|
@@ -895,9 +896,13 @@ internal static partial class MSBuildHelper
|
|
895
896
|
|
896
897
|
internal static string? GetMissingFile(string output)
|
897
898
|
{
|
898
|
-
var
|
899
|
-
|
900
|
-
|
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)
|
901
906
|
{
|
902
907
|
return match.Groups["FilePath"].Value;
|
903
908
|
}
|
@@ -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
|
}
|
@@ -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
|
@@ -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();
|
@@ -1,6 +1,5 @@
|
|
1
1
|
using NuGet.Versioning;
|
2
2
|
|
3
|
-
using NuGetUpdater.Core.Analyze;
|
4
3
|
using NuGetUpdater.Core.Run;
|
5
4
|
using NuGetUpdater.Core.Run.ApiModel;
|
6
5
|
using NuGetUpdater.Core.Test.Utilities;
|
@@ -228,37 +227,33 @@ public class SerializationTests
|
|
228
227
|
Assert.False(experimentsManager.UseDirectDiscovery);
|
229
228
|
}
|
230
229
|
|
231
|
-
[
|
232
|
-
|
230
|
+
[Theory]
|
231
|
+
[MemberData(nameof(DeserializeErrorTypesData))]
|
232
|
+
public void SerializeError(JobErrorBase error, string expectedSerialization)
|
233
233
|
{
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
"this-is-not-a-job-and-parsing-will-fail-but-an-empty-experiment-set-should-sill-be-returned": {
|
240
|
-
}
|
241
|
-
}
|
242
|
-
""";
|
243
|
-
await File.WriteAllTextAsync(jobFilePath, jobContent);
|
244
|
-
var capturingTestLogger = new CapturingTestLogger();
|
245
|
-
|
246
|
-
// act - this is the entrypoint the update command uses to parse the job file
|
247
|
-
var experimentsManager = await ExperimentsManager.FromJobFileAsync(jobFilePath, capturingTestLogger);
|
234
|
+
if (error is UnknownError unknown)
|
235
|
+
{
|
236
|
+
// special case the exception's call stack to make it testable
|
237
|
+
unknown.Details["error-backtrace"] = "TEST-BACKTRACE";
|
238
|
+
}
|
248
239
|
|
249
|
-
|
250
|
-
Assert.
|
251
|
-
Assert.False(experimentsManager.UseDirectDiscovery);
|
252
|
-
Assert.Single(capturingTestLogger.Messages, m => m.Contains("Error deserializing job file"));
|
240
|
+
var actual = HttpApiHandler.Serialize(error);
|
241
|
+
Assert.Equal(expectedSerialization, actual);
|
253
242
|
}
|
254
243
|
|
255
244
|
[Fact]
|
256
|
-
public void
|
245
|
+
public void SerializeError_AllErrorTypesHaveSerializationTests()
|
257
246
|
{
|
258
|
-
var
|
259
|
-
|
260
|
-
|
261
|
-
|
247
|
+
var untestedTypes = typeof(JobErrorBase).Assembly.GetTypes()
|
248
|
+
.Where(t => t.IsSubclassOf(typeof(JobErrorBase)))
|
249
|
+
.ToHashSet();
|
250
|
+
foreach (object?[] data in DeserializeErrorTypesData())
|
251
|
+
{
|
252
|
+
var testedErrorType = data[0]!.GetType();
|
253
|
+
untestedTypes.Remove(testedErrorType);
|
254
|
+
}
|
255
|
+
|
256
|
+
Assert.Empty(untestedTypes.Select(t => t.Name));
|
262
257
|
}
|
263
258
|
|
264
259
|
[Fact]
|
@@ -503,7 +498,9 @@ public class SerializationTests
|
|
503
498
|
"repo": "some/repo"
|
504
499
|
},
|
505
500
|
"commit-message-options": {
|
506
|
-
"prefix": "[SECURITY] "
|
501
|
+
"prefix": "[SECURITY] ",
|
502
|
+
"prefix-development": null,
|
503
|
+
"include-scope": true
|
507
504
|
}
|
508
505
|
}
|
509
506
|
}
|
@@ -511,7 +508,58 @@ public class SerializationTests
|
|
511
508
|
var jobWrapper = RunWorker.Deserialize(jsonWrapperJson)!;
|
512
509
|
Assert.Equal("[SECURITY] ", jobWrapper.Job.CommitMessageOptions!.Prefix);
|
513
510
|
Assert.Null(jobWrapper.Job.CommitMessageOptions!.PrefixDevelopment);
|
514
|
-
Assert.
|
511
|
+
Assert.True(jobWrapper.Job.CommitMessageOptions!.IncludeScope);
|
512
|
+
}
|
513
|
+
|
514
|
+
public static IEnumerable<object?[]> DeserializeErrorTypesData()
|
515
|
+
{
|
516
|
+
yield return
|
517
|
+
[
|
518
|
+
new BadRequirement("some message"),
|
519
|
+
"""
|
520
|
+
{"data":{"error-type":"illformed_requirement","error-details":{"message":"some message"}}}
|
521
|
+
"""
|
522
|
+
];
|
523
|
+
|
524
|
+
yield return
|
525
|
+
[
|
526
|
+
new DependencyFileNotFound("some message", "/some/file"),
|
527
|
+
"""
|
528
|
+
{"data":{"error-type":"dependency_file_not_found","error-details":{"message":"some message","file-path":"/some/file"}}}
|
529
|
+
"""
|
530
|
+
];
|
531
|
+
|
532
|
+
yield return
|
533
|
+
[
|
534
|
+
new JobRepoNotFound("some message"),
|
535
|
+
"""
|
536
|
+
{"data":{"error-type":"job_repo_not_found","error-details":{"message":"some message"}}}
|
537
|
+
"""
|
538
|
+
];
|
539
|
+
|
540
|
+
yield return
|
541
|
+
[
|
542
|
+
new PrivateSourceAuthenticationFailure(["url1", "url2"]),
|
543
|
+
"""
|
544
|
+
{"data":{"error-type":"private_source_authentication_failure","error-details":{"source":"(url1|url2)"}}}
|
545
|
+
"""
|
546
|
+
];
|
547
|
+
|
548
|
+
yield return
|
549
|
+
[
|
550
|
+
new UnknownError(new Exception("some message"), "JOB-ID"),
|
551
|
+
"""
|
552
|
+
{"data":{"error-type":"unknown_error","error-details":{"error-class":"Exception","error-message":"some message","error-backtrace":"TEST-BACKTRACE","package-manager":"nuget","job-id":"JOB-ID"}}}
|
553
|
+
"""
|
554
|
+
];
|
555
|
+
|
556
|
+
yield return
|
557
|
+
[
|
558
|
+
new UpdateNotPossible(["dep1", "dep2"]),
|
559
|
+
"""
|
560
|
+
{"data":{"error-type":"update_not_possible","error-details":{"dependencies":["dep1","dep2"]}}}
|
561
|
+
"""
|
562
|
+
];
|
515
563
|
}
|
516
564
|
|
517
565
|
public static IEnumerable<object?[]> DeserializeAllowedUpdatesData()
|
@@ -596,16 +644,4 @@ public class SerializationTests
|
|
596
644
|
}
|
597
645
|
];
|
598
646
|
}
|
599
|
-
|
600
|
-
private class CapturingTestLogger : ILogger
|
601
|
-
{
|
602
|
-
private readonly List<string> _messages = new();
|
603
|
-
|
604
|
-
public IReadOnlyList<string> Messages => _messages;
|
605
|
-
|
606
|
-
public void LogRaw(string message)
|
607
|
-
{
|
608
|
-
_messages.Add(message);
|
609
|
-
}
|
610
|
-
}
|
611
647
|
}
|
@@ -47,7 +47,7 @@ public abstract class UpdateWorkerTestBase : TestBase
|
|
47
47
|
{
|
48
48
|
return useSolution
|
49
49
|
? TestUpdateForSolution(dependencyName, oldVersion, newVersion, projectFiles: [(projectFilePath, projectContents)], projectFilesExpected: [(projectFilePath, expectedProjectContents)], isTransitive, additionalFiles, additionalFilesExpected, packages, experimentsManager)
|
50
|
-
: TestUpdateForProject(dependencyName, oldVersion, newVersion, projectFile: (projectFilePath, projectContents), expectedProjectContents, isTransitive, additionalFiles, additionalFilesExpected, packages, experimentsManager);
|
50
|
+
: TestUpdateForProject(dependencyName, oldVersion, newVersion, projectFile: (projectFilePath, projectContents), expectedProjectContents, isTransitive, additionalFiles, additionalFilesExpected, additionalChecks: null, packages: packages, experimentsManager: experimentsManager);
|
51
51
|
}
|
52
52
|
|
53
53
|
protected static Task TestUpdate(
|
@@ -65,7 +65,7 @@ public abstract class UpdateWorkerTestBase : TestBase
|
|
65
65
|
{
|
66
66
|
return useSolution
|
67
67
|
? TestUpdateForSolution(dependencyName, oldVersion, newVersion, projectFiles: [projectFile], projectFilesExpected: [(projectFile.Path, expectedProjectContents)], isTransitive, additionalFiles, additionalFilesExpected, packages, experimentsManager)
|
68
|
-
: TestUpdateForProject(dependencyName, oldVersion, newVersion, projectFile, expectedProjectContents, isTransitive, additionalFiles, additionalFilesExpected, packages, experimentsManager);
|
68
|
+
: TestUpdateForProject(dependencyName, oldVersion, newVersion, projectFile, expectedProjectContents, isTransitive, additionalFiles, additionalFilesExpected, additionalChecks: null, packages: packages, experimentsManager: experimentsManager);
|
69
69
|
}
|
70
70
|
|
71
71
|
protected static Task TestNoChangeforProject(
|
@@ -101,6 +101,7 @@ public abstract class UpdateWorkerTestBase : TestBase
|
|
101
101
|
bool isTransitive = false,
|
102
102
|
TestFile[]? additionalFiles = null,
|
103
103
|
TestFile[]? additionalFilesExpected = null,
|
104
|
+
Action<string>? additionalChecks = null,
|
104
105
|
MockNuGetPackage[]? packages = null,
|
105
106
|
ExperimentsManager? experimentsManager = null,
|
106
107
|
string projectFilePath = "test-project.csproj",
|
@@ -114,6 +115,7 @@ public abstract class UpdateWorkerTestBase : TestBase
|
|
114
115
|
isTransitive,
|
115
116
|
additionalFiles,
|
116
117
|
additionalFilesExpected,
|
118
|
+
additionalChecks,
|
117
119
|
packages,
|
118
120
|
experimentsManager,
|
119
121
|
expectedResult);
|
@@ -127,6 +129,7 @@ public abstract class UpdateWorkerTestBase : TestBase
|
|
127
129
|
bool isTransitive = false,
|
128
130
|
TestFile[]? additionalFiles = null,
|
129
131
|
TestFile[]? additionalFilesExpected = null,
|
132
|
+
Action<string>? additionalChecks = null,
|
130
133
|
MockNuGetPackage[]? packages = null,
|
131
134
|
ExperimentsManager? experimentsManager = null,
|
132
135
|
ExpectedUpdateOperationResult? expectedResult = null)
|
@@ -156,6 +159,21 @@ public abstract class UpdateWorkerTestBase : TestBase
|
|
156
159
|
{
|
157
160
|
ValidateUpdateOperationResult(expectedResult, actualResult!);
|
158
161
|
}
|
162
|
+
else if ((actualResult.ErrorType ?? ErrorType.None) != ErrorType.None)
|
163
|
+
{
|
164
|
+
throw new Exception($"Result indicates failure: ErrorType={actualResult.ErrorType}, ErrorDetails={actualResult.ErrorDetails}");
|
165
|
+
}
|
166
|
+
|
167
|
+
if (additionalChecks is not null)
|
168
|
+
{
|
169
|
+
var sourcesDirectory = temporaryDirectory;
|
170
|
+
if (placeFilesInSrc)
|
171
|
+
{
|
172
|
+
sourcesDirectory = Path.Combine(temporaryDirectory, "src");
|
173
|
+
}
|
174
|
+
|
175
|
+
additionalChecks(sourcesDirectory);
|
176
|
+
}
|
159
177
|
});
|
160
178
|
|
161
179
|
var expectedResultFiles = additionalFilesExpected.Prepend((projectFilePath, expectedProjectContents)).ToArray();
|
@@ -69,10 +69,10 @@ public partial class UpdateWorkerTests
|
|
69
69
|
<PropertyGroup>
|
70
70
|
<TargetFramework>netstandard2.0</TargetFramework>
|
71
71
|
</PropertyGroup>
|
72
|
-
|
72
|
+
|
73
73
|
<ItemGroup>
|
74
74
|
<PackageReference Include="Some.Package" Version="13.0.3" />
|
75
|
-
</ItemGroup
|
75
|
+
</ItemGroup>
|
76
76
|
</Project>
|
77
77
|
""",
|
78
78
|
additionalFiles:
|