dependabot-nuget 0.289.0 → 0.291.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 (97) hide show
  1. checksums.yaml +4 -4
  2. data/helpers/lib/NuGetUpdater/Directory.Packages.props +1 -1
  3. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/AnalyzeCommand.cs +7 -3
  4. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/RunCommand.cs +1 -1
  5. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Analyze.cs +26 -1
  6. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Discover.cs +2 -1
  7. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Run.cs +0 -6
  8. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Update.cs +1 -1
  9. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/AnalyzeWorker.cs +6 -1
  10. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/CompatabilityChecker.cs +24 -9
  11. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/DependencyFinder.cs +2 -0
  12. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/NuGetContext.cs +0 -13
  13. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/RequirementConverter.cs +17 -0
  14. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DiscoveryWorker.cs +44 -5
  15. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/PackagesConfigDiscovery.cs +2 -2
  16. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/ProjectDiscoveryResult.cs +2 -0
  17. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/SdkProjectDiscovery.cs +19 -11
  18. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ErrorType.cs +1 -0
  19. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ExperimentsManager.cs +3 -0
  20. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/Advisory.cs +13 -0
  21. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/AllowedUpdate.cs +18 -1
  22. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/CommitOptions.cs +8 -0
  23. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/Condition.cs +19 -0
  24. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/DependencyGroup.cs +8 -0
  25. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/GroupPullRequest.cs +9 -0
  26. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/Job.cs +13 -10
  27. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/PullRequest.cs +11 -0
  28. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/RequirementsUpdateStrategy.cs +15 -0
  29. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/RunWorker.cs +24 -4
  30. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/VersionConverter.cs +19 -0
  31. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/BindingRedirectManager.cs +2 -1
  32. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/LockFileUpdater.cs +3 -2
  33. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackageReferenceUpdater.cs +43 -18
  34. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackagesConfigUpdater.cs +13 -12
  35. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdaterWorker.cs +1 -1
  36. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/JsonHelper.cs +2 -0
  37. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +40 -14
  38. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/NuGetHelper.cs +2 -2
  39. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ProcessExtensions.cs +45 -7
  40. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ProjectHelper.cs +2 -2
  41. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTestBase.cs +5 -2
  42. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.DotNetToolsJson.cs +45 -1
  43. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.GlobalJson.cs +35 -1
  44. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Project.cs +0 -4
  45. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs +41 -0
  46. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/ExpectedDiscoveryResults.cs +1 -0
  47. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/SdkProjectDiscoveryTests.cs +1 -1
  48. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/MockNuGetPackage.cs +2 -1
  49. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/MiscellaneousTests.cs +85 -0
  50. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/RunWorkerTests.cs +7 -31
  51. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/SerializationTests.cs +340 -0
  52. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TemporaryDirectory.cs +18 -7
  53. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/PackagesConfigUpdaterTests.cs +24 -0
  54. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs +0 -12
  55. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.DotNetTools.cs +84 -0
  56. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.GlobalJson.cs +66 -0
  57. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackageReference.cs +55 -0
  58. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs +0 -6
  59. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/MSBuildHelperTests.cs +785 -755
  60. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/PathHelperTests.cs +2 -2
  61. data/lib/dependabot/nuget/analysis/analysis_json_reader.rb +1 -1
  62. data/lib/dependabot/nuget/analysis/dependency_analysis.rb +3 -3
  63. data/lib/dependabot/nuget/discovery/dependency_details.rb +10 -3
  64. data/lib/dependabot/nuget/discovery/dependency_file_discovery.rb +8 -12
  65. data/lib/dependabot/nuget/discovery/discovery_json_reader.rb +214 -29
  66. data/lib/dependabot/nuget/discovery/project_discovery.rb +41 -8
  67. data/lib/dependabot/nuget/discovery/workspace_discovery.rb +14 -19
  68. data/lib/dependabot/nuget/file_fetcher.rb +3 -3
  69. data/lib/dependabot/nuget/file_parser.rb +92 -3
  70. data/lib/dependabot/nuget/file_updater.rb +13 -13
  71. data/lib/dependabot/nuget/language.rb +82 -0
  72. data/lib/dependabot/nuget/native_helpers.rb +37 -5
  73. data/lib/dependabot/nuget/package_manager.rb +51 -0
  74. data/lib/dependabot/nuget/update_checker/requirements_updater.rb +23 -27
  75. data/lib/dependabot/nuget/update_checker.rb +116 -190
  76. metadata +20 -29
  77. data/lib/dependabot/nuget/discovery/directory_packages_props_discovery.rb +0 -43
  78. data/lib/dependabot/nuget/http_response_helpers.rb +0 -19
  79. data/lib/dependabot/nuget/native_discovery/native_dependency_details.rb +0 -102
  80. data/lib/dependabot/nuget/native_discovery/native_dependency_file_discovery.rb +0 -122
  81. data/lib/dependabot/nuget/native_discovery/native_discovery_json_reader.rb +0 -277
  82. data/lib/dependabot/nuget/native_discovery/native_evaluation_details.rb +0 -63
  83. data/lib/dependabot/nuget/native_discovery/native_project_discovery.rb +0 -104
  84. data/lib/dependabot/nuget/native_discovery/native_property_details.rb +0 -43
  85. data/lib/dependabot/nuget/native_discovery/native_workspace_discovery.rb +0 -61
  86. data/lib/dependabot/nuget/native_update_checker/native_requirements_updater.rb +0 -105
  87. data/lib/dependabot/nuget/native_update_checker/native_update_checker.rb +0 -214
  88. data/lib/dependabot/nuget/nuget_client.rb +0 -223
  89. data/lib/dependabot/nuget/update_checker/compatibility_checker.rb +0 -116
  90. data/lib/dependabot/nuget/update_checker/dependency_finder.rb +0 -297
  91. data/lib/dependabot/nuget/update_checker/nupkg_fetcher.rb +0 -221
  92. data/lib/dependabot/nuget/update_checker/nuspec_fetcher.rb +0 -110
  93. data/lib/dependabot/nuget/update_checker/property_updater.rb +0 -196
  94. data/lib/dependabot/nuget/update_checker/repository_finder.rb +0 -466
  95. data/lib/dependabot/nuget/update_checker/tfm_comparer.rb +0 -34
  96. data/lib/dependabot/nuget/update_checker/tfm_finder.rb +0 -30
  97. 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
 
@@ -257,6 +261,342 @@ 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();
@@ -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>
@@ -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
  }
@@ -272,10 +272,6 @@ public abstract class UpdateWorkerTestBase : TestBase
272
272
  {
273
273
  Job = new()
274
274
  {
275
- AllowedUpdates =
276
- [
277
- new() { UpdateType = "all" }
278
- ],
279
275
  Source = new()
280
276
  {
281
277
  Provider = "github",
@@ -315,14 +311,6 @@ public abstract class UpdateWorkerTestBase : TestBase
315
311
  """
316
312
  );
317
313
  }
318
-
319
- // override various nuget locations
320
- foreach (var envName in new[] { "NUGET_PACKAGES", "NUGET_HTTP_CACHE_PATH", "NUGET_SCRATCH", "NUGET_PLUGINS_CACHE_PATH" })
321
- {
322
- string dir = Path.Join(temporaryDirectory, envName);
323
- Directory.CreateDirectory(dir);
324
- Environment.SetEnvironmentVariable(envName, dir);
325
- }
326
314
  }
327
315
 
328
316
  protected static async Task<TestFile[]> RunUpdate(TestFile[] files, Func<string, Task> action)
@@ -287,5 +287,89 @@ public partial class UpdateWorkerTests
287
287
  ]
288
288
  );
289
289
  }
290
+
291
+ [Fact]
292
+ public async Task UpdateSingleDependencyWithTrailingComma()
293
+ {
294
+ await TestUpdateForProject("Some.DotNet.Tool", "1.0.0", "1.1.0",
295
+ packages:
296
+ [
297
+ MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.3", "net8.0"),
298
+ MockNuGetPackage.CreateDotNetToolPackage("Some.DotNet.Tool", "1.0.0", "net8.0"),
299
+ MockNuGetPackage.CreateDotNetToolPackage("Some.DotNet.Tool", "1.1.0", "net8.0"),
300
+ ],
301
+ // initial
302
+ projectContents: """
303
+ <Project Sdk="Microsoft.NET.Sdk">
304
+ <PropertyGroup>
305
+ <TargetFramework>net8.0</TargetFramework>
306
+ </PropertyGroup>
307
+
308
+ <ItemGroup>
309
+ <PackageReference Include="Some.Package" Version="13.0.3" />
310
+ </ItemGroup>
311
+ </Project>
312
+ """,
313
+ additionalFiles:
314
+ [
315
+ (".config/dotnet-tools.json", """
316
+ {
317
+ "version": 1,
318
+ "isRoot": true,
319
+ "tools": {
320
+ "some.dotnet.tool": {
321
+ "version": "1.0.0",
322
+ "commands": [
323
+ "some.dotnet.tool"
324
+ ],
325
+ },
326
+ "some-other-tool": {
327
+ "version": "2.1.3",
328
+ "commands": [
329
+ "some-other-tool"
330
+ ],
331
+ }
332
+ }
333
+ }
334
+ """)
335
+ ],
336
+ // expected
337
+ expectedProjectContents: """
338
+ <Project Sdk="Microsoft.NET.Sdk">
339
+ <PropertyGroup>
340
+ <TargetFramework>net8.0</TargetFramework>
341
+ </PropertyGroup>
342
+
343
+ <ItemGroup>
344
+ <PackageReference Include="Some.Package" Version="13.0.3" />
345
+ </ItemGroup>
346
+ </Project>
347
+ """,
348
+ // expected files no longer have trailing commas in the json
349
+ additionalFilesExpected:
350
+ [
351
+ (".config/dotnet-tools.json", """
352
+ {
353
+ "version": 1,
354
+ "isRoot": true,
355
+ "tools": {
356
+ "some.dotnet.tool": {
357
+ "version": "1.1.0",
358
+ "commands": [
359
+ "some.dotnet.tool"
360
+ ]
361
+ },
362
+ "some-other-tool": {
363
+ "version": "2.1.3",
364
+ "commands": [
365
+ "some-other-tool"
366
+ ]
367
+ }
368
+ }
369
+ }
370
+ """)
371
+ ]
372
+ );
373
+ }
290
374
  }
291
375
  }
@@ -226,5 +226,71 @@ public partial class UpdateWorkerTests
226
226
  ]
227
227
  );
228
228
  }
229
+
230
+ [Fact]
231
+ public async Task UpdateDependencyWithTrailingComma()
232
+ {
233
+ await TestUpdateForProject("Some.MSBuild.Sdk", "3.2.0", "4.1.0",
234
+ packages:
235
+ [
236
+ MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.3", "net8.0"),
237
+ MockNuGetPackage.CreateMSBuildSdkPackage("Some.MSBuild.Sdk", "3.2.0"),
238
+ MockNuGetPackage.CreateMSBuildSdkPackage("Some.MSBuild.Sdk", "4.1.0"),
239
+ ],
240
+ // initial
241
+ projectContents: """
242
+ <Project Sdk="Microsoft.NET.Sdk">
243
+ <PropertyGroup>
244
+ <TargetFramework>net8.0</TargetFramework>
245
+ </PropertyGroup>
246
+
247
+ <ItemGroup>
248
+ <PackageReference Include="Some.Package" Version="13.0.3" />
249
+ </ItemGroup>
250
+ </Project>
251
+ """,
252
+ additionalFiles:
253
+ [
254
+ ("global.json", """
255
+ {
256
+ "sdk": {
257
+ "version": "6.0.405",
258
+ "rollForward": "latestPatch"
259
+ },
260
+ "msbuild-sdks": {
261
+ "Some.MSBuild.Sdk": "3.2.0"
262
+ },
263
+ }
264
+ """)
265
+ ],
266
+ // expected
267
+ expectedProjectContents: """
268
+ <Project Sdk="Microsoft.NET.Sdk">
269
+ <PropertyGroup>
270
+ <TargetFramework>net8.0</TargetFramework>
271
+ </PropertyGroup>
272
+
273
+ <ItemGroup>
274
+ <PackageReference Include="Some.Package" Version="13.0.3" />
275
+ </ItemGroup>
276
+ </Project>
277
+ """,
278
+ // expected file no longer has the trailing comma because the parser removes it.
279
+ additionalFilesExpected:
280
+ [
281
+ ("global.json", """
282
+ {
283
+ "sdk": {
284
+ "version": "6.0.405",
285
+ "rollForward": "latestPatch"
286
+ },
287
+ "msbuild-sdks": {
288
+ "Some.MSBuild.Sdk": "4.1.0"
289
+ }
290
+ }
291
+ """)
292
+ ]
293
+ );
294
+ }
229
295
  }
230
296
  }
@@ -158,6 +158,61 @@ public partial class UpdateWorkerTests
158
158
  );
159
159
  }
160
160
 
161
+ [Theory]
162
+ [InlineData(true)]
163
+ [InlineData(false)]
164
+ public async Task PackageIsUpdatedFromCommonTargetsFile(bool useDirectDiscovery)
165
+ {
166
+ await TestUpdateForProject("Some.Package", "1.0.0", "2.0.0",
167
+ packages:
168
+ [
169
+ MockNuGetPackage.CreateSimplePackage("Some.Package", "1.0.0", "net8.0"),
170
+ MockNuGetPackage.CreateSimplePackage("Some.Package", "2.0.0", "net8.0"),
171
+ ],
172
+ experimentsManager: new ExperimentsManager() { UseDirectDiscovery = useDirectDiscovery },
173
+ projectContents: """
174
+ <Project Sdk="Microsoft.NET.Sdk">
175
+ <PropertyGroup>
176
+ <TargetFramework>net8.0</TargetFramework>
177
+ </PropertyGroup>
178
+ <Import Project="CommonPackages.targets" />
179
+ </Project>
180
+ """,
181
+ additionalFiles:
182
+ [
183
+ ("CommonPackages.targets", """
184
+ <Project>
185
+ <ItemGroup>
186
+ <PackageReference Include="Some.Package">
187
+ <Version>1.0.0</Version>
188
+ </PackageReference>
189
+ </ItemGroup>
190
+ </Project>
191
+ """)
192
+ ],
193
+ expectedProjectContents: """
194
+ <Project Sdk="Microsoft.NET.Sdk">
195
+ <PropertyGroup>
196
+ <TargetFramework>net8.0</TargetFramework>
197
+ </PropertyGroup>
198
+ <Import Project="CommonPackages.targets" />
199
+ </Project>
200
+ """,
201
+ additionalFilesExpected:
202
+ [
203
+ ("CommonPackages.targets", """
204
+ <Project>
205
+ <ItemGroup>
206
+ <PackageReference Include="Some.Package">
207
+ <Version>2.0.0</Version>
208
+ </PackageReference>
209
+ </ItemGroup>
210
+ </Project>
211
+ """)
212
+ ]
213
+ );
214
+ }
215
+
161
216
  [Fact]
162
217
  public async Task CallingResolveDependencyConflictsNew()
163
218
  {