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:
         
     |