dependabot-nuget 0.292.0 → 0.294.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/helpers/lib/NuGetUpdater/.gitignore +1 -0
  3. data/helpers/lib/NuGetUpdater/Directory.Packages.props +2 -1
  4. data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/Correlator.cs +197 -0
  5. data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/DotNetPackageCorrelation.csproj +12 -0
  6. data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/Model/PackageMapper.cs +68 -0
  7. data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/Model/PackageSet.cs +11 -0
  8. data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/Model/Release.cs +25 -0
  9. data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/Model/ReleasesFile.cs +9 -0
  10. data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/Model/RuntimePackages.cs +11 -0
  11. data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/Model/Sdk.cs +13 -0
  12. data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/Model/SemVerComparer.cs +16 -0
  13. data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/Model/SemVersionConverter.cs +42 -0
  14. data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation.Cli/DotNetPackageCorrelation.Cli.csproj +16 -0
  15. data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation.Cli/Program.cs +32 -0
  16. data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation.Test/CorrelatorTests.cs +99 -0
  17. data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation.Test/DotNetPackageCorrelation.Test.csproj +18 -0
  18. data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation.Test/EndToEndTests.cs +30 -0
  19. data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation.Test/RuntimePackagesTests.cs +206 -0
  20. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/AnalyzeCommand.cs +6 -4
  21. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/DiscoverCommand.cs +8 -7
  22. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/RunCommand.cs +4 -4
  23. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/UpdateCommand.cs +17 -5
  24. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Analyze.cs +7 -1
  25. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Discover.cs +46 -6
  26. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Update.cs +8 -0
  27. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/AnalyzeWorker.cs +8 -17
  28. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/DependencyFinder.cs +4 -4
  29. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/Extensions.cs +1 -1
  30. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/VersionFinder.cs +16 -5
  31. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Clone/CloneWorker.cs +2 -1
  32. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/DependencyDiscovery.targets +2 -2
  33. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DiscoveryWorker.cs +7 -20
  34. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/ProjectDiscoveryResult.cs +3 -3
  35. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/SdkProjectDiscovery.cs +99 -2
  36. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/EnsureDotNetPackageCorrelation.targets +25 -0
  37. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ExperimentsManager.cs +9 -22
  38. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/PackagesConfigBuildFile.cs +5 -1
  39. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/MissingFileException.cs +2 -1
  40. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/NativeResult.cs +3 -3
  41. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/NuGetUpdater.Core.csproj +3 -0
  42. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/Advisory.cs +2 -0
  43. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/DependencyFileNotFound.cs +7 -3
  44. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/DependencyFileNotParseable.cs +15 -0
  45. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/JobErrorBase.cs +24 -0
  46. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/RunWorker.cs +33 -30
  47. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/UnparseableFileException.cs +12 -0
  48. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackageReferenceUpdater.cs +21 -0
  49. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdaterWorker.cs +6 -30
  50. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/DotNetPackageCorrelationManager.cs +46 -0
  51. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +51 -27
  52. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/NuGetHelper.cs +1 -1
  53. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTestBase.cs +15 -4
  54. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTests.cs +70 -9
  55. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTestBase.cs +20 -12
  56. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Project.cs +108 -0
  57. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs +16 -12
  58. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/ExpectedDiscoveryResults.cs +1 -1
  59. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/MockNuGetPackage.cs +15 -28
  60. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/MiscellaneousTests.cs +61 -0
  61. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/RunWorkerTests.cs +5 -4
  62. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/SerializationTests.cs +9 -1
  63. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TestBase.cs +24 -0
  64. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/ExpectedUpdateOperationResult.cs +1 -1
  65. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs +11 -15
  66. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.DirsProj.cs +1 -1
  67. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Mixed.cs +14 -8
  68. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackageReference.cs +148 -3
  69. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs +12 -14
  70. data/helpers/lib/NuGetUpdater/NuGetUpdater.sln +18 -1
  71. data/lib/dependabot/nuget/native_helpers.rb +41 -16
  72. metadata +25 -6
  73. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ErrorType.cs +0 -12
@@ -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
- ErrorType = ErrorType.DependencyFileNotParseable,
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
- ErrorType = ErrorType.AuthenticationFailure,
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
- // "ErrorType": "AuthenticationFailure",
1156
- // "ErrorDetails": "<some package feed>",
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 errorType = jsonDocument.RootElement.GetProperty("ErrorType");
1161
- var errorDetails = jsonDocument.RootElement.GetProperty("ErrorDetails");
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("AuthenticationFailure", errorType.GetString());
1164
- Assert.Equal("<some package feed>", errorDetails.GetString());
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
- ErrorType = ErrorType.AuthenticationFailure,
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? ErrorDetailsPattern { get; init; } = null;
15
+ public string? ErrorRegex { get; init; } = null;
16
16
  }
17
17
 
18
18
  public record ExpectedSdkProjectDiscoveryResult : ExpectedDependencyDiscoveryResult
@@ -388,6 +388,17 @@ namespace NuGetUpdater.Core.Test
388
388
  return WellKnownPackages[key];
389
389
  }
390
390
 
391
+ public static MockNuGetPackage GetMicrosoftNETCoreAppRefPackage(int majorRuntimeVersion)
392
+ {
393
+ return WellKnownReferencePackage("Microsoft.NETCore.App", $"net{majorRuntimeVersion}.0",
394
+ [
395
+ ("data/FrameworkList.xml", Encoding.UTF8.GetBytes($"""
396
+ <FileList TargetFrameworkIdentifier=".NETCoreApp" TargetFrameworkVersion="{majorRuntimeVersion}.0" FrameworkName="Microsoft.NETCore.App" Name=".NET Runtime">
397
+ </FileList>
398
+ """))
399
+ ]);
400
+ }
401
+
391
402
  public static MockNuGetPackage WellKnownHostPackage(string packageName, string targetFramework, (string Path, byte[] Content)[]? files = null)
392
403
  {
393
404
  string key = $"{packageName}/{targetFramework}";
@@ -437,34 +448,10 @@ namespace NuGetUpdater.Core.Test
437
448
  WellKnownReferencePackage("Microsoft.AspNetCore.App", "net7.0"),
438
449
  WellKnownReferencePackage("Microsoft.AspNetCore.App", "net8.0"),
439
450
  WellKnownReferencePackage("Microsoft.AspNetCore.App", "net9.0"),
440
- WellKnownReferencePackage("Microsoft.NETCore.App", "net6.0",
441
- [
442
- ("data/FrameworkList.xml", Encoding.UTF8.GetBytes("""
443
- <FileList TargetFrameworkIdentifier=".NETCoreApp" TargetFrameworkVersion="6.0" FrameworkName="Microsoft.NETCore.App" Name=".NET Runtime">
444
- </FileList>
445
- """))
446
- ]),
447
- WellKnownReferencePackage("Microsoft.NETCore.App", "net7.0",
448
- [
449
- ("data/FrameworkList.xml", Encoding.UTF8.GetBytes("""
450
- <FileList TargetFrameworkIdentifier=".NETCoreApp" TargetFrameworkVersion="7.0" FrameworkName="Microsoft.NETCore.App" Name=".NET Runtime">
451
- </FileList>
452
- """))
453
- ]),
454
- WellKnownReferencePackage("Microsoft.NETCore.App", "net8.0",
455
- [
456
- ("data/FrameworkList.xml", Encoding.UTF8.GetBytes("""
457
- <FileList TargetFrameworkIdentifier=".NETCoreApp" TargetFrameworkVersion="8.0" FrameworkName="Microsoft.NETCore.App" Name=".NET Runtime">
458
- </FileList>
459
- """))
460
- ]),
461
- WellKnownReferencePackage("Microsoft.NETCore.App", "net9.0",
462
- [
463
- ("data/FrameworkList.xml", Encoding.UTF8.GetBytes("""
464
- <FileList TargetFrameworkIdentifier=".NETCoreApp" TargetFrameworkVersion="9.0" FrameworkName="Microsoft.NETCore.App" Name=".NET Runtime">
465
- </FileList>
466
- """))
467
- ]),
451
+ GetMicrosoftNETCoreAppRefPackage(6),
452
+ GetMicrosoftNETCoreAppRefPackage(7),
453
+ GetMicrosoftNETCoreAppRefPackage(8),
454
+ GetMicrosoftNETCoreAppRefPackage(9),
468
455
  WellKnownReferencePackage("Microsoft.WindowsDesktop.App", "net6.0"),
469
456
  WellKnownReferencePackage("Microsoft.WindowsDesktop.App", "net7.0"),
470
457
  WellKnownReferencePackage("Microsoft.WindowsDesktop.App", "net8.0"),
@@ -1,3 +1,5 @@
1
+ using System.Text.Json;
2
+
1
3
  using NuGet.Versioning;
2
4
 
3
5
  using NuGetUpdater.Core.Analyze;
@@ -29,6 +31,16 @@ public class MiscellaneousTests
29
31
  Assert.Equal(expectedRequirementsStrings, actualRequirementsStrings);
30
32
  }
31
33
 
34
+ [Theory]
35
+ [MemberData(nameof(DependencyInfoFromJobData))]
36
+ public void DependencyInfoFromJob(Job job, Dependency dependency, DependencyInfo expectedDependencyInfo)
37
+ {
38
+ var actualDependencyInfo = RunWorker.GetDependencyInfo(job, dependency);
39
+ var expectedString = JsonSerializer.Serialize(expectedDependencyInfo, AnalyzeWorker.SerializerOptions);
40
+ var actualString = JsonSerializer.Serialize(actualDependencyInfo, AnalyzeWorker.SerializerOptions);
41
+ Assert.Equal(expectedString, actualString);
42
+ }
43
+
32
44
  public static IEnumerable<object?[]> RequirementsFromIgnoredVersionsData()
33
45
  {
34
46
  yield return
@@ -82,4 +94,53 @@ public class MiscellaneousTests
82
94
  }
83
95
  ];
84
96
  }
97
+
98
+ public static IEnumerable<object[]> DependencyInfoFromJobData()
99
+ {
100
+ yield return
101
+ [
102
+ // job
103
+ new Job()
104
+ {
105
+ Source = new()
106
+ {
107
+ Provider = "github",
108
+ Repo = "some/repo"
109
+ },
110
+ SecurityAdvisories = [
111
+ new()
112
+ {
113
+ DependencyName = "Some.Dependency",
114
+ AffectedVersions = [Requirement.Parse(">= 1.0.0, < 1.1.0")],
115
+ PatchedVersions = [Requirement.Parse("= 1.1.0")],
116
+ UnaffectedVersions = [Requirement.Parse("= 1.2.0")]
117
+ },
118
+ new()
119
+ {
120
+ DependencyName = "Unrelated.Dependency",
121
+ AffectedVersions = [Requirement.Parse(">= 1.0.0, < 99.99.99")]
122
+ }
123
+ ]
124
+ },
125
+ // dependency
126
+ new Dependency("Some.Dependency", "1.0.0", DependencyType.PackageReference),
127
+ // expectedDependencyInfo
128
+ new DependencyInfo()
129
+ {
130
+ Name = "Some.Dependency",
131
+ Version = "1.0.0",
132
+ IsVulnerable = true,
133
+ IgnoredVersions = [],
134
+ Vulnerabilities = [
135
+ new()
136
+ {
137
+ DependencyName = "Some.Dependency",
138
+ PackageManager = "nuget",
139
+ VulnerableVersions = [Requirement.Parse(">= 1.0.0, < 1.1.0")],
140
+ SafeVersions = [Requirement.Parse("= 1.1.0"), Requirement.Parse("= 1.2.0")],
141
+ }
142
+ ]
143
+ }
144
+ ];
145
+ }
85
146
  }
@@ -1729,11 +1729,12 @@ public class RunWorkerTests
1729
1729
  experimentsManager ??= new ExperimentsManager();
1730
1730
  var testApiHandler = new TestApiHandler();
1731
1731
  var logger = new TestLogger();
1732
- discoveryWorker ??= new DiscoveryWorker(experimentsManager, logger);
1733
- analyzeWorker ??= new AnalyzeWorker(experimentsManager, logger);
1734
- updaterWorker ??= new UpdaterWorker(experimentsManager, logger);
1732
+ var jobId = "TEST-JOB-ID";
1733
+ discoveryWorker ??= new DiscoveryWorker(jobId, experimentsManager, logger);
1734
+ analyzeWorker ??= new AnalyzeWorker(jobId, experimentsManager, logger);
1735
+ updaterWorker ??= new UpdaterWorker(jobId, experimentsManager, logger);
1735
1736
 
1736
- var worker = new RunWorker("TEST-JOB-ID", testApiHandler, discoveryWorker, analyzeWorker, updaterWorker, logger);
1737
+ var worker = new RunWorker(jobId, testApiHandler, discoveryWorker, analyzeWorker, updaterWorker, logger);
1737
1738
  var repoContentsPathDirectoryInfo = new DirectoryInfo(tempDirectory.DirectoryPath);
1738
1739
  var actualResult = await worker.RunAsync(job, repoContentsPathDirectoryInfo, "TEST-COMMIT-SHA");
1739
1740
  var actualApiMessages = testApiHandler.ReceivedMessages.ToArray();
@@ -523,12 +523,20 @@ public class SerializationTests
523
523
 
524
524
  yield return
525
525
  [
526
- new DependencyFileNotFound("some message", "/some/file"),
526
+ new DependencyFileNotFound("/some/file", "some message"),
527
527
  """
528
528
  {"data":{"error-type":"dependency_file_not_found","error-details":{"message":"some message","file-path":"/some/file"}}}
529
529
  """
530
530
  ];
531
531
 
532
+ yield return
533
+ [
534
+ new DependencyFileNotParseable("/some/file", "some message"),
535
+ """
536
+ {"data":{"error-type":"dependency_file_not_parseable","error-details":{"message":"some message","file-path":"/some/file"}}}
537
+ """
538
+ ];
539
+
532
540
  yield return
533
541
  [
534
542
  new JobRepoNotFound("some message"),
@@ -1,3 +1,10 @@
1
+ using System.Text.Json;
2
+
3
+ using NuGetUpdater.Core.Run.ApiModel;
4
+ using NuGetUpdater.Core.Run;
5
+
6
+ using Xunit;
7
+
1
8
  namespace NuGetUpdater.Core.Test
2
9
  {
3
10
  public abstract class TestBase
@@ -6,5 +13,22 @@ namespace NuGetUpdater.Core.Test
6
13
  {
7
14
  MSBuildHelper.RegisterMSBuild(Environment.CurrentDirectory, Environment.CurrentDirectory);
8
15
  }
16
+
17
+ protected static void ValidateError(JobErrorBase expected, JobErrorBase? actual)
18
+ {
19
+ var expectedErrorString = JsonSerializer.Serialize(expected, RunWorker.SerializerOptions);
20
+ var actualErrorString = actual is null
21
+ ? null
22
+ : JsonSerializer.Serialize(actual, RunWorker.SerializerOptions);
23
+ Assert.Equal(expectedErrorString, actualErrorString);
24
+ }
25
+
26
+ protected static void ValidateErrorRegex(string expectedErrorRegex, JobErrorBase? actual)
27
+ {
28
+ var actualErrorString = actual is null
29
+ ? null
30
+ : JsonSerializer.Serialize(actual, RunWorker.SerializerOptions);
31
+ Assert.Matches(expectedErrorRegex, actualErrorString);
32
+ }
9
33
  }
10
34
  }
@@ -4,5 +4,5 @@ namespace NuGetUpdater.Core.Test.Updater;
4
4
 
5
5
  public record ExpectedUpdateOperationResult : UpdateOperationResult
6
6
  {
7
- public string? ErrorDetailsRegex { get; init; } = null;
7
+ public string? ErrorRegex { get; init; } = null;
8
8
  }
@@ -152,17 +152,10 @@ public abstract class UpdateWorkerTestBase : TestBase
152
152
 
153
153
  // run update
154
154
  experimentsManager ??= new ExperimentsManager();
155
- var worker = new UpdaterWorker(experimentsManager, new TestLogger());
155
+ var worker = new UpdaterWorker("TEST-JOB-ID", experimentsManager, new TestLogger());
156
156
  var projectPath = placeFilesInSrc ? $"src/{projectFilePath}" : projectFilePath;
157
157
  var actualResult = await worker.RunWithErrorHandlingAsync(temporaryDirectory, projectPath, dependencyName, oldVersion, newVersion, isTransitive);
158
- if (expectedResult is { })
159
- {
160
- ValidateUpdateOperationResult(expectedResult, actualResult!);
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
- }
158
+ ValidateUpdateOperationResult(expectedResult, actualResult!);
166
159
 
167
160
  if (additionalChecks is not null)
168
161
  {
@@ -185,16 +178,19 @@ public abstract class UpdateWorkerTestBase : TestBase
185
178
  AssertContainsFiles(expectedResultFiles, actualResult);
186
179
  }
187
180
 
188
- protected static void ValidateUpdateOperationResult(ExpectedUpdateOperationResult expectedResult, UpdateOperationResult actualResult)
181
+ protected static void ValidateUpdateOperationResult(ExpectedUpdateOperationResult? expectedResult, UpdateOperationResult actualResult)
189
182
  {
190
- Assert.Equal(expectedResult.ErrorType, actualResult.ErrorType);
191
- if (expectedResult.ErrorDetailsRegex is not null && actualResult.ErrorDetails is string errorDetails)
183
+ if (expectedResult?.Error is not null)
184
+ {
185
+ ValidateError(expectedResult.Error, actualResult.Error);
186
+ }
187
+ else if (expectedResult?.ErrorRegex is not null)
192
188
  {
193
- Assert.Matches(expectedResult.ErrorDetailsRegex, errorDetails);
189
+ ValidateErrorRegex(expectedResult.ErrorRegex, actualResult.Error);
194
190
  }
195
191
  else
196
192
  {
197
- Assert.Equivalent(expectedResult.ErrorDetails, actualResult.ErrorDetails);
193
+ Assert.Null(actualResult.Error);
198
194
  }
199
195
  }
200
196
 
@@ -274,7 +270,7 @@ public abstract class UpdateWorkerTestBase : TestBase
274
270
 
275
271
  experimentsManager ??= new ExperimentsManager();
276
272
  var slnPath = Path.Combine(temporaryDirectory, slnName);
277
- var worker = new UpdaterWorker(experimentsManager, new TestLogger());
273
+ var worker = new UpdaterWorker("TEST-JOB-ID", experimentsManager, new TestLogger());
278
274
  await worker.RunAsync(temporaryDirectory, slnPath, dependencyName, oldVersion, newVersion, isTransitive);
279
275
  });
280
276
 
@@ -366,7 +366,7 @@ public partial class UpdateWorkerTests
366
366
 
367
367
  experimentsManager ??= new ExperimentsManager();
368
368
  var projectPath = Path.Combine(temporaryDirectory, projectFileName);
369
- var worker = new UpdaterWorker(experimentsManager, new TestLogger());
369
+ var worker = new UpdaterWorker("TEST-JOB-ID", experimentsManager, new TestLogger());
370
370
  await worker.RunAsync(temporaryDirectory, projectPath, dependencyName, oldVersion, newVersion, isTransitive);
371
371
  });
372
372
 
@@ -1,5 +1,6 @@
1
1
  using System.Text.Json;
2
2
 
3
+ using NuGetUpdater.Core.Run.ApiModel;
3
4
  using NuGetUpdater.Core.Updater;
4
5
 
5
6
  using Xunit;
@@ -16,8 +17,7 @@ public partial class UpdateWorkerTests
16
17
  using var temporaryDirectory = await TemporaryDirectory.CreateWithContentsAsync([]);
17
18
  var result = new UpdateOperationResult()
18
19
  {
19
- ErrorType = ErrorType.AuthenticationFailure,
20
- ErrorDetails = "<some package feed>",
20
+ Error = new PrivateSourceAuthenticationFailure(["<some package feed>"]),
21
21
  };
22
22
  var resultFilePath = Path.Combine(temporaryDirectory.DirectoryPath, "update-result.json");
23
23
  await UpdaterWorker.WriteResultFile(result, resultFilePath, new TestLogger());
@@ -26,16 +26,22 @@ public partial class UpdateWorkerTests
26
26
  // raw result file should look like this:
27
27
  // {
28
28
  // ...
29
- // "ErrorType": "AuthenticationFailure",
30
- // "ErrorDetails": "<some package feed>",
29
+ // "Error": {
30
+ // "error-type": "private_source_authentication_failure",
31
+ // "error-details": {
32
+ // "source": "<some package feed>"
33
+ // }
34
+ // }
31
35
  // ...
32
36
  // }
33
37
  var jsonDocument = JsonDocument.Parse(resultContent);
34
- var errorType = jsonDocument.RootElement.GetProperty("ErrorType");
35
- var errorDetails = jsonDocument.RootElement.GetProperty("ErrorDetails");
38
+ var error = jsonDocument.RootElement.GetProperty("Error");
39
+ var errorType = error.GetProperty("error-type");
40
+ var errorDetails = error.GetProperty("error-details");
41
+ var source = errorDetails.GetProperty("source");
36
42
 
37
- Assert.Equal("AuthenticationFailure", errorType.GetString());
38
- Assert.Equal("<some package feed>", errorDetails.GetString());
43
+ Assert.Equal("private_source_authentication_failure", errorType.GetString());
44
+ Assert.Equal("(<some package feed>)", source.GetString());
39
45
  }
40
46
 
41
47
  [Fact]
@@ -2,6 +2,7 @@ using System.Linq;
2
2
  using System.Text;
3
3
  using System.Text.Json;
4
4
 
5
+ using NuGetUpdater.Core.Run.ApiModel;
5
6
  using NuGetUpdater.Core.Updater;
6
7
 
7
8
  using Xunit;
@@ -571,7 +572,7 @@ public partial class UpdateWorkerTests
571
572
  //
572
573
  // do the update
573
574
  //
574
- UpdaterWorker worker = new(new ExperimentsManager(), new TestLogger());
575
+ UpdaterWorker worker = new("TEST-JOB-ID", new ExperimentsManager(), new TestLogger());
575
576
  await worker.RunAsync(tempDirectory.DirectoryPath, projectPath, "Some.Package", "1.0.0", "1.1.0", isTransitive: false);
576
577
 
577
578
  //
@@ -3482,10 +3483,154 @@ public partial class UpdateWorkerTests
3482
3483
  """,
3483
3484
  expectedResult: new()
3484
3485
  {
3485
- ErrorType = ErrorType.AuthenticationFailure,
3486
- ErrorDetails = $"({http.BaseUrl.TrimEnd('/')}/index.json)",
3486
+ Error = new PrivateSourceAuthenticationFailure([$"{http.BaseUrl.TrimEnd('/')}/index.json"]),
3487
3487
  }
3488
3488
  );
3489
3489
  }
3490
+
3491
+ [Fact]
3492
+ public async Task UpdateSdkManagedPackage_DirectDependency()
3493
+ {
3494
+ // To avoid a unit test that's tightly coupled to the installed SDK, several values are simulated,
3495
+ // including the runtime major version, the current Microsoft.NETCore.App.Ref package, and the package
3496
+ // correlation file. Doing this requires a temporary file and environment variable override.
3497
+ var runtimeMajorVersion = Environment.Version.Major;
3498
+ var netCoreAppRefPackage = MockNuGetPackage.GetMicrosoftNETCoreAppRefPackage(runtimeMajorVersion);
3499
+ using var tempDirectory = new TemporaryDirectory();
3500
+ var packageCorrelationFile = Path.Combine(tempDirectory.DirectoryPath, "dotnet-package-correlation.json");
3501
+ await File.WriteAllTextAsync(packageCorrelationFile, $$"""
3502
+ {
3503
+ "Runtimes": {
3504
+ "{{runtimeMajorVersion}}.0.0": {
3505
+ "Packages": {
3506
+ "{{netCoreAppRefPackage.Id}}": "{{netCoreAppRefPackage.Version}}",
3507
+ "System.Text.Json": "{{runtimeMajorVersion}}.0.98"
3508
+ }
3509
+ }
3510
+ }
3511
+ }
3512
+ """);
3513
+ using var tempEnvironment = new TemporaryEnvironment([("DOTNET_PACKAGE_CORRELATION_FILE_PATH", packageCorrelationFile)]);
3514
+
3515
+ // In the `packages` section below, we fake a `System.Text.Json` package with a low assembly version that
3516
+ // will always trigger the replacement so that can be detected and then the equivalent version is pulled
3517
+ // from the correlation file specified above. In the original project contents, package version `x.0.98`
3518
+ // is reported which makes the update to `x.0.99` always possible.
3519
+ await TestUpdateForProject("System.Text.Json", $"{runtimeMajorVersion}.0.98", $"{runtimeMajorVersion}.0.99",
3520
+ experimentsManager: new ExperimentsManager() { UseDirectDiscovery = true, InstallDotnetSdks = true },
3521
+ packages:
3522
+ [
3523
+ // this assembly version is lower than what the SDK will have
3524
+ MockNuGetPackage.CreatePackageWithAssembly("System.Text.Json", $"{runtimeMajorVersion}.0.0", $"net{runtimeMajorVersion}.0", assemblyVersion: $"{runtimeMajorVersion}.0.0.0"),
3525
+ // this assembly version is greater than what the SDK will have
3526
+ MockNuGetPackage.CreatePackageWithAssembly("System.Text.Json", $"{runtimeMajorVersion}.0.99", $"net{runtimeMajorVersion}.0", assemblyVersion: $"{runtimeMajorVersion}.99.99.99"),
3527
+ ],
3528
+ projectContents: $"""
3529
+ <Project Sdk="Microsoft.NET.Sdk">
3530
+ <PropertyGroup>
3531
+ <TargetFramework>net{runtimeMajorVersion}.0</TargetFramework>
3532
+ </PropertyGroup>
3533
+ <ItemGroup>
3534
+ <PackageReference Include="System.Text.Json" Version="{runtimeMajorVersion}.0.0" />
3535
+ </ItemGroup>
3536
+ </Project>
3537
+ """,
3538
+ additionalFiles: [
3539
+ ("global.json", $$"""
3540
+ {
3541
+ "sdk": {
3542
+ "version": "{{runtimeMajorVersion}}.0.100",
3543
+ "allowPrerelease": true,
3544
+ "rollForward": "latestMinor"
3545
+ }
3546
+ }
3547
+ """)
3548
+ ],
3549
+ expectedProjectContents: $"""
3550
+ <Project Sdk="Microsoft.NET.Sdk">
3551
+ <PropertyGroup>
3552
+ <TargetFramework>net{runtimeMajorVersion}.0</TargetFramework>
3553
+ </PropertyGroup>
3554
+ <ItemGroup>
3555
+ <PackageReference Include="System.Text.Json" Version="{runtimeMajorVersion}.0.99" />
3556
+ </ItemGroup>
3557
+ </Project>
3558
+ """
3559
+ );
3560
+ }
3561
+
3562
+ [Fact]
3563
+ public async Task UpdateSdkManagedPackage_TransitiveDependency()
3564
+ {
3565
+ // To avoid a unit test that's tightly coupled to the installed SDK, several values are simulated,
3566
+ // including the runtime major version, the current Microsoft.NETCore.App.Ref package, and the package
3567
+ // correlation file. Doing this requires a temporary file and environment variable override.
3568
+ var runtimeMajorVersion = Environment.Version.Major;
3569
+ var netCoreAppRefPackage = MockNuGetPackage.GetMicrosoftNETCoreAppRefPackage(runtimeMajorVersion);
3570
+ using var tempDirectory = new TemporaryDirectory();
3571
+ var packageCorrelationFile = Path.Combine(tempDirectory.DirectoryPath, "dotnet-package-correlation.json");
3572
+ await File.WriteAllTextAsync(packageCorrelationFile, $$"""
3573
+ {
3574
+ "Runtimes": {
3575
+ "{{runtimeMajorVersion}}.0.0": {
3576
+ "Packages": {
3577
+ "{{netCoreAppRefPackage.Id}}": "{{netCoreAppRefPackage.Version}}",
3578
+ "System.Text.Json": "{{runtimeMajorVersion}}.0.98"
3579
+ }
3580
+ }
3581
+ }
3582
+ }
3583
+ """);
3584
+ using var tempEnvironment = new TemporaryEnvironment([("DOTNET_PACKAGE_CORRELATION_FILE_PATH", packageCorrelationFile)]);
3585
+
3586
+ // In the `packages` section below, we fake a `System.Text.Json` package with a low assembly version that
3587
+ // will always trigger the replacement so that can be detected and then the equivalent version is pulled
3588
+ // from the correlation file specified above. In the original project contents, package version `x.0.98`
3589
+ // is reported which makes the update to `x.0.99` always possible.
3590
+ await TestUpdateForProject("System.Text.Json", $"{runtimeMajorVersion}.0.98", $"{runtimeMajorVersion}.0.99",
3591
+ isTransitive: true,
3592
+ experimentsManager: new ExperimentsManager() { UseDirectDiscovery = true, InstallDotnetSdks = true },
3593
+ packages:
3594
+ [
3595
+ MockNuGetPackage.CreateSimplePackage("Some.Package", "1.0.0", $"net{runtimeMajorVersion}.0", [(null, [("System.Text.Json", $"[{runtimeMajorVersion}.0.0]")])]),
3596
+ MockNuGetPackage.CreateSimplePackage("Some.Package", "2.0.0", $"net{runtimeMajorVersion}.0", [(null, [("System.Text.Json", $"[{runtimeMajorVersion}.0.99]")])]),
3597
+ // this assembly version is lower than what the SDK will have
3598
+ MockNuGetPackage.CreatePackageWithAssembly("System.Text.Json", $"{runtimeMajorVersion}.0.0", $"net{runtimeMajorVersion}.0", assemblyVersion: $"{runtimeMajorVersion}.0.0.0"),
3599
+ // this assembly version is greater than what the SDK will have
3600
+ MockNuGetPackage.CreatePackageWithAssembly("System.Text.Json", $"{runtimeMajorVersion}.0.99", $"net{runtimeMajorVersion}.0", assemblyVersion: $"{runtimeMajorVersion}.99.99.99"),
3601
+ ],
3602
+ projectContents: $"""
3603
+ <Project Sdk="Microsoft.NET.Sdk">
3604
+ <PropertyGroup>
3605
+ <TargetFramework>net{runtimeMajorVersion}.0</TargetFramework>
3606
+ </PropertyGroup>
3607
+ <ItemGroup>
3608
+ <PackageReference Include="Some.Package" Version="1.0.0" />
3609
+ </ItemGroup>
3610
+ </Project>
3611
+ """,
3612
+ additionalFiles: [
3613
+ ("global.json", $$"""
3614
+ {
3615
+ "sdk": {
3616
+ "version": "{{runtimeMajorVersion}}.0.100",
3617
+ "allowPrerelease": true,
3618
+ "rollForward": "latestMinor"
3619
+ }
3620
+ }
3621
+ """)
3622
+ ],
3623
+ expectedProjectContents: $"""
3624
+ <Project Sdk="Microsoft.NET.Sdk">
3625
+ <PropertyGroup>
3626
+ <TargetFramework>net{runtimeMajorVersion}.0</TargetFramework>
3627
+ </PropertyGroup>
3628
+ <ItemGroup>
3629
+ <PackageReference Include="Some.Package" Version="2.0.0" />
3630
+ </ItemGroup>
3631
+ </Project>
3632
+ """
3633
+ );
3634
+ }
3490
3635
  }
3491
3636
  }