dependabot-nuget 0.288.0 → 0.290.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 (117) hide show
  1. checksums.yaml +4 -4
  2. data/helpers/lib/NuGetUpdater/Directory.Packages.props +19 -17
  3. data/helpers/lib/NuGetUpdater/NuGetProjects/NuGet.Packaging/NuGet.Packaging.csproj +0 -1
  4. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/AnalyzeCommand.cs +7 -3
  5. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/RunCommand.cs +1 -1
  6. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Analyze.cs +29 -2
  7. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Discover.cs +25 -4
  8. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Run.cs +0 -6
  9. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/AnalyzeWorker.cs +33 -16
  10. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/CompatabilityChecker.cs +25 -10
  11. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/NuGetContext.cs +0 -13
  12. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/RequirementArrayConverter.cs +39 -0
  13. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/VersionFinder.cs +1 -1
  14. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Clone/ShellGitCommandHandler.cs +1 -1
  15. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DiscoveryWorker.cs +60 -66
  16. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DotNetToolsJsonDiscovery.cs +2 -2
  17. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/GlobalJsonDiscovery.cs +2 -2
  18. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/PackagesConfigDiscovery.cs +11 -3
  19. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/PackagesConfigDiscoveryResult.cs +1 -0
  20. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/ProjectDiscoveryResult.cs +2 -4
  21. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/SdkProjectDiscovery.cs +54 -11
  22. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/WorkspaceDiscoveryResult.cs +0 -1
  23. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ExperimentsManager.cs +1 -2
  24. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/JsonBuildFile.cs +1 -1
  25. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/FrameworkChecker/CompatabilityChecker.cs +2 -2
  26. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/Advisory.cs +13 -0
  27. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/AllowedUpdate.cs +18 -1
  28. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/CommitOptions.cs +8 -0
  29. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/Condition.cs +19 -0
  30. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/DependencyGroup.cs +8 -0
  31. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/GroupPullRequest.cs +9 -0
  32. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/Job.cs +13 -10
  33. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/PullRequest.cs +11 -0
  34. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/RequirementsUpdateStrategy.cs +15 -0
  35. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/RunWorker.cs +67 -58
  36. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/VersionConverter.cs +19 -0
  37. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/BindingRedirectManager.cs +15 -44
  38. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/DotNetToolsJsonUpdater.cs +4 -4
  39. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/GlobalJsonUpdater.cs +5 -5
  40. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/LockFileUpdater.cs +2 -10
  41. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackageReferenceUpdater.cs +38 -33
  42. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackagesConfigUpdater.cs +25 -23
  43. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdaterWorker.cs +16 -12
  44. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ConsoleLogger.cs +1 -1
  45. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/DependencyConflictResolver.cs +19 -19
  46. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ILogger.cs +11 -1
  47. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/JsonHelper.cs +2 -0
  48. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +18 -17
  49. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/NuGetHelper.cs +1 -17
  50. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/PathHelper.cs +17 -9
  51. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ProjectHelper.cs +96 -0
  52. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTestBase.cs +5 -2
  53. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTests.cs +87 -5
  54. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTestBase.cs +2 -5
  55. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.DotNetToolsJson.cs +45 -1
  56. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.GlobalJson.cs +35 -1
  57. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.PackagesConfig.cs +16 -0
  58. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Proj.cs +6 -0
  59. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Project.cs +143 -36
  60. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs +184 -48
  61. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/ExpectedDiscoveryResults.cs +5 -5
  62. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/SdkProjectDiscoveryTests.cs +32 -10
  63. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/MiscellaneousTests.cs +85 -0
  64. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/RunWorkerTests.cs +402 -102
  65. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/SerializationTests.cs +342 -2
  66. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/UpdatedDependencyListTests.cs +60 -2
  67. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TemporaryDirectory.cs +18 -7
  68. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TestLogger.cs +1 -1
  69. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/BindingRedirectsTests.cs +1 -1
  70. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/PackagesConfigUpdaterTests.cs +24 -0
  71. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs +4 -14
  72. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.DotNetTools.cs +84 -0
  73. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.GlobalJson.cs +66 -0
  74. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackageReference.cs +95 -0
  75. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs +1 -7
  76. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/AssertEx.cs +1 -1
  77. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/LinuxOnlyAttribute.cs +12 -0
  78. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/MSBuildHelperTests.cs +558 -711
  79. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/PathHelperTests.cs +47 -2
  80. data/lib/dependabot/nuget/analysis/analysis_json_reader.rb +4 -2
  81. data/lib/dependabot/nuget/analysis/dependency_analysis.rb +3 -3
  82. data/lib/dependabot/nuget/discovery/dependency_details.rb +10 -3
  83. data/lib/dependabot/nuget/discovery/dependency_file_discovery.rb +8 -12
  84. data/lib/dependabot/nuget/discovery/discovery_json_reader.rb +214 -29
  85. data/lib/dependabot/nuget/discovery/project_discovery.rb +41 -8
  86. data/lib/dependabot/nuget/discovery/workspace_discovery.rb +14 -19
  87. data/lib/dependabot/nuget/file_fetcher.rb +11 -393
  88. data/lib/dependabot/nuget/file_parser.rb +23 -61
  89. data/lib/dependabot/nuget/file_updater.rb +28 -23
  90. data/lib/dependabot/nuget/native_helpers.rb +14 -5
  91. data/lib/dependabot/nuget/update_checker/requirements_updater.rb +23 -27
  92. data/lib/dependabot/nuget/update_checker.rb +116 -190
  93. metadata +20 -32
  94. data/helpers/lib/NuGetUpdater/NuGetProjects/Directory.Packages.props +0 -29
  95. data/lib/dependabot/nuget/discovery/directory_packages_props_discovery.rb +0 -43
  96. data/lib/dependabot/nuget/file_fetcher/import_paths_finder.rb +0 -73
  97. data/lib/dependabot/nuget/file_fetcher/sln_project_paths_finder.rb +0 -60
  98. data/lib/dependabot/nuget/http_response_helpers.rb +0 -19
  99. data/lib/dependabot/nuget/native_discovery/native_dependency_details.rb +0 -102
  100. data/lib/dependabot/nuget/native_discovery/native_dependency_file_discovery.rb +0 -129
  101. data/lib/dependabot/nuget/native_discovery/native_discovery_json_reader.rb +0 -171
  102. data/lib/dependabot/nuget/native_discovery/native_evaluation_details.rb +0 -63
  103. data/lib/dependabot/nuget/native_discovery/native_project_discovery.rb +0 -82
  104. data/lib/dependabot/nuget/native_discovery/native_property_details.rb +0 -43
  105. data/lib/dependabot/nuget/native_discovery/native_workspace_discovery.rb +0 -68
  106. data/lib/dependabot/nuget/native_update_checker/native_requirements_updater.rb +0 -105
  107. data/lib/dependabot/nuget/native_update_checker/native_update_checker.rb +0 -201
  108. data/lib/dependabot/nuget/nuget_client.rb +0 -223
  109. data/lib/dependabot/nuget/update_checker/compatibility_checker.rb +0 -116
  110. data/lib/dependabot/nuget/update_checker/dependency_finder.rb +0 -297
  111. data/lib/dependabot/nuget/update_checker/nupkg_fetcher.rb +0 -221
  112. data/lib/dependabot/nuget/update_checker/nuspec_fetcher.rb +0 -110
  113. data/lib/dependabot/nuget/update_checker/property_updater.rb +0 -196
  114. data/lib/dependabot/nuget/update_checker/repository_finder.rb +0 -466
  115. data/lib/dependabot/nuget/update_checker/tfm_comparer.rb +0 -34
  116. data/lib/dependabot/nuget/update_checker/tfm_finder.rb +0 -30
  117. data/lib/dependabot/nuget/update_checker/version_finder.rb +0 -449
@@ -1,5 +1,9 @@
1
+ using NuGet.Versioning;
2
+
3
+ using NuGetUpdater.Core.Analyze;
1
4
  using NuGetUpdater.Core.Run;
2
5
  using NuGetUpdater.Core.Run.ApiModel;
6
+ using NuGetUpdater.Core.Test.Utilities;
3
7
 
4
8
  using Xunit;
5
9
 
@@ -245,7 +249,7 @@ public class SerializationTests
245
249
  // assert
246
250
  Assert.False(experimentsManager.UseLegacyDependencySolver);
247
251
  Assert.False(experimentsManager.UseDirectDiscovery);
248
- Assert.Single(capturingTestLogger.Messages.Where(m => m.Contains("Error deserializing job file")));
252
+ Assert.Single(capturingTestLogger.Messages, m => m.Contains("Error deserializing job file"));
249
253
  }
250
254
 
251
255
  [Fact]
@@ -257,13 +261,349 @@ public class SerializationTests
257
261
  Assert.Equal(expected, actual);
258
262
  }
259
263
 
264
+ [Fact]
265
+ public void DeserializeJobIgnoreConditions()
266
+ {
267
+ var jobContent = """
268
+ {
269
+ "job": {
270
+ "package-manager": "nuget",
271
+ "source": {
272
+ "provider": "github",
273
+ "repo": "some-org/some-repo",
274
+ "directory": "specific-sdk"
275
+ },
276
+ "ignore-conditions": [
277
+ {
278
+ "dependency-name": "Package.1",
279
+ "source": "some-file",
280
+ "update-types": [
281
+ "version-update:semver-major"
282
+ ],
283
+ "version-requirement": "> 1.2.3"
284
+ },
285
+ {
286
+ "dependency-name": "Package.2",
287
+ "updated-at": "2024-12-05T15:47:12Z"
288
+ }
289
+ ]
290
+ }
291
+ }
292
+ """;
293
+ var jobWrapper = RunWorker.Deserialize(jobContent)!;
294
+ Assert.Equal(2, jobWrapper.Job.IgnoreConditions.Length);
295
+
296
+ Assert.Equal("Package.1", jobWrapper.Job.IgnoreConditions[0].DependencyName);
297
+ Assert.Equal("some-file", jobWrapper.Job.IgnoreConditions[0].Source);
298
+ Assert.Equal("version-update:semver-major", jobWrapper.Job.IgnoreConditions[0].UpdateTypes.Single());
299
+ Assert.Null(jobWrapper.Job.IgnoreConditions[0].UpdatedAt);
300
+ Assert.Equal("> 1.2.3", jobWrapper.Job.IgnoreConditions[0].VersionRequirement?.ToString());
301
+
302
+ Assert.Equal("Package.2", jobWrapper.Job.IgnoreConditions[1].DependencyName);
303
+ Assert.Null(jobWrapper.Job.IgnoreConditions[1].Source);
304
+ Assert.Empty(jobWrapper.Job.IgnoreConditions[1].UpdateTypes);
305
+ Assert.Equal(new DateTime(2024, 12, 5, 15, 47, 12), jobWrapper.Job.IgnoreConditions[1].UpdatedAt);
306
+ Assert.Null(jobWrapper.Job.IgnoreConditions[1].VersionRequirement);
307
+ }
308
+
309
+ [Theory]
310
+ [MemberData(nameof(DeserializeAllowedUpdatesData))]
311
+ public void DeserializeAllowedUpdates(string? allowedUpdatesJsonBody, AllowedUpdate[] expectedAllowedUpdates)
312
+ {
313
+ string? allowedUpdatesJson = allowedUpdatesJsonBody is null
314
+ ? null
315
+ : $$"""
316
+ ,
317
+ "allowed-updates": {{allowedUpdatesJsonBody}}
318
+ """;
319
+ var jobWrapperJson = $$"""
320
+ {
321
+ "job": {
322
+ "source": {
323
+ "provider": "github",
324
+ "repo": "some/repo"
325
+ }
326
+ {{allowedUpdatesJson}}
327
+ }
328
+ }
329
+ """;
330
+ var jobWrapper = RunWorker.Deserialize(jobWrapperJson)!;
331
+ AssertEx.Equal(expectedAllowedUpdates, jobWrapper.Job.AllowedUpdates);
332
+ }
333
+
334
+ [Fact]
335
+ public void DeserializeDependencyGroups()
336
+ {
337
+ var jsonWrapperJson = """
338
+ {
339
+ "job": {
340
+ "source": {
341
+ "provider": "github",
342
+ "repo": "some/repo"
343
+ },
344
+ "dependency-groups": [
345
+ {
346
+ "name": "Some.Dependency",
347
+ "rules": {
348
+ "patterns": ["1.2.3", "4.5.6"]
349
+ }
350
+ },
351
+ {
352
+ "name": "Some.Other.Dependency",
353
+ "applies-to": "something"
354
+ }
355
+ ]
356
+ }
357
+ }
358
+ """;
359
+ var jobWrapper = RunWorker.Deserialize(jsonWrapperJson)!;
360
+ Assert.Equal(2, jobWrapper.Job.DependencyGroups.Length);
361
+
362
+ Assert.Equal("Some.Dependency", jobWrapper.Job.DependencyGroups[0].Name);
363
+ Assert.Null(jobWrapper.Job.DependencyGroups[0].AppliesTo);
364
+ Assert.Single(jobWrapper.Job.DependencyGroups[0].Rules);
365
+ Assert.Equal("[\"1.2.3\", \"4.5.6\"]", jobWrapper.Job.DependencyGroups[0].Rules["patterns"].ToString());
366
+
367
+ Assert.Equal("Some.Other.Dependency", jobWrapper.Job.DependencyGroups[1].Name);
368
+ Assert.Equal("something", jobWrapper.Job.DependencyGroups[1].AppliesTo);
369
+ Assert.Empty(jobWrapper.Job.DependencyGroups[1].Rules);
370
+ }
371
+
372
+ [Fact]
373
+ public void DeserializeExistingPullRequests()
374
+ {
375
+ var jsonWrapperJson = """
376
+ {
377
+ "job": {
378
+ "source": {
379
+ "provider": "github",
380
+ "repo": "some/repo"
381
+ },
382
+ "existing-pull-requests": [
383
+ [
384
+ {
385
+ "dependency-name": "Some.Package",
386
+ "dependency-version": "1.2.3"
387
+ }
388
+ ]
389
+ ]
390
+ }
391
+ }
392
+ """;
393
+ var jobWrapper = RunWorker.Deserialize(jsonWrapperJson)!;
394
+ Assert.Single(jobWrapper.Job.ExistingPullRequests);
395
+ Assert.Single(jobWrapper.Job.ExistingPullRequests[0]);
396
+ Assert.Equal("Some.Package", jobWrapper.Job.ExistingPullRequests[0][0].DependencyName);
397
+ Assert.Equal(NuGetVersion.Parse("1.2.3"), jobWrapper.Job.ExistingPullRequests[0][0].DependencyVersion);
398
+ Assert.False(jobWrapper.Job.ExistingPullRequests[0][0].DependencyRemoved);
399
+ Assert.Null(jobWrapper.Job.ExistingPullRequests[0][0].Directory);
400
+ }
401
+
402
+ [Fact]
403
+ public void DeserializeExistingGroupPullRequests()
404
+ {
405
+ var jsonWrapperJson = """
406
+ {
407
+ "job": {
408
+ "source": {
409
+ "provider": "github",
410
+ "repo": "some/repo"
411
+ },
412
+ "existing-group-pull-requests": [
413
+ {
414
+ "dependency-group-name": "Some-Group-Name",
415
+ "dependencies": [
416
+ {
417
+ "dependency-name": "Some.Package",
418
+ "dependency-version": "1.2.3"
419
+ },
420
+ {
421
+ "dependency-name": "Some.Other.Package",
422
+ "dependency-version": "4.5.6",
423
+ "directory": "/some-dir"
424
+ }
425
+ ]
426
+ }
427
+ ]
428
+ }
429
+ }
430
+ """;
431
+ var jobWrapper = RunWorker.Deserialize(jsonWrapperJson)!;
432
+ Assert.Single(jobWrapper.Job.ExistingGroupPullRequests);
433
+ Assert.Equal("Some-Group-Name", jobWrapper.Job.ExistingGroupPullRequests[0].DependencyGroupName);
434
+ Assert.Equal(2, jobWrapper.Job.ExistingGroupPullRequests[0].Dependencies.Length);
435
+ Assert.Equal("Some.Package", jobWrapper.Job.ExistingGroupPullRequests[0].Dependencies[0].DependencyName);
436
+ Assert.Equal("1.2.3", jobWrapper.Job.ExistingGroupPullRequests[0].Dependencies[0].DependencyVersion.ToString());
437
+ Assert.Null(jobWrapper.Job.ExistingGroupPullRequests[0].Dependencies[0].Directory);
438
+ Assert.Equal("Some.Other.Package", jobWrapper.Job.ExistingGroupPullRequests[0].Dependencies[1].DependencyName);
439
+ Assert.Equal("4.5.6", jobWrapper.Job.ExistingGroupPullRequests[0].Dependencies[1].DependencyVersion.ToString());
440
+ Assert.Equal("/some-dir", jobWrapper.Job.ExistingGroupPullRequests[0].Dependencies[1].Directory);
441
+ }
442
+
443
+ [Theory]
444
+ [InlineData("null", null)]
445
+ [InlineData("\"bump_versions\"", RequirementsUpdateStrategy.BumpVersions)]
446
+ [InlineData("\"lockfile_only\"", RequirementsUpdateStrategy.LockfileOnly)]
447
+ public void DeserializeRequirementsUpdateStrategy(string requirementsUpdateStrategyStringJson, RequirementsUpdateStrategy? expectedRequirementsUpdateStrategy)
448
+ {
449
+ var jsonWrapperJson = $$"""
450
+ {
451
+ "job": {
452
+ "source": {
453
+ "provider": "github",
454
+ "repo": "some/repo"
455
+ },
456
+ "requirements-update-strategy": {{requirementsUpdateStrategyStringJson}}
457
+ }
458
+ }
459
+ """;
460
+ var jobWrapper = RunWorker.Deserialize(jsonWrapperJson)!;
461
+ var actualRequirementsUpdateStrategy = jobWrapper.Job.RequirementsUpdateStrategy;
462
+ Assert.Equal(expectedRequirementsUpdateStrategy, actualRequirementsUpdateStrategy);
463
+ }
464
+
465
+ [Fact]
466
+ public void DeserializeSecurityAdvisories()
467
+ {
468
+ var jsonWrapperJson = """
469
+ {
470
+ "job": {
471
+ "source": {
472
+ "provider": "github",
473
+ "repo": "some/repo"
474
+ },
475
+ "security-advisories": [
476
+ {
477
+ "dependency-name": "Some.Package",
478
+ "affected-versions": [
479
+ ">= 1.0.0, < 1.2.0"
480
+ ],
481
+ "patched-versions": null
482
+ }
483
+ ]
484
+ }
485
+ }
486
+ """;
487
+ var jobWrapper = RunWorker.Deserialize(jsonWrapperJson)!;
488
+ Assert.Single(jobWrapper.Job.SecurityAdvisories);
489
+ Assert.Equal("Some.Package", jobWrapper.Job.SecurityAdvisories[0].DependencyName);
490
+ Assert.Equal(">= 1.0.0, < 1.2.0", jobWrapper.Job.SecurityAdvisories[0].AffectedVersions!.Value.Single().ToString());
491
+ Assert.Null(jobWrapper.Job.SecurityAdvisories[0].PatchedVersions);
492
+ Assert.Null(jobWrapper.Job.SecurityAdvisories[0].PatchedVersions);
493
+ }
494
+
495
+ [Fact]
496
+ public void DeserializeCommitOptions()
497
+ {
498
+ var jsonWrapperJson = """
499
+ {
500
+ "job": {
501
+ "source": {
502
+ "provider": "github",
503
+ "repo": "some/repo"
504
+ },
505
+ "commit-message-options": {
506
+ "prefix": "[SECURITY] "
507
+ }
508
+ }
509
+ }
510
+ """;
511
+ var jobWrapper = RunWorker.Deserialize(jsonWrapperJson)!;
512
+ Assert.Equal("[SECURITY] ", jobWrapper.Job.CommitMessageOptions!.Prefix);
513
+ Assert.Null(jobWrapper.Job.CommitMessageOptions!.PrefixDevelopment);
514
+ Assert.Null(jobWrapper.Job.CommitMessageOptions!.IncludeScope);
515
+ }
516
+
517
+ public static IEnumerable<object?[]> DeserializeAllowedUpdatesData()
518
+ {
519
+ // common default value - most job files look like this
520
+ yield return
521
+ [
522
+ // allowedUpdatesJsonBody
523
+ """
524
+ [
525
+ {
526
+ "update-type": "all"
527
+ }
528
+ ]
529
+ """,
530
+ // expectedAllowedUpdates
531
+ new[]
532
+ {
533
+ new AllowedUpdate()
534
+ {
535
+ DependencyType = Core.Run.ApiModel.DependencyType.All,
536
+ DependencyName = null,
537
+ UpdateType = UpdateType.All
538
+ }
539
+ }
540
+ ];
541
+
542
+ // allowed updates is missing - ensure proper defaults
543
+ yield return
544
+ [
545
+ // allowedUpdatesJsonBody
546
+ null,
547
+ // expectedAllowedUpdates
548
+ new[]
549
+ {
550
+ new AllowedUpdate()
551
+ }
552
+ ];
553
+
554
+ // multiple non-default values
555
+ yield return
556
+ [
557
+ // allowedUpdatesJsonBody
558
+ """
559
+ [
560
+ {
561
+ "dependency-type": "indirect",
562
+ "dependency-name": "Dependency.One",
563
+ "update-type": "security"
564
+ },
565
+ {
566
+ "dependency-type": "production",
567
+ "dependency-name": "Dependency.Two",
568
+ "update-type": "all"
569
+ },
570
+ {
571
+ "dependency-type": "indirect",
572
+ "update-type": "security"
573
+ }
574
+ ]
575
+ """,
576
+ new[]
577
+ {
578
+ new AllowedUpdate()
579
+ {
580
+ DependencyType = Core.Run.ApiModel.DependencyType.Indirect,
581
+ DependencyName = "Dependency.One",
582
+ UpdateType = UpdateType.Security
583
+ },
584
+ new AllowedUpdate()
585
+ {
586
+ DependencyType = Core.Run.ApiModel.DependencyType.Production,
587
+ DependencyName = "Dependency.Two",
588
+ UpdateType = UpdateType.All
589
+ },
590
+ new AllowedUpdate()
591
+ {
592
+ DependencyType = Core.Run.ApiModel.DependencyType.Indirect,
593
+ DependencyName = null,
594
+ UpdateType = UpdateType.Security
595
+ }
596
+ }
597
+ ];
598
+ }
599
+
260
600
  private class CapturingTestLogger : ILogger
261
601
  {
262
602
  private readonly List<string> _messages = new();
263
603
 
264
604
  public IReadOnlyList<string> Messages => _messages;
265
605
 
266
- public void Log(string message)
606
+ public void LogRaw(string message)
267
607
  {
268
608
  _messages.Add(message);
269
609
  }
@@ -40,6 +40,8 @@ public class UpdatedDependencyListTests
40
40
  Properties = [],
41
41
  TargetFrameworks = ["net8.0"],
42
42
  ReferencedProjectPaths = [],
43
+ ImportedFiles = [],
44
+ AdditionalFiles = ["packages.config"],
43
45
  },
44
46
  new()
45
47
  {
@@ -50,6 +52,8 @@ public class UpdatedDependencyListTests
50
52
  Properties = [],
51
53
  TargetFrameworks = ["net8.0"],
52
54
  ReferencedProjectPaths = [],
55
+ ImportedFiles = [],
56
+ AdditionalFiles = ["packages.config"],
53
57
  },
54
58
  new()
55
59
  {
@@ -62,6 +66,8 @@ public class UpdatedDependencyListTests
62
66
  Properties = [],
63
67
  TargetFrameworks = ["net8.0"],
64
68
  ReferencedProjectPaths = [],
69
+ ImportedFiles = [],
70
+ AdditionalFiles = ["packages.config"],
65
71
  }
66
72
  ]
67
73
  };
@@ -99,13 +105,65 @@ public class UpdatedDependencyListTests
99
105
  new ReportedRequirement()
100
106
  {
101
107
  Requirement = "13.0.1",
102
- File = "/src/c/packages.config",
108
+ File = "/src/c/project.csproj",
103
109
  Groups = ["dependencies"],
104
110
  },
105
111
  ]
106
112
  },
107
113
  ],
108
- DependencyFiles = ["/src/a/project.csproj", "/src/b/project.csproj", "/src/c/project.csproj", "/src/a/packages.config", "/src/b/packages.config", "/src/c/packages.config"],
114
+ DependencyFiles = ["/src/a/packages.config", "/src/a/project.csproj", "/src/b/packages.config", "/src/b/project.csproj", "/src/c/packages.config", "/src/c/project.csproj"],
115
+ };
116
+
117
+ // doing JSON comparison makes this easier; we don't have to define custom record equality and we get an easy diff
118
+ var actualJson = JsonSerializer.Serialize(updatedDependencyList);
119
+ var expectedJson = JsonSerializer.Serialize(expectedDependencyList);
120
+ Assert.Equal(expectedJson, actualJson);
121
+ }
122
+
123
+ [Fact]
124
+ public async Task UpdatedDependencyListDeduplicatesFiles()
125
+ {
126
+ // arrange
127
+ using var tempDir = new TemporaryDirectory();
128
+ var testFiles = new[]
129
+ {
130
+ "Directory.Packages.props",
131
+ "project1/project1.csproj",
132
+ "project2/project2.csproj",
133
+ };
134
+ foreach (var testFile in testFiles)
135
+ {
136
+ var fullFilePath = Path.Join(tempDir.DirectoryPath, testFile);
137
+ Directory.CreateDirectory(Path.GetDirectoryName(fullFilePath)!);
138
+ await File.WriteAllTextAsync(fullFilePath, "");
139
+ }
140
+ var discovery = new WorkspaceDiscoveryResult()
141
+ {
142
+ Path = "",
143
+ Projects = [
144
+ new()
145
+ {
146
+ FilePath = "project1/project1.csproj",
147
+ Dependencies = [],
148
+ ImportedFiles = ["../Directory.Packages.props"],
149
+ AdditionalFiles = [],
150
+ },
151
+ new()
152
+ {
153
+ FilePath = "project2/project2.csproj",
154
+ Dependencies = [],
155
+ ImportedFiles = ["../Directory.Packages.props"],
156
+ AdditionalFiles = [],
157
+ }
158
+ ]
159
+ };
160
+
161
+ // act
162
+ var updatedDependencyList = RunWorker.GetUpdatedDependencyListFromDiscovery(discovery, pathToContents: tempDir.DirectoryPath);
163
+ var expectedDependencyList = new UpdatedDependencyList()
164
+ {
165
+ Dependencies = [],
166
+ DependencyFiles = ["/Directory.Packages.props", "/project1/project1.csproj", "/project2/project2.csproj"],
109
167
  };
110
168
 
111
169
  // doing JSON comparison makes this easier; we don't have to define custom record equality and we get an easy diff
@@ -4,19 +4,32 @@ using TestFile = (string Path, string Contents);
4
4
 
5
5
  public sealed class TemporaryDirectory : IDisposable
6
6
  {
7
+ private readonly TemporaryEnvironment _environment;
8
+ private readonly string _rootDirectory;
9
+
7
10
  public string DirectoryPath { get; }
8
11
 
9
12
  public TemporaryDirectory()
10
13
  {
11
14
  var parentDir = Path.GetDirectoryName(GetType().Assembly.Location)!;
12
15
  var tempDirName = $"nuget-updater-{Guid.NewGuid():d}";
13
- DirectoryPath = Path.Combine(parentDir, "test-data", tempDirName);
16
+ _rootDirectory = Path.Combine(parentDir, "test-data", tempDirName);
17
+ _environment = new TemporaryEnvironment(
18
+ [
19
+ ("NUGET_PACKAGES", Path.Combine(_rootDirectory, "NUGET_PACKAGES")),
20
+ ("NUGET_HTTP_CACHE_PATH", Path.Combine(_rootDirectory, "NUGET_HTTP_CACHE_PATH")),
21
+ ("NUGET_SCRATCH", Path.Combine(_rootDirectory, "NUGET_SCRATCH")),
22
+ ("NUGET_PLUGINS_CACHE_PATH", Path.Combine(_rootDirectory, "NUGET_PLUGINS_CACHE_PATH")),
23
+ ]);
24
+
25
+ DirectoryPath = Path.Combine(_rootDirectory, "repo-root");
14
26
  Directory.CreateDirectory(DirectoryPath);
15
27
  }
16
28
 
17
29
  public void Dispose()
18
30
  {
19
- Directory.Delete(DirectoryPath, true);
31
+ _environment.Dispose();
32
+ Directory.Delete(_rootDirectory, true);
20
33
  }
21
34
 
22
35
  public async Task<TestFile[]> ReadFileContentsAsync(HashSet<string> filePaths)
@@ -47,12 +60,10 @@ public sealed class TemporaryDirectory : IDisposable
47
60
  {
48
61
  var temporaryDirectory = new TemporaryDirectory();
49
62
 
50
- var parentDirectory = Path.GetDirectoryName(temporaryDirectory.DirectoryPath)!;
51
-
52
63
  // prevent directory crawling
53
- await File.WriteAllTextAsync(Path.Combine(parentDirectory, "Directory.Build.props"), "<Project />");
54
- await File.WriteAllTextAsync(Path.Combine(parentDirectory, "Directory.Build.targets"), "<Project />");
55
- await File.WriteAllTextAsync(Path.Combine(parentDirectory, "Directory.Packages.props"), """
64
+ await File.WriteAllTextAsync(Path.Combine(temporaryDirectory._rootDirectory, "Directory.Build.props"), "<Project />");
65
+ await File.WriteAllTextAsync(Path.Combine(temporaryDirectory._rootDirectory, "Directory.Build.targets"), "<Project />");
66
+ await File.WriteAllTextAsync(Path.Combine(temporaryDirectory._rootDirectory, "Directory.Packages.props"), """
56
67
  <Project>
57
68
  <PropertyGroup>
58
69
  <ManagePackageVersionsCentrally>false</ManagePackageVersionsCentrally>
@@ -4,7 +4,7 @@ namespace NuGetUpdater.Core.Test;
4
4
 
5
5
  public class TestLogger : ILogger
6
6
  {
7
- public void Log(string message)
7
+ public void LogRaw(string message)
8
8
  {
9
9
  Debug.WriteLine(message);
10
10
  }
@@ -2,7 +2,7 @@ using Xunit;
2
2
 
3
3
  namespace NuGetUpdater.Core.Test.Update;
4
4
 
5
- public class BindingRedirectsTests
5
+ public class BindingRedirectsTests : TestBase
6
6
  {
7
7
  [Fact]
8
8
  public async Task SimpleBindingRedirectIsPerformed()
@@ -169,5 +169,29 @@ public class PackagesConfigUpdaterTests : TestBase
169
169
  // expected packages directory path
170
170
  null
171
171
  ];
172
+
173
+ // project with differing package name and assembly name
174
+ yield return
175
+ [
176
+ // project contents
177
+ """
178
+ <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
179
+ <ItemGroup>
180
+ <Reference Include="Assembly.For.Some.Package, Version=1.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed">
181
+ <HintPath>..\packages\Some.Package.1.0.0\lib\net45\Assembly.For.Some.Package.dll</HintPath>
182
+ <Private>True</Private>
183
+ </Reference>
184
+ </ItemGroup>
185
+ </Project>
186
+ """,
187
+ // packages.config contents
188
+ null,
189
+ // dependency name
190
+ "Some.Package",
191
+ // dependency version
192
+ "1.0.0",
193
+ // expected packages directory path
194
+ "../packages"
195
+ ];
172
196
  }
173
197
  }
@@ -77,7 +77,8 @@ public abstract class UpdateWorkerTestBase : TestBase
77
77
  TestFile[]? additionalFiles = null,
78
78
  MockNuGetPackage[]? packages = null,
79
79
  ExperimentsManager? experimentsManager = null,
80
- string projectFilePath = "test-project.csproj")
80
+ string projectFilePath = "test-project.csproj",
81
+ ExpectedUpdateOperationResult? expectedResult = null)
81
82
  => TestUpdateForProject(
82
83
  dependencyName,
83
84
  oldVersion,
@@ -88,7 +89,8 @@ public abstract class UpdateWorkerTestBase : TestBase
88
89
  additionalFiles,
89
90
  additionalFilesExpected: additionalFiles,
90
91
  packages: packages,
91
- experimentsManager: experimentsManager);
92
+ experimentsManager: experimentsManager,
93
+ expectedResult: expectedResult);
92
94
 
93
95
  protected static Task TestUpdateForProject(
94
96
  string dependencyName,
@@ -270,10 +272,6 @@ public abstract class UpdateWorkerTestBase : TestBase
270
272
  {
271
273
  Job = new()
272
274
  {
273
- AllowedUpdates =
274
- [
275
- new() { UpdateType = "all" }
276
- ],
277
275
  Source = new()
278
276
  {
279
277
  Provider = "github",
@@ -313,14 +311,6 @@ public abstract class UpdateWorkerTestBase : TestBase
313
311
  """
314
312
  );
315
313
  }
316
-
317
- // override various nuget locations
318
- foreach (var envName in new[] { "NUGET_PACKAGES", "NUGET_HTTP_CACHE_PATH", "NUGET_SCRATCH", "NUGET_PLUGINS_CACHE_PATH" })
319
- {
320
- string dir = Path.Join(temporaryDirectory, envName);
321
- Directory.CreateDirectory(dir);
322
- Environment.SetEnvironmentVariable(envName, dir);
323
- }
324
314
  }
325
315
 
326
316
  protected static async Task<TestFile[]> RunUpdate(TestFile[] files, Func<string, Task> action)