dependabot-nuget 0.292.0 → 0.293.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/.gitignore +1 -0
- data/helpers/lib/NuGetUpdater/Directory.Packages.props +1 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/Correlator.cs +197 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/DotNetPackageCorrelation.csproj +12 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/Model/PackageMapper.cs +68 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/Model/PackageSet.cs +11 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/Model/Release.cs +25 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/Model/ReleasesFile.cs +9 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/Model/RuntimePackages.cs +11 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/Model/Sdk.cs +13 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/Model/SemVerComparer.cs +16 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/Model/SemVersionConverter.cs +42 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation.Cli/DotNetPackageCorrelation.Cli.csproj +16 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation.Cli/Program.cs +32 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation.Test/CorrelatorTests.cs +99 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation.Test/DotNetPackageCorrelation.Test.csproj +18 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation.Test/EndToEndTests.cs +30 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation.Test/RuntimePackagesTests.cs +206 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/AnalyzeCommand.cs +6 -4
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/DiscoverCommand.cs +8 -7
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/RunCommand.cs +4 -4
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/UpdateCommand.cs +17 -5
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Analyze.cs +7 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Discover.cs +46 -6
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Update.cs +8 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/AnalyzeWorker.cs +8 -17
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/DependencyFinder.cs +4 -4
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/Extensions.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Clone/CloneWorker.cs +2 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/DependencyDiscovery.targets +2 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DiscoveryWorker.cs +7 -20
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/ProjectDiscoveryResult.cs +3 -3
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/SdkProjectDiscovery.cs +99 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/EnsureDotNetPackageCorrelation.targets +25 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ExperimentsManager.cs +9 -22
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/PackagesConfigBuildFile.cs +5 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/MissingFileException.cs +2 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/NativeResult.cs +3 -3
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/NuGetUpdater.Core.csproj +3 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/DependencyFileNotFound.cs +7 -3
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/DependencyFileNotParseable.cs +15 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/JobErrorBase.cs +24 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/RunWorker.cs +6 -21
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/UnparseableFileException.cs +12 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackageReferenceUpdater.cs +21 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdaterWorker.cs +6 -30
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/DotNetPackageCorrelationManager.cs +46 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +51 -27
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/NuGetHelper.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTestBase.cs +15 -4
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTests.cs +15 -9
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTestBase.cs +20 -12
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Project.cs +108 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs +16 -12
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/ExpectedDiscoveryResults.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/MockNuGetPackage.cs +15 -28
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/RunWorkerTests.cs +5 -4
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/SerializationTests.cs +9 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TestBase.cs +24 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/ExpectedUpdateOperationResult.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs +11 -15
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.DirsProj.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Mixed.cs +14 -8
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackageReference.cs +148 -3
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs +12 -14
- data/helpers/lib/NuGetUpdater/NuGetUpdater.sln +18 -1
- data/lib/dependabot/nuget/native_helpers.rb +41 -16
- metadata +25 -6
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ErrorType.cs +0 -12
@@ -0,0 +1,206 @@
|
|
1
|
+
using Semver;
|
2
|
+
|
3
|
+
using Xunit;
|
4
|
+
|
5
|
+
namespace DotNetPackageCorrelation;
|
6
|
+
|
7
|
+
public class RuntimePackagesTests
|
8
|
+
{
|
9
|
+
[Theory]
|
10
|
+
[MemberData(nameof(CorrelatedPackageCanBeFoundData))]
|
11
|
+
public void CorrelatedPackageCanBeFound(RuntimePackages runtimePackages, string runtimePackageName, string runtimePackageVersion, string candidatePackageName, string? expectedPackageVersion)
|
12
|
+
{
|
13
|
+
var packageMapper = PackageMapper.Load(runtimePackages);
|
14
|
+
var actualPackageVersion = packageMapper.GetPackageVersionThatShippedWithOtherPackage(runtimePackageName, SemVersion.Parse(runtimePackageVersion), candidatePackageName);
|
15
|
+
if (expectedPackageVersion is null)
|
16
|
+
{
|
17
|
+
Assert.Null(actualPackageVersion);
|
18
|
+
}
|
19
|
+
else
|
20
|
+
{
|
21
|
+
Assert.NotNull(actualPackageVersion);
|
22
|
+
Assert.Equal(expectedPackageVersion, actualPackageVersion.ToString());
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
26
|
+
public static IEnumerable<object?[]> CorrelatedPackageCanBeFoundData()
|
27
|
+
{
|
28
|
+
// package not found in specified runtime, but it is in earlier runtime; more recent runtime has that package, but that's not returned
|
29
|
+
yield return
|
30
|
+
[
|
31
|
+
// runtimePackages
|
32
|
+
new RuntimePackages()
|
33
|
+
{
|
34
|
+
Runtimes = new SortedDictionary<SemVersion, PackageSet>(SemVerComparer.Instance)
|
35
|
+
{
|
36
|
+
{
|
37
|
+
SemVersion.Parse("1.0.100"),
|
38
|
+
new PackageSet()
|
39
|
+
{
|
40
|
+
Packages = new SortedDictionary<string, SemVersion>(StringComparer.OrdinalIgnoreCase)
|
41
|
+
{
|
42
|
+
{ "Runtime.Package", SemVersion.Parse("1.0.0") },
|
43
|
+
{ "Some.Package", SemVersion.Parse("1.0.1") }
|
44
|
+
}
|
45
|
+
}
|
46
|
+
},
|
47
|
+
{
|
48
|
+
SemVersion.Parse("1.0.101"),
|
49
|
+
new PackageSet()
|
50
|
+
{
|
51
|
+
Packages = new SortedDictionary<string, SemVersion>(StringComparer.OrdinalIgnoreCase)
|
52
|
+
{
|
53
|
+
// this runtime didn't ship with a new version of "Some.Package", but the earlier release did
|
54
|
+
{ "Runtime.Package", SemVersion.Parse("1.0.1") }
|
55
|
+
}
|
56
|
+
}
|
57
|
+
},
|
58
|
+
{
|
59
|
+
SemVersion.Parse("1.0.200"),
|
60
|
+
new PackageSet()
|
61
|
+
{
|
62
|
+
Packages = new SortedDictionary<string, SemVersion>(StringComparer.OrdinalIgnoreCase)
|
63
|
+
{
|
64
|
+
// the requested package shipped with this runtime, but this runtime isn't the correct version so it's not returned
|
65
|
+
{ "Runtime.Package", SemVersion.Parse("1.0.2") },
|
66
|
+
{ "Some.Package", SemVersion.Parse("1.0.2") }
|
67
|
+
}
|
68
|
+
}
|
69
|
+
},
|
70
|
+
}
|
71
|
+
},
|
72
|
+
// runtimePackageName
|
73
|
+
"Runtime.Package",
|
74
|
+
// runtimePackageVersion
|
75
|
+
"1.0.1",
|
76
|
+
// candidatePackageName
|
77
|
+
"Some.Package",
|
78
|
+
// expectedPackageVersion
|
79
|
+
"1.0.1"
|
80
|
+
];
|
81
|
+
|
82
|
+
// package differing in case is found
|
83
|
+
yield return
|
84
|
+
[
|
85
|
+
// runtimePackages
|
86
|
+
new RuntimePackages()
|
87
|
+
{
|
88
|
+
Runtimes = new SortedDictionary<SemVersion, PackageSet>(SemVerComparer.Instance)
|
89
|
+
{
|
90
|
+
{
|
91
|
+
SemVersion.Parse("1.0.100"),
|
92
|
+
new PackageSet()
|
93
|
+
{
|
94
|
+
Packages = new SortedDictionary<string, SemVersion>(StringComparer.OrdinalIgnoreCase)
|
95
|
+
{
|
96
|
+
{ "runtime.package", SemVersion.Parse("1.0.0") },
|
97
|
+
{ "some.package", SemVersion.Parse("1.0.1") }
|
98
|
+
}
|
99
|
+
}
|
100
|
+
}
|
101
|
+
}
|
102
|
+
},
|
103
|
+
// runtimePackageName
|
104
|
+
"Runtime.Package",
|
105
|
+
// runtimePackageVersion
|
106
|
+
"1.0.0",
|
107
|
+
// candidatePackageName
|
108
|
+
"Some.Package",
|
109
|
+
// expectedPackageVersion
|
110
|
+
"1.0.1"
|
111
|
+
];
|
112
|
+
|
113
|
+
// runtime package not found by name
|
114
|
+
yield return
|
115
|
+
[
|
116
|
+
// runtimePackages
|
117
|
+
new RuntimePackages()
|
118
|
+
{
|
119
|
+
Runtimes = new SortedDictionary<SemVersion, PackageSet>(SemVerComparer.Instance)
|
120
|
+
{
|
121
|
+
{
|
122
|
+
SemVersion.Parse("1.0.100"),
|
123
|
+
new PackageSet()
|
124
|
+
{
|
125
|
+
Packages = new SortedDictionary<string, SemVersion>(StringComparer.OrdinalIgnoreCase)
|
126
|
+
{
|
127
|
+
{ "runtime.package", SemVersion.Parse("1.0.0") },
|
128
|
+
{ "some.package", SemVersion.Parse("1.0.1") }
|
129
|
+
}
|
130
|
+
}
|
131
|
+
}
|
132
|
+
}
|
133
|
+
},
|
134
|
+
// runtimePackageName
|
135
|
+
"Different.Runtime.Package",
|
136
|
+
// runtimePackageVersion
|
137
|
+
"1.0.0",
|
138
|
+
// candidatePackageName
|
139
|
+
"Some.Package",
|
140
|
+
// expectedPackageVersion
|
141
|
+
null
|
142
|
+
];
|
143
|
+
|
144
|
+
// runtime package not found by version
|
145
|
+
yield return
|
146
|
+
[
|
147
|
+
// runtimePackages
|
148
|
+
new RuntimePackages()
|
149
|
+
{
|
150
|
+
Runtimes = new SortedDictionary<SemVersion, PackageSet>(SemVerComparer.Instance)
|
151
|
+
{
|
152
|
+
{
|
153
|
+
SemVersion.Parse("1.0.100"),
|
154
|
+
new PackageSet()
|
155
|
+
{
|
156
|
+
Packages = new SortedDictionary<string, SemVersion>(StringComparer.OrdinalIgnoreCase)
|
157
|
+
{
|
158
|
+
{ "runtime.package", SemVersion.Parse("1.0.0") },
|
159
|
+
{ "some.package", SemVersion.Parse("1.0.1") }
|
160
|
+
}
|
161
|
+
}
|
162
|
+
}
|
163
|
+
}
|
164
|
+
},
|
165
|
+
// runtimePackageName
|
166
|
+
"Runtime.Package",
|
167
|
+
// runtimePackageVersion
|
168
|
+
"9.9.9",
|
169
|
+
// candidatePackageName
|
170
|
+
"Some.Package",
|
171
|
+
// expectedPackageVersion
|
172
|
+
null
|
173
|
+
];
|
174
|
+
|
175
|
+
// candidate package not found
|
176
|
+
yield return
|
177
|
+
[
|
178
|
+
// runtimePackages
|
179
|
+
new RuntimePackages()
|
180
|
+
{
|
181
|
+
Runtimes = new SortedDictionary<SemVersion, PackageSet>(SemVerComparer.Instance)
|
182
|
+
{
|
183
|
+
{
|
184
|
+
SemVersion.Parse("1.0.100"),
|
185
|
+
new PackageSet()
|
186
|
+
{
|
187
|
+
Packages = new SortedDictionary<string, SemVersion>(StringComparer.OrdinalIgnoreCase)
|
188
|
+
{
|
189
|
+
{ "runtime.package", SemVersion.Parse("1.0.0") },
|
190
|
+
{ "some.package", SemVersion.Parse("1.0.1") }
|
191
|
+
}
|
192
|
+
}
|
193
|
+
}
|
194
|
+
}
|
195
|
+
},
|
196
|
+
// runtimePackageName
|
197
|
+
"Runtime.Package",
|
198
|
+
// runtimePackageVersion
|
199
|
+
"1.0.0",
|
200
|
+
// candidatePackageName
|
201
|
+
"Package.Not.In.This.Runtime",
|
202
|
+
// expectedPackageVersion
|
203
|
+
null
|
204
|
+
];
|
205
|
+
}
|
206
|
+
}
|
@@ -7,6 +7,7 @@ namespace NuGetUpdater.Cli.Commands;
|
|
7
7
|
|
8
8
|
internal static class AnalyzeCommand
|
9
9
|
{
|
10
|
+
internal static readonly Option<string> JobIdOption = new("--job-id") { IsRequired = true };
|
10
11
|
internal static readonly Option<FileInfo> JobPathOption = new("--job-path") { IsRequired = true };
|
11
12
|
internal static readonly Option<DirectoryInfo> RepoRootOption = new("--repo-root") { IsRequired = true };
|
12
13
|
internal static readonly Option<FileInfo> DependencyFilePathOption = new("--dependency-file-path") { IsRequired = true };
|
@@ -17,6 +18,7 @@ internal static class AnalyzeCommand
|
|
17
18
|
{
|
18
19
|
Command command = new("analyze", "Determines how to update a dependency based on the workspace discovery information.")
|
19
20
|
{
|
21
|
+
JobIdOption,
|
20
22
|
JobPathOption,
|
21
23
|
RepoRootOption,
|
22
24
|
DependencyFilePathOption,
|
@@ -26,13 +28,13 @@ internal static class AnalyzeCommand
|
|
26
28
|
|
27
29
|
command.TreatUnmatchedTokensAsErrors = true;
|
28
30
|
|
29
|
-
command.SetHandler(async (jobPath, repoRoot, discoveryPath, dependencyPath, analysisDirectory) =>
|
31
|
+
command.SetHandler(async (jobId, jobPath, repoRoot, discoveryPath, dependencyPath, analysisDirectory) =>
|
30
32
|
{
|
31
33
|
var logger = new ConsoleLogger();
|
32
|
-
var (experimentsManager, _errorResult) = await ExperimentsManager.FromJobFileAsync(jobPath.FullName);
|
33
|
-
var worker = new AnalyzeWorker(experimentsManager, logger);
|
34
|
+
var (experimentsManager, _errorResult) = await ExperimentsManager.FromJobFileAsync(jobId, jobPath.FullName);
|
35
|
+
var worker = new AnalyzeWorker(jobId, experimentsManager, logger);
|
34
36
|
await worker.RunAsync(repoRoot.FullName, discoveryPath.FullName, dependencyPath.FullName, analysisDirectory.FullName);
|
35
|
-
}, JobPathOption, RepoRootOption, DiscoveryFilePathOption, DependencyFilePathOption, AnalysisFolderOption);
|
37
|
+
}, JobIdOption, JobPathOption, RepoRootOption, DiscoveryFilePathOption, DependencyFilePathOption, AnalysisFolderOption);
|
36
38
|
|
37
39
|
return command;
|
38
40
|
}
|
@@ -7,6 +7,7 @@ namespace NuGetUpdater.Cli.Commands;
|
|
7
7
|
|
8
8
|
internal static class DiscoverCommand
|
9
9
|
{
|
10
|
+
internal static readonly Option<string> JobIdOption = new("--job-id") { IsRequired = true };
|
10
11
|
internal static readonly Option<FileInfo> JobPathOption = new("--job-path") { IsRequired = true };
|
11
12
|
internal static readonly Option<DirectoryInfo> RepoRootOption = new("--repo-root") { IsRequired = true };
|
12
13
|
internal static readonly Option<string> WorkspaceOption = new("--workspace") { IsRequired = true };
|
@@ -16,6 +17,7 @@ internal static class DiscoverCommand
|
|
16
17
|
{
|
17
18
|
Command command = new("discover", "Generates a report of the workspace dependencies and where they are located.")
|
18
19
|
{
|
20
|
+
JobIdOption,
|
19
21
|
JobPathOption,
|
20
22
|
RepoRootOption,
|
21
23
|
WorkspaceOption,
|
@@ -24,27 +26,26 @@ internal static class DiscoverCommand
|
|
24
26
|
|
25
27
|
command.TreatUnmatchedTokensAsErrors = true;
|
26
28
|
|
27
|
-
command.SetHandler(async (jobPath, repoRoot, workspace, outputPath) =>
|
29
|
+
command.SetHandler(async (jobId, jobPath, repoRoot, workspace, outputPath) =>
|
28
30
|
{
|
29
|
-
var (experimentsManager,
|
30
|
-
if (
|
31
|
+
var (experimentsManager, error) = await ExperimentsManager.FromJobFileAsync(jobId, jobPath.FullName);
|
32
|
+
if (error is not null)
|
31
33
|
{
|
32
34
|
// to make testing easier, this should be a `WorkspaceDiscoveryResult` object
|
33
35
|
var discoveryErrorResult = new WorkspaceDiscoveryResult
|
34
36
|
{
|
37
|
+
Error = error,
|
35
38
|
Path = workspace,
|
36
39
|
Projects = [],
|
37
|
-
ErrorType = errorResult.ErrorType,
|
38
|
-
ErrorDetails = errorResult.ErrorDetails,
|
39
40
|
};
|
40
41
|
await DiscoveryWorker.WriteResultsAsync(repoRoot.FullName, outputPath.FullName, discoveryErrorResult);
|
41
42
|
return;
|
42
43
|
}
|
43
44
|
|
44
45
|
var logger = new ConsoleLogger();
|
45
|
-
var worker = new DiscoveryWorker(experimentsManager, logger);
|
46
|
+
var worker = new DiscoveryWorker(jobId, experimentsManager, logger);
|
46
47
|
await worker.RunAsync(repoRoot.FullName, workspace, outputPath.FullName);
|
47
|
-
}, JobPathOption, RepoRootOption, WorkspaceOption, OutputOption);
|
48
|
+
}, JobIdOption, JobPathOption, RepoRootOption, WorkspaceOption, OutputOption);
|
48
49
|
|
49
50
|
return command;
|
50
51
|
}
|
@@ -33,11 +33,11 @@ internal static class RunCommand
|
|
33
33
|
command.SetHandler(async (jobPath, repoContentsPath, apiUrl, jobId, outputPath, baseCommitSha) =>
|
34
34
|
{
|
35
35
|
var apiHandler = new HttpApiHandler(apiUrl.ToString(), jobId);
|
36
|
-
var (experimentsManager, _errorResult) = await ExperimentsManager.FromJobFileAsync(jobPath.FullName);
|
36
|
+
var (experimentsManager, _errorResult) = await ExperimentsManager.FromJobFileAsync(jobId, jobPath.FullName);
|
37
37
|
var logger = new ConsoleLogger();
|
38
|
-
var discoverWorker = new DiscoveryWorker(experimentsManager, logger);
|
39
|
-
var analyzeWorker = new AnalyzeWorker(experimentsManager, logger);
|
40
|
-
var updateWorker = new UpdaterWorker(experimentsManager, logger);
|
38
|
+
var discoverWorker = new DiscoveryWorker(jobId, experimentsManager, logger);
|
39
|
+
var analyzeWorker = new AnalyzeWorker(jobId, experimentsManager, logger);
|
40
|
+
var updateWorker = new UpdaterWorker(jobId, experimentsManager, logger);
|
41
41
|
var worker = new RunWorker(jobId, apiHandler, discoverWorker, analyzeWorker, updateWorker, logger);
|
42
42
|
await worker.RunAsync(jobPath, repoContentsPath, baseCommitSha, outputPath);
|
43
43
|
}, JobPathOption, RepoContentsPathOption, ApiUrlOption, JobIdOption, OutputPathOption, BaseCommitShaOption);
|
@@ -6,6 +6,7 @@ namespace NuGetUpdater.Cli.Commands;
|
|
6
6
|
|
7
7
|
internal static class UpdateCommand
|
8
8
|
{
|
9
|
+
internal static readonly Option<string> JobIdOption = new("--job-id") { IsRequired = true };
|
9
10
|
internal static readonly Option<FileInfo> JobPathOption = new("--job-path") { IsRequired = true };
|
10
11
|
internal static readonly Option<DirectoryInfo> RepoRootOption = new("--repo-root", () => new DirectoryInfo(Environment.CurrentDirectory)) { IsRequired = false };
|
11
12
|
internal static readonly Option<FileInfo> SolutionOrProjectFileOption = new("--solution-or-project") { IsRequired = true };
|
@@ -19,6 +20,7 @@ internal static class UpdateCommand
|
|
19
20
|
{
|
20
21
|
Command command = new("update", "Applies the changes from an analysis report to update a dependency.")
|
21
22
|
{
|
23
|
+
JobIdOption,
|
22
24
|
JobPathOption,
|
23
25
|
RepoRootOption,
|
24
26
|
SolutionOrProjectFileOption,
|
@@ -30,15 +32,25 @@ internal static class UpdateCommand
|
|
30
32
|
};
|
31
33
|
|
32
34
|
command.TreatUnmatchedTokensAsErrors = true;
|
33
|
-
|
34
|
-
command.SetHandler(async (jobPath, repoRoot, solutionOrProjectFile, dependencyName, newVersion, previousVersion, isTransitive, resultOutputPath) =>
|
35
|
+
command.SetHandler(async (context) =>
|
35
36
|
{
|
36
|
-
|
37
|
+
// since we have more than 8 arguments, we have to pull them out manually
|
38
|
+
var jobId = context.ParseResult.GetValueForOption(JobIdOption)!;
|
39
|
+
var jobPath = context.ParseResult.GetValueForOption(JobPathOption)!;
|
40
|
+
var repoRoot = context.ParseResult.GetValueForOption(RepoRootOption)!;
|
41
|
+
var solutionOrProjectFile = context.ParseResult.GetValueForOption(SolutionOrProjectFileOption)!;
|
42
|
+
var dependencyName = context.ParseResult.GetValueForOption(DependencyNameOption)!;
|
43
|
+
var newVersion = context.ParseResult.GetValueForOption(NewVersionOption)!;
|
44
|
+
var previousVersion = context.ParseResult.GetValueForOption(PreviousVersionOption)!;
|
45
|
+
var isTransitive = context.ParseResult.GetValueForOption(IsTransitiveOption);
|
46
|
+
var resultOutputPath = context.ParseResult.GetValueForOption(ResultOutputPathOption);
|
47
|
+
|
48
|
+
var (experimentsManager, _error) = await ExperimentsManager.FromJobFileAsync(jobId, jobPath.FullName);
|
37
49
|
var logger = new ConsoleLogger();
|
38
|
-
var worker = new UpdaterWorker(experimentsManager, logger);
|
50
|
+
var worker = new UpdaterWorker(jobId, experimentsManager, logger);
|
39
51
|
await worker.RunAsync(repoRoot.FullName, solutionOrProjectFile.FullName, dependencyName, previousVersion, newVersion, isTransitive, resultOutputPath);
|
40
52
|
setExitCode(0);
|
41
|
-
}
|
53
|
+
});
|
42
54
|
|
43
55
|
return command;
|
44
56
|
}
|
@@ -26,6 +26,8 @@ public partial class EntryPointTests
|
|
26
26
|
await RunAsync(path =>
|
27
27
|
[
|
28
28
|
"analyze",
|
29
|
+
"--job-id",
|
30
|
+
"TEST-JOB-ID",
|
29
31
|
"--job-path",
|
30
32
|
Path.Combine(path, "job.json"),
|
31
33
|
"--repo-root",
|
@@ -146,6 +148,8 @@ public partial class EntryPointTests
|
|
146
148
|
await RunAsync(path =>
|
147
149
|
[
|
148
150
|
"analyze",
|
151
|
+
"--job-id",
|
152
|
+
"TEST-JOB-ID",
|
149
153
|
"--job-path",
|
150
154
|
Path.Combine(path, "job.json"),
|
151
155
|
"--repo-root",
|
@@ -235,6 +239,8 @@ public partial class EntryPointTests
|
|
235
239
|
await RunAsync(path =>
|
236
240
|
[
|
237
241
|
"analyze",
|
242
|
+
"--job-id",
|
243
|
+
"TEST-JOB-ID",
|
238
244
|
"--job-path",
|
239
245
|
Path.Combine(path, "job.json"),
|
240
246
|
"--repo-root",
|
@@ -345,7 +351,7 @@ public partial class EntryPointTests
|
|
345
351
|
{
|
346
352
|
if (args[i] == "--job-path")
|
347
353
|
{
|
348
|
-
var experimentsResult = await ExperimentsManager.FromJobFileAsync(args[i + 1]);
|
354
|
+
var experimentsResult = await ExperimentsManager.FromJobFileAsync("TEST-JOB-ID", args[i + 1]);
|
349
355
|
experimentsManager = experimentsResult.ExperimentsManager;
|
350
356
|
}
|
351
357
|
}
|
@@ -1,5 +1,6 @@
|
|
1
1
|
using System.Text;
|
2
2
|
using System.Text.Json;
|
3
|
+
using System.Text.Json.Serialization;
|
3
4
|
|
4
5
|
using NuGetUpdater.Core;
|
5
6
|
using NuGetUpdater.Core.Discover;
|
@@ -25,6 +26,8 @@ public partial class EntryPointTests
|
|
25
26
|
await RunAsync(path =>
|
26
27
|
[
|
27
28
|
"discover",
|
29
|
+
"--job-id",
|
30
|
+
"TEST-JOB-ID",
|
28
31
|
"--job-path",
|
29
32
|
Path.Combine(path, "job.json"),
|
30
33
|
"--repo-root",
|
@@ -83,6 +86,8 @@ public partial class EntryPointTests
|
|
83
86
|
await RunAsync(path =>
|
84
87
|
[
|
85
88
|
"discover",
|
89
|
+
"--job-id",
|
90
|
+
"TEST-JOB-ID",
|
86
91
|
"--job-path",
|
87
92
|
Path.Combine(path, "job.json"),
|
88
93
|
"--repo-root",
|
@@ -178,6 +183,8 @@ public partial class EntryPointTests
|
|
178
183
|
await RunAsync(path =>
|
179
184
|
[
|
180
185
|
"discover",
|
186
|
+
"--job-id",
|
187
|
+
"TEST-JOB-ID",
|
181
188
|
"--job-path",
|
182
189
|
Path.Combine(path, "job.json"),
|
183
190
|
"--repo-root",
|
@@ -251,6 +258,8 @@ public partial class EntryPointTests
|
|
251
258
|
await RunAsync(path =>
|
252
259
|
[
|
253
260
|
"discover",
|
261
|
+
"--job-id",
|
262
|
+
"TEST-JOB-ID",
|
254
263
|
"--job-path",
|
255
264
|
Path.Combine(path, "job.json"),
|
256
265
|
"--repo-root",
|
@@ -321,6 +330,8 @@ public partial class EntryPointTests
|
|
321
330
|
await RunAsync(path =>
|
322
331
|
[
|
323
332
|
"discover",
|
333
|
+
"--job-id",
|
334
|
+
"TEST-JOB-ID",
|
324
335
|
"--job-path",
|
325
336
|
Path.Combine(path, "job.json"),
|
326
337
|
"--repo-root",
|
@@ -398,6 +409,8 @@ public partial class EntryPointTests
|
|
398
409
|
await RunAsync(path =>
|
399
410
|
[
|
400
411
|
"discover",
|
412
|
+
"--job-id",
|
413
|
+
"TEST-JOB-ID",
|
401
414
|
"--job-path",
|
402
415
|
jobFilePath,
|
403
416
|
"--repo-root",
|
@@ -412,8 +425,7 @@ public partial class EntryPointTests
|
|
412
425
|
{
|
413
426
|
Path = "/",
|
414
427
|
Projects = [],
|
415
|
-
|
416
|
-
ErrorDetailsPattern = "JsonException",
|
428
|
+
ErrorRegex = "Error deserializing job file contents",
|
417
429
|
}
|
418
430
|
);
|
419
431
|
}
|
@@ -445,6 +457,8 @@ public partial class EntryPointTests
|
|
445
457
|
await RunAsync(path =>
|
446
458
|
[
|
447
459
|
"discover",
|
460
|
+
"--job-id",
|
461
|
+
"TEST-JOB-ID",
|
448
462
|
"--job-path",
|
449
463
|
jobFilePath,
|
450
464
|
"--repo-root",
|
@@ -459,8 +473,7 @@ public partial class EntryPointTests
|
|
459
473
|
{
|
460
474
|
Path = "/",
|
461
475
|
Projects = [],
|
462
|
-
|
463
|
-
ErrorDetailsPattern = "not a valid requirement",
|
476
|
+
Error = new Core.Run.ApiModel.BadRequirement("not a valid requirement"),
|
464
477
|
}
|
465
478
|
);
|
466
479
|
}
|
@@ -497,7 +510,7 @@ public partial class EntryPointTests
|
|
497
510
|
switch (args[i])
|
498
511
|
{
|
499
512
|
case "--job-path":
|
500
|
-
var experimentsResult = await ExperimentsManager.FromJobFileAsync(args[i + 1]);
|
513
|
+
var experimentsResult = await ExperimentsManager.FromJobFileAsync("TEST-JOB-ID", args[i + 1]);
|
501
514
|
experimentsManager = experimentsResult.ExperimentsManager;
|
502
515
|
break;
|
503
516
|
case "--output":
|
@@ -520,11 +533,38 @@ public partial class EntryPointTests
|
|
520
533
|
|
521
534
|
resultPath ??= Path.Join(path, DiscoveryWorker.DiscoveryResultFileName);
|
522
535
|
var resultJson = await File.ReadAllTextAsync(resultPath);
|
523
|
-
var
|
536
|
+
var serializerOptions = new JsonSerializerOptions()
|
537
|
+
{
|
538
|
+
Converters = { new TestJobErrorBaseConverter() }
|
539
|
+
};
|
540
|
+
foreach (var converter in DiscoveryWorker.SerializerOptions.Converters)
|
541
|
+
{
|
542
|
+
serializerOptions.Converters.Add(converter);
|
543
|
+
}
|
544
|
+
var resultObject = JsonSerializer.Deserialize<WorkspaceDiscoveryResult>(resultJson, serializerOptions);
|
524
545
|
return resultObject!;
|
525
546
|
});
|
526
547
|
|
527
548
|
ValidateWorkspaceResult(expectedResult, actualResult, experimentsManager);
|
528
549
|
}
|
550
|
+
|
551
|
+
private class TestJobErrorBaseConverter : JsonConverter<Core.Run.ApiModel.JobErrorBase>
|
552
|
+
{
|
553
|
+
public override Core.Run.ApiModel.JobErrorBase? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
554
|
+
{
|
555
|
+
var dict = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(ref reader, options)!;
|
556
|
+
return dict["error-type"].GetString() switch
|
557
|
+
{
|
558
|
+
"illformed_requirement" => new Core.Run.ApiModel.BadRequirement(dict["error-details"].GetProperty("message").GetString()!),
|
559
|
+
"unknown_error" => new Core.Run.ApiModel.UnknownError(new Exception("Error deserializing job file contents"), "TEST-JOB-ID"),
|
560
|
+
_ => throw new NotImplementedException($"Unknown error type: {dict["error-type"]}"),
|
561
|
+
};
|
562
|
+
}
|
563
|
+
|
564
|
+
public override void Write(Utf8JsonWriter writer, Core.Run.ApiModel.JobErrorBase value, JsonSerializerOptions options)
|
565
|
+
{
|
566
|
+
throw new NotImplementedException();
|
567
|
+
}
|
568
|
+
}
|
529
569
|
}
|
530
570
|
}
|
@@ -19,6 +19,8 @@ public partial class EntryPointTests
|
|
19
19
|
await Run(path =>
|
20
20
|
[
|
21
21
|
"update",
|
22
|
+
"--job-id",
|
23
|
+
"TEST-JOB-ID",
|
22
24
|
"--job-path",
|
23
25
|
Path.Combine(path, "job.json"),
|
24
26
|
"--repo-root",
|
@@ -122,6 +124,8 @@ public partial class EntryPointTests
|
|
122
124
|
await Run(path =>
|
123
125
|
[
|
124
126
|
"update",
|
127
|
+
"--job-id",
|
128
|
+
"TEST-JOB-ID",
|
125
129
|
"--job-path",
|
126
130
|
Path.Combine(path, "job.json"),
|
127
131
|
"--repo-root",
|
@@ -202,6 +206,8 @@ public partial class EntryPointTests
|
|
202
206
|
await Run(path =>
|
203
207
|
[
|
204
208
|
"update",
|
209
|
+
"--job-id",
|
210
|
+
"TEST-JOB-ID",
|
205
211
|
"--job-path",
|
206
212
|
Path.Combine(path, "job.json"),
|
207
213
|
"--repo-root",
|
@@ -361,6 +367,8 @@ public partial class EntryPointTests
|
|
361
367
|
IEnumerable<string> executableArgs = [
|
362
368
|
executableName,
|
363
369
|
"update",
|
370
|
+
"--job-id",
|
371
|
+
"TEST-JOB-ID",
|
364
372
|
"--job-path",
|
365
373
|
Path.Combine(tempDir.DirectoryPath, "job.json"),
|
366
374
|
"--repo-root",
|
@@ -7,6 +7,7 @@ using NuGet.Frameworks;
|
|
7
7
|
using NuGet.Versioning;
|
8
8
|
|
9
9
|
using NuGetUpdater.Core.Discover;
|
10
|
+
using NuGetUpdater.Core.Run.ApiModel;
|
10
11
|
|
11
12
|
namespace NuGetUpdater.Core.Analyze;
|
12
13
|
|
@@ -16,6 +17,7 @@ public partial class AnalyzeWorker : IAnalyzeWorker
|
|
16
17
|
{
|
17
18
|
public const string AnalysisDirectoryName = "./.dependabot/analysis";
|
18
19
|
|
20
|
+
private readonly string _jobId;
|
19
21
|
private readonly ExperimentsManager _experimentsManager;
|
20
22
|
private readonly ILogger _logger;
|
21
23
|
|
@@ -25,8 +27,9 @@ public partial class AnalyzeWorker : IAnalyzeWorker
|
|
25
27
|
Converters = { new JsonStringEnumConverter(), new RequirementArrayConverter() },
|
26
28
|
};
|
27
29
|
|
28
|
-
public AnalyzeWorker(ExperimentsManager experimentsManager, ILogger logger)
|
30
|
+
public AnalyzeWorker(string jobId, ExperimentsManager experimentsManager, ILogger logger)
|
29
31
|
{
|
32
|
+
_jobId = jobId;
|
30
33
|
_experimentsManager = experimentsManager;
|
31
34
|
_logger = logger;
|
32
35
|
}
|
@@ -48,26 +51,11 @@ public partial class AnalyzeWorker : IAnalyzeWorker
|
|
48
51
|
{
|
49
52
|
analysisResult = await RunAsync(repoRoot, discovery, dependencyInfo);
|
50
53
|
}
|
51
|
-
catch (HttpRequestException ex)
|
52
|
-
when (ex.StatusCode == HttpStatusCode.Unauthorized || ex.StatusCode == HttpStatusCode.Forbidden)
|
53
|
-
{
|
54
|
-
var localPath = PathHelper.JoinPath(repoRoot, discovery.Path);
|
55
|
-
using var nugetContext = new NuGetContext(localPath);
|
56
|
-
analysisResult = new AnalysisResult
|
57
|
-
{
|
58
|
-
ErrorType = ErrorType.AuthenticationFailure,
|
59
|
-
ErrorDetails = "(" + string.Join("|", nugetContext.PackageSources.Select(s => s.Source)) + ")",
|
60
|
-
UpdatedVersion = string.Empty,
|
61
|
-
CanUpdate = false,
|
62
|
-
UpdatedDependencies = [],
|
63
|
-
};
|
64
|
-
}
|
65
54
|
catch (Exception ex)
|
66
55
|
{
|
67
56
|
analysisResult = new AnalysisResult
|
68
57
|
{
|
69
|
-
|
70
|
-
ErrorDetails = ex.ToString(),
|
58
|
+
Error = JobErrorBase.ErrorFromException(ex, _jobId, PathHelper.JoinPath(repoRoot, discovery.Path)),
|
71
59
|
UpdatedVersion = string.Empty,
|
72
60
|
CanUpdate = false,
|
73
61
|
UpdatedDependencies = [],
|
@@ -79,6 +67,8 @@ public partial class AnalyzeWorker : IAnalyzeWorker
|
|
79
67
|
|
80
68
|
public async Task<AnalysisResult> RunAsync(string repoRoot, WorkspaceDiscoveryResult discovery, DependencyInfo dependencyInfo)
|
81
69
|
{
|
70
|
+
MSBuildHelper.RegisterMSBuild(repoRoot, repoRoot);
|
71
|
+
|
82
72
|
var startingDirectory = PathHelper.JoinPath(repoRoot, discovery.Path);
|
83
73
|
|
84
74
|
_logger.Info($"Starting analysis of {dependencyInfo.Name}...");
|
@@ -423,6 +413,7 @@ public partial class AnalyzeWorker : IAnalyzeWorker
|
|
423
413
|
.SelectMany(p => p.TargetFrameworks)
|
424
414
|
.Select(NuGetFramework.Parse)
|
425
415
|
.Distinct()
|
416
|
+
.Select(f => f.GetShortFolderName())
|
426
417
|
.ToImmutableArray();
|
427
418
|
|
428
419
|
// When updating peer dependencies, we only need to consider top-level dependencies.
|
@@ -7,10 +7,10 @@ namespace NuGetUpdater.Core.Analyze;
|
|
7
7
|
|
8
8
|
internal static class DependencyFinder
|
9
9
|
{
|
10
|
-
public static async Task<ImmutableDictionary<
|
10
|
+
public static async Task<ImmutableDictionary<string, ImmutableArray<Dependency>>> GetDependenciesAsync(
|
11
11
|
string repoRoot,
|
12
12
|
string projectPath,
|
13
|
-
IEnumerable<
|
13
|
+
IEnumerable<string> frameworks,
|
14
14
|
ImmutableHashSet<string> packageIds,
|
15
15
|
NuGetVersion version,
|
16
16
|
NuGetContext nugetContext,
|
@@ -23,13 +23,13 @@ internal static class DependencyFinder
|
|
23
23
|
.Select(id => new Dependency(id, versionString, DependencyType.Unknown))
|
24
24
|
.ToImmutableArray();
|
25
25
|
|
26
|
-
var result = ImmutableDictionary.CreateBuilder<
|
26
|
+
var result = ImmutableDictionary.CreateBuilder<string, ImmutableArray<Dependency>>();
|
27
27
|
foreach (var framework in frameworks)
|
28
28
|
{
|
29
29
|
var dependencies = await MSBuildHelper.GetAllPackageDependenciesAsync(
|
30
30
|
repoRoot,
|
31
31
|
projectPath,
|
32
|
-
framework
|
32
|
+
framework,
|
33
33
|
packages,
|
34
34
|
experimentsManager,
|
35
35
|
logger);
|
@@ -7,7 +7,7 @@ using NuGetUpdater.Core;
|
|
7
7
|
|
8
8
|
internal static class Extensions
|
9
9
|
{
|
10
|
-
public static ImmutableArray<Dependency> GetDependencies(this ImmutableDictionary<
|
10
|
+
public static ImmutableArray<Dependency> GetDependencies(this ImmutableDictionary<string, ImmutableArray<Dependency>> dependenciesByTfm)
|
11
11
|
{
|
12
12
|
Dictionary<string, Dependency> dependencies = [];
|
13
13
|
foreach (var (_framework, dependenciesForTfm) in dependenciesByTfm)
|