dependabot-nuget 0.322.0 → 0.322.1
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/NuGetUpdater.Cli.Test/EntryPointTests.Analyze.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Discover.cs +10 -23
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Run.cs +9 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Update.cs +15 -232
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/SdkProjectDiscovery.cs +1 -154
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ExperimentsManager.cs +3 -12
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/PullRequestBodyGenerator/AzurePackageDetailFinder.cs +30 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/PullRequestBodyGenerator/DetailedPullRequestBodyGenerator.cs +237 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/PullRequestBodyGenerator/GitHubPackageDetailFinder.cs +101 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/PullRequestBodyGenerator/GitLabPackageDetailFinder.cs +107 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/PullRequestBodyGenerator/HttpFetcher.cs +32 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/PullRequestBodyGenerator/IHttpFetcher.cs +30 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/PullRequestBodyGenerator/IPackageDetailFinder.cs +47 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/PullRequestBodyGenerator/IPullRequestBodyGenerator.cs +11 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/PullRequestBodyGenerator/SimplePullRequestBodyGenerator.cs +15 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/PullRequestTextGenerator.cs +7 -3
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/RunWorker.cs +3 -525
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/UpdateHandlers/CreateSecurityUpdatePullRequestHandler.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/UpdateHandlers/GroupUpdateAllVersionsHandler.cs +2 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/UpdateHandlers/RefreshGroupUpdatePullRequestHandler.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/UpdateHandlers/RefreshSecurityUpdatePullRequestHandler.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/UpdateHandlers/RefreshVersionUpdatePullRequestHandler.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/FileWriters/FileWriterWorker.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/FileWriters/XmlFileWriter.cs +10 -3
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackageReferenceUpdater.cs +1 -856
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdaterWorker.cs +16 -200
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +6 -556
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTests.cs +9 -73
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Clone/CloneWorkerTests.cs +2 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/DependencySolver/MSBuildDependencySolverTests.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTestBase.cs +1 -20
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.PackagesConfig.cs +3 -62
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Project.cs +13 -563
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs +20 -267
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/SdkProjectDiscoveryTests.cs +2 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/EndToEndTests.cs +131 -131
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/MiscellaneousTests.cs +0 -203
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/PullRequestBodyGenerator/DetailedPullRequestBodyGeneratorTests.cs +871 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/PullRequestBodyGenerator/IPackageDetailFinderTests.cs +28 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/PullRequestBodyGenerator/TestHttpFetcher.cs +23 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/PullRequestTextTests.cs +3 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/SerializationTests.cs +6 -12
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/UpdateHandlers/CreateSecurityUpdatePullRequestHandlerTests.cs +6 -6
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/UpdateHandlers/GroupUpdateAllVersionsHandlerTests.cs +18 -18
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/UpdateHandlers/RefreshGroupUpdatePullRequestHandlerTests.cs +15 -15
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/UpdateHandlers/RefreshSecurityUpdatePullRequestHandlerTests.cs +21 -21
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/UpdateHandlers/RefreshVersionUpdatePullRequestHandlerTests.cs +15 -15
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/UpdateHandlers/UpdateHandlersTestsBase.cs +1 -8
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/FileWriters/FileWriterWorkerTests.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/FileWriters/XmlFileWriterTests.cs +85 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/PackageReferenceUpdaterTests.cs +1 -159
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/MSBuildHelperTests.cs +10 -660
- metadata +16 -10
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/RunResult.cs +0 -13
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/PullRequestMessageTests.cs +0 -296
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/RunWorkerTests.cs +0 -3592
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/UpdatePermittedAndMessageTests.cs +0 -457
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.DirsProj.cs +0 -378
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/SdkPackageUpdaterHelperTests.cs +0 -175
@@ -1,12 +1,8 @@
|
|
1
1
|
using System.Collections.Immutable;
|
2
|
-
using System.IO;
|
3
2
|
using System.IO.Enumeration;
|
4
|
-
using System.Text;
|
5
3
|
using System.Text.Json;
|
6
4
|
using System.Text.Json.Serialization;
|
7
5
|
|
8
|
-
using Microsoft.Extensions.FileSystemGlobbing;
|
9
|
-
|
10
6
|
using NuGet.Versioning;
|
11
7
|
|
12
8
|
using NuGetUpdater.Core.Analyze;
|
@@ -49,35 +45,12 @@ public class RunWorker
|
|
49
45
|
var jobFileContent = await File.ReadAllTextAsync(jobFilePath.FullName);
|
50
46
|
var jobWrapper = Deserialize(jobFileContent);
|
51
47
|
var experimentsManager = ExperimentsManager.GetExperimentsManager(jobWrapper.Job.Experiments);
|
52
|
-
|
53
|
-
if (experimentsManager.UseLegacyUpdateHandler)
|
54
|
-
{
|
55
|
-
// only the legacy handler writes this file
|
56
|
-
var resultJson = JsonSerializer.Serialize(result, SerializerOptions);
|
57
|
-
await File.WriteAllTextAsync(outputFilePath.FullName, resultJson);
|
58
|
-
}
|
48
|
+
await RunAsync(jobWrapper.Job, repoContentsPath, caseInsensitiveRepoContentsPath, baseCommitSha, experimentsManager);
|
59
49
|
}
|
60
50
|
|
61
|
-
public async Task
|
51
|
+
public async Task RunAsync(Job job, DirectoryInfo repoContentsPath, DirectoryInfo? caseInsensitiveRepoContentsPath, string baseCommitSha, ExperimentsManager experimentsManager)
|
62
52
|
{
|
63
|
-
|
64
|
-
if (experimentsManager.UseLegacyUpdateHandler)
|
65
|
-
{
|
66
|
-
result = await RunWithErrorHandlingAsync(job, repoContentsPath, caseInsensitiveRepoContentsPath, baseCommitSha, experimentsManager);
|
67
|
-
}
|
68
|
-
else
|
69
|
-
{
|
70
|
-
await RunScenarioHandlersWithErrorHandlingAsync(job, repoContentsPath, caseInsensitiveRepoContentsPath, baseCommitSha, experimentsManager);
|
71
|
-
|
72
|
-
// the group updater doesn't return this, so we provide an empty object
|
73
|
-
result = new RunResult()
|
74
|
-
{
|
75
|
-
Base64DependencyFiles = [],
|
76
|
-
BaseCommitSha = baseCommitSha,
|
77
|
-
};
|
78
|
-
}
|
79
|
-
|
80
|
-
return result;
|
53
|
+
await RunScenarioHandlersWithErrorHandlingAsync(job, repoContentsPath, caseInsensitiveRepoContentsPath, baseCommitSha, experimentsManager);
|
81
54
|
}
|
82
55
|
|
83
56
|
private static readonly ImmutableArray<IUpdateHandler> UpdateHandlers =
|
@@ -115,252 +88,6 @@ public class RunWorker
|
|
115
88
|
await _apiHandler.MarkAsProcessed(new(baseCommitSha));
|
116
89
|
}
|
117
90
|
|
118
|
-
private async Task<RunResult> RunWithErrorHandlingAsync(Job job, DirectoryInfo repoContentsPath, DirectoryInfo? caseInsensitiveRepoContentsPath, string baseCommitSha, ExperimentsManager experimentsManager)
|
119
|
-
{
|
120
|
-
JobErrorBase? error = null;
|
121
|
-
var currentDirectory = repoContentsPath.FullName; // used for error reporting below
|
122
|
-
var runResult = new RunResult()
|
123
|
-
{
|
124
|
-
Base64DependencyFiles = [],
|
125
|
-
BaseCommitSha = baseCommitSha,
|
126
|
-
};
|
127
|
-
|
128
|
-
try
|
129
|
-
{
|
130
|
-
MSBuildHelper.RegisterMSBuild(repoContentsPath.FullName, repoContentsPath.FullName, _logger);
|
131
|
-
|
132
|
-
var allDependencyFiles = new Dictionary<string, DependencyFile>();
|
133
|
-
foreach (var directory in job.GetAllDirectories())
|
134
|
-
{
|
135
|
-
var localPath = PathHelper.JoinPath(repoContentsPath.FullName, directory);
|
136
|
-
currentDirectory = localPath;
|
137
|
-
var result = await RunForDirectory(job, repoContentsPath, caseInsensitiveRepoContentsPath, directory, baseCommitSha, experimentsManager);
|
138
|
-
foreach (var dependencyFile in result.Base64DependencyFiles)
|
139
|
-
{
|
140
|
-
var uniqueKey = Path.GetFullPath(Path.Join(dependencyFile.Directory, dependencyFile.Name)).NormalizePathToUnix().EnsurePrefix("/");
|
141
|
-
allDependencyFiles[uniqueKey] = dependencyFile;
|
142
|
-
}
|
143
|
-
}
|
144
|
-
|
145
|
-
runResult = new RunResult()
|
146
|
-
{
|
147
|
-
Base64DependencyFiles = allDependencyFiles.Values.ToArray(),
|
148
|
-
BaseCommitSha = baseCommitSha,
|
149
|
-
};
|
150
|
-
}
|
151
|
-
catch (Exception ex)
|
152
|
-
{
|
153
|
-
error = JobErrorBase.ErrorFromException(ex, _jobId, currentDirectory);
|
154
|
-
}
|
155
|
-
|
156
|
-
if (error is not null)
|
157
|
-
{
|
158
|
-
await _apiHandler.RecordUpdateJobError(error, _logger);
|
159
|
-
}
|
160
|
-
|
161
|
-
await _apiHandler.MarkAsProcessed(new(baseCommitSha));
|
162
|
-
|
163
|
-
return runResult;
|
164
|
-
}
|
165
|
-
|
166
|
-
private async Task<RunResult> RunForDirectory(Job job, DirectoryInfo originalRepoContentsPath, DirectoryInfo? caseInsensitiveRepoContentsPath, string repoDirectory, string baseCommitSha, ExperimentsManager experimentsManager)
|
167
|
-
{
|
168
|
-
var repoContentsPath = caseInsensitiveRepoContentsPath ?? originalRepoContentsPath;
|
169
|
-
var discoveryResult = await _discoveryWorker.RunAsync(repoContentsPath.FullName, repoDirectory);
|
170
|
-
_logger.ReportDiscovery(discoveryResult);
|
171
|
-
|
172
|
-
if (discoveryResult.Error is not null)
|
173
|
-
{
|
174
|
-
// this is unrecoverable
|
175
|
-
await _apiHandler.RecordUpdateJobError(discoveryResult.Error, _logger);
|
176
|
-
return new()
|
177
|
-
{
|
178
|
-
Base64DependencyFiles = [],
|
179
|
-
BaseCommitSha = baseCommitSha,
|
180
|
-
};
|
181
|
-
}
|
182
|
-
|
183
|
-
// report dependencies
|
184
|
-
var discoveredUpdatedDependencies = GetUpdatedDependencyListFromDiscovery(discoveryResult, originalRepoContentsPath.FullName, _logger);
|
185
|
-
await _apiHandler.UpdateDependencyList(discoveredUpdatedDependencies);
|
186
|
-
|
187
|
-
var incrementMetric = GetIncrementMetric(job);
|
188
|
-
await _apiHandler.IncrementMetric(incrementMetric);
|
189
|
-
|
190
|
-
// TODO: pull out relevant dependencies, then check each for updates and track the changes
|
191
|
-
var actualUpdatedDependencies = new List<ReportedDependency>();
|
192
|
-
|
193
|
-
// track original contents for later handling
|
194
|
-
var tracker = new ModifiedFilesTracker(originalRepoContentsPath, _logger);
|
195
|
-
await tracker.StartTrackingAsync(discoveryResult);
|
196
|
-
|
197
|
-
// do update
|
198
|
-
var updateOperationsPerformed = new List<UpdateOperationBase>();
|
199
|
-
var existingPullRequests = job.GetAllExistingPullRequests();
|
200
|
-
var unhandledPullRequestDependenciesSet = existingPullRequests
|
201
|
-
.Select(pr => pr.Item2.Select(d => d.DependencyName).ToHashSet(StringComparer.OrdinalIgnoreCase))
|
202
|
-
.ToHashSet();
|
203
|
-
var remainingSecurityIssues = job.SecurityAdvisories
|
204
|
-
.Select(s => s.DependencyName)
|
205
|
-
.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
206
|
-
var updateOperations = GetUpdateOperations(discoveryResult).ToArray();
|
207
|
-
|
208
|
-
foreach (var updateOperation in updateOperations)
|
209
|
-
{
|
210
|
-
var dependency = updateOperation.Dependency;
|
211
|
-
var (isAllowed, message) = UpdatePermittedAndMessage(job, updateOperation.Dependency);
|
212
|
-
if (message is SecurityUpdateNotNeeded sec)
|
213
|
-
{
|
214
|
-
// flag this update operation as having been handled
|
215
|
-
remainingSecurityIssues.RemoveWhere(r => r.Equals(dependency.Name, StringComparison.OrdinalIgnoreCase));
|
216
|
-
|
217
|
-
// we only want to send this message if we're in the only update operation for this dependency, otherwise it's ambiguous
|
218
|
-
var updateOperationsWithSameName = updateOperations.Where(u => u.Dependency.Name.Equals(dependency.Name, StringComparison.OrdinalIgnoreCase))
|
219
|
-
.ToArray();
|
220
|
-
if (updateOperationsWithSameName.Length > 1)
|
221
|
-
{
|
222
|
-
// suppress the message
|
223
|
-
message = null;
|
224
|
-
}
|
225
|
-
}
|
226
|
-
|
227
|
-
await SendApiMessage(message);
|
228
|
-
if (!isAllowed)
|
229
|
-
{
|
230
|
-
continue;
|
231
|
-
}
|
232
|
-
|
233
|
-
_logger.Info($"Updating [{dependency.Name}] in [{updateOperation.ProjectPath}]");
|
234
|
-
|
235
|
-
var dependencyInfo = GetDependencyInfo(job, dependency);
|
236
|
-
var analysisResult = await _analyzeWorker.RunAsync(repoContentsPath.FullName, discoveryResult, dependencyInfo);
|
237
|
-
_logger.ReportAnalysis(analysisResult);
|
238
|
-
|
239
|
-
if (analysisResult.Error is not null)
|
240
|
-
{
|
241
|
-
await _apiHandler.RecordUpdateJobError(analysisResult.Error, _logger);
|
242
|
-
continue;
|
243
|
-
}
|
244
|
-
|
245
|
-
if (analysisResult.CanUpdate)
|
246
|
-
{
|
247
|
-
if (!job.UpdatingAPullRequest)
|
248
|
-
{
|
249
|
-
var updatedDependencyFromAnalysis = analysisResult.UpdatedDependencies
|
250
|
-
.FirstOrDefault(d => d.Name.Equals(dependency.Name, StringComparison.OrdinalIgnoreCase));
|
251
|
-
if (updatedDependencyFromAnalysis is not null)
|
252
|
-
{
|
253
|
-
var existingPullRequest = job.GetExistingPullRequestForDependencies([updatedDependencyFromAnalysis], considerVersions: true);
|
254
|
-
if (existingPullRequest is not null)
|
255
|
-
{
|
256
|
-
await SendApiMessage(new PullRequestExistsForLatestVersion(dependency.Name, analysisResult.UpdatedVersion));
|
257
|
-
unhandledPullRequestDependenciesSet.RemoveWhere(handled => handled.Count == 1 && handled.Contains(dependency.Name));
|
258
|
-
continue;
|
259
|
-
}
|
260
|
-
}
|
261
|
-
}
|
262
|
-
|
263
|
-
// TODO: this is inefficient, but not likely causing a bottleneck
|
264
|
-
var previousDependency = discoveredUpdatedDependencies.Dependencies
|
265
|
-
.Single(d => d.Name == dependency.Name && d.Requirements.Single().File == updateOperation.ProjectPath);
|
266
|
-
var updatedDependency = new ReportedDependency()
|
267
|
-
{
|
268
|
-
Name = dependency.Name,
|
269
|
-
Version = analysisResult.UpdatedVersion,
|
270
|
-
Requirements =
|
271
|
-
[
|
272
|
-
new ReportedRequirement()
|
273
|
-
{
|
274
|
-
File = updateOperation.ProjectPath,
|
275
|
-
Requirement = analysisResult.UpdatedVersion,
|
276
|
-
Groups = previousDependency.Requirements.Single().Groups,
|
277
|
-
Source = new RequirementSource()
|
278
|
-
{
|
279
|
-
SourceUrl = analysisResult.UpdatedDependencies.FirstOrDefault(d => d.Name == dependency.Name)?.InfoUrl,
|
280
|
-
},
|
281
|
-
}
|
282
|
-
],
|
283
|
-
PreviousVersion = dependency.Version,
|
284
|
-
PreviousRequirements = previousDependency.Requirements,
|
285
|
-
};
|
286
|
-
|
287
|
-
var projectDiscovery = discoveryResult.GetProjectDiscoveryFromPath(updateOperation.ProjectPath);
|
288
|
-
var updateResult = await _updaterWorker.RunAsync(repoContentsPath.FullName, updateOperation.ProjectPath, dependency.Name, dependency.Version!, analysisResult.UpdatedVersion, isTransitive: dependency.IsTransitive);
|
289
|
-
if (updateResult.Error is not null)
|
290
|
-
{
|
291
|
-
await _apiHandler.RecordUpdateJobError(updateResult.Error, _logger);
|
292
|
-
}
|
293
|
-
else
|
294
|
-
{
|
295
|
-
actualUpdatedDependencies.Add(updatedDependency);
|
296
|
-
}
|
297
|
-
|
298
|
-
var patchedUpdateOperations = PatchInOldVersions(updateResult.UpdateOperations, projectDiscovery);
|
299
|
-
updateOperationsPerformed.AddRange(patchedUpdateOperations);
|
300
|
-
}
|
301
|
-
}
|
302
|
-
|
303
|
-
// create PR - we need to manually check file contents; we can't easily use `git status` in tests
|
304
|
-
var updatedDependencyFiles = await tracker.StopTrackingAsync();
|
305
|
-
var normalizedUpdateOperationsPerformed = UpdateOperationBase.NormalizeUpdateOperationCollection(repoContentsPath.FullName, updateOperationsPerformed);
|
306
|
-
var report = UpdateOperationBase.GenerateUpdateOperationReport(normalizedUpdateOperationsPerformed);
|
307
|
-
_logger.Info(report);
|
308
|
-
|
309
|
-
var sortedUpdatedDependencies = actualUpdatedDependencies.OrderBy(d => d.Name, StringComparer.OrdinalIgnoreCase).ToArray();
|
310
|
-
var resultMessage = GetPullRequestApiMessage(job, [.. updatedDependencyFiles], sortedUpdatedDependencies, normalizedUpdateOperationsPerformed, baseCommitSha);
|
311
|
-
switch (resultMessage)
|
312
|
-
{
|
313
|
-
case ClosePullRequest close:
|
314
|
-
var closePrDependencies = close.DependencyNames.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
315
|
-
remainingSecurityIssues.RemoveWhere(closePrDependencies.Contains);
|
316
|
-
if (!unhandledPullRequestDependenciesSet.Remove(closePrDependencies))
|
317
|
-
{
|
318
|
-
// this PR was handled earlier, we don't want to now close it; suppress the message
|
319
|
-
resultMessage = null;
|
320
|
-
}
|
321
|
-
break;
|
322
|
-
case CreatePullRequest create:
|
323
|
-
var createPrDependencies = create.Dependencies.Select(d => d.Name).ToHashSet(StringComparer.OrdinalIgnoreCase);
|
324
|
-
remainingSecurityIssues.RemoveWhere(createPrDependencies.Contains);
|
325
|
-
break;
|
326
|
-
case UpdatePullRequest update:
|
327
|
-
var updatePrDependencies = update.DependencyNames.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
328
|
-
remainingSecurityIssues.RemoveWhere(updatePrDependencies.Contains);
|
329
|
-
break;
|
330
|
-
}
|
331
|
-
|
332
|
-
await SendApiMessage(resultMessage);
|
333
|
-
|
334
|
-
// for each security advisory that _didn't_ result in a pr, report it
|
335
|
-
foreach (var depName in remainingSecurityIssues)
|
336
|
-
{
|
337
|
-
await SendApiMessage(new SecurityUpdateNotNeeded(depName));
|
338
|
-
}
|
339
|
-
|
340
|
-
var result = new RunResult()
|
341
|
-
{
|
342
|
-
Base64DependencyFiles = tracker.OriginalDependencyFileContents.OrderBy(kvp => kvp.Key).Select(kvp =>
|
343
|
-
{
|
344
|
-
var fullPath = kvp.Key.FullyNormalizedRootedPath();
|
345
|
-
var rawContent = Encoding.UTF8.GetBytes(kvp.Value);
|
346
|
-
if (tracker.OriginalDependencyFileBOMs[kvp.Key])
|
347
|
-
{
|
348
|
-
rawContent = Encoding.UTF8.GetPreamble().Concat(rawContent).ToArray();
|
349
|
-
}
|
350
|
-
|
351
|
-
return new DependencyFile()
|
352
|
-
{
|
353
|
-
Name = Path.GetFileName(fullPath),
|
354
|
-
Content = Convert.ToBase64String(rawContent),
|
355
|
-
ContentEncoding = "base64",
|
356
|
-
Directory = Path.GetDirectoryName(fullPath)!.NormalizePathToUnix(),
|
357
|
-
};
|
358
|
-
}).ToArray(),
|
359
|
-
BaseCommitSha = baseCommitSha,
|
360
|
-
};
|
361
|
-
return result;
|
362
|
-
}
|
363
|
-
|
364
91
|
internal static ImmutableArray<UpdateOperationBase> PatchInOldVersions(ImmutableArray<UpdateOperationBase> updateOperations, ProjectDiscoveryResult? projectDiscovery)
|
365
92
|
{
|
366
93
|
if (projectDiscovery is null)
|
@@ -377,115 +104,6 @@ public class RunWorker
|
|
377
104
|
return patchedUpdateOperations;
|
378
105
|
}
|
379
106
|
|
380
|
-
private async Task SendApiMessage(MessageBase? message)
|
381
|
-
{
|
382
|
-
if (message is null)
|
383
|
-
{
|
384
|
-
return;
|
385
|
-
}
|
386
|
-
|
387
|
-
var report = message.GetReport();
|
388
|
-
_logger.Info(report);
|
389
|
-
switch (message)
|
390
|
-
{
|
391
|
-
case JobErrorBase error:
|
392
|
-
await _apiHandler.RecordUpdateJobError(error, _logger);
|
393
|
-
break;
|
394
|
-
case CreatePullRequest create:
|
395
|
-
await _apiHandler.CreatePullRequest(create);
|
396
|
-
break;
|
397
|
-
case ClosePullRequest close:
|
398
|
-
await _apiHandler.ClosePullRequest(close);
|
399
|
-
break;
|
400
|
-
case UpdatePullRequest update:
|
401
|
-
await _apiHandler.UpdatePullRequest(update);
|
402
|
-
break;
|
403
|
-
default:
|
404
|
-
throw new NotSupportedException($"unsupported api message: {message.GetType().Name}");
|
405
|
-
}
|
406
|
-
}
|
407
|
-
|
408
|
-
internal static MessageBase? GetPullRequestApiMessage(
|
409
|
-
Job job,
|
410
|
-
DependencyFile[] updatedFiles,
|
411
|
-
ReportedDependency[] updatedDependencies,
|
412
|
-
ImmutableArray<UpdateOperationBase> updateOperationsPerformed,
|
413
|
-
string baseCommitSha
|
414
|
-
)
|
415
|
-
{
|
416
|
-
var updatedDependencyNames = updateOperationsPerformed.Select(u => u.DependencyName).OrderBy(d => d, StringComparer.OrdinalIgnoreCase).ToArray();
|
417
|
-
var updatedDependenciesSet = updatedDependencyNames.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
418
|
-
|
419
|
-
// all pull request dependencies with optional group name
|
420
|
-
var existingPullRequests = job.GetAllExistingPullRequests();
|
421
|
-
var existingPullRequest = existingPullRequests.FirstOrDefault(pr => pr.Item2.Select(d => d.DependencyName).All(updatedDependenciesSet.Contains));
|
422
|
-
if (existingPullRequest is null && updatedFiles.Length == 0)
|
423
|
-
{
|
424
|
-
// it's possible that we were asked to update a specific package, but it's no longer there; in that case find _that_ specific PR
|
425
|
-
var requestedUpdates = job.Dependencies.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
426
|
-
existingPullRequest = existingPullRequests.FirstOrDefault(pr => pr.Item2.Select(d => d.DependencyName).All(requestedUpdates.Contains));
|
427
|
-
}
|
428
|
-
|
429
|
-
var expectedSecurityUpdateDependencyNames = job.SecurityAdvisories.Select(sa => sa.DependencyName).ToHashSet(StringComparer.OrdinalIgnoreCase);
|
430
|
-
var isExpectedSecurityUpdate = updatedDependenciesSet.All(expectedSecurityUpdateDependencyNames.Contains);
|
431
|
-
|
432
|
-
if (existingPullRequest is { })
|
433
|
-
{
|
434
|
-
if (job.UpdatingAPullRequest)
|
435
|
-
{
|
436
|
-
return new UpdatePullRequest()
|
437
|
-
{
|
438
|
-
DependencyGroup = existingPullRequest.Item1,
|
439
|
-
DependencyNames = [.. updatedDependencyNames],
|
440
|
-
UpdatedDependencyFiles = updatedFiles,
|
441
|
-
BaseCommitSha = baseCommitSha,
|
442
|
-
CommitMessage = PullRequestTextGenerator.GetPullRequestCommitMessage(job, updateOperationsPerformed, existingPullRequest.Item1),
|
443
|
-
PrTitle = PullRequestTextGenerator.GetPullRequestTitle(job, updateOperationsPerformed, existingPullRequest.Item1),
|
444
|
-
PrBody = PullRequestTextGenerator.GetPullRequestBody(job, updateOperationsPerformed, existingPullRequest.Item1),
|
445
|
-
};
|
446
|
-
}
|
447
|
-
else
|
448
|
-
{
|
449
|
-
if (updatedDependenciesSet.Count == 0)
|
450
|
-
{
|
451
|
-
// nothing found, close current
|
452
|
-
return new ClosePullRequest()
|
453
|
-
{
|
454
|
-
DependencyNames = [.. existingPullRequest.Item2.Select(d => d.DependencyName)],
|
455
|
-
Reason = "dependency_removed",
|
456
|
-
};
|
457
|
-
}
|
458
|
-
else
|
459
|
-
{
|
460
|
-
// found but no longer required
|
461
|
-
return new ClosePullRequest()
|
462
|
-
{
|
463
|
-
DependencyNames = [.. updatedDependenciesSet],
|
464
|
-
Reason = "up_to_date",
|
465
|
-
};
|
466
|
-
}
|
467
|
-
}
|
468
|
-
}
|
469
|
-
else
|
470
|
-
{
|
471
|
-
if (updatedDependencyNames.Any())
|
472
|
-
{
|
473
|
-
return new CreatePullRequest()
|
474
|
-
{
|
475
|
-
Dependencies = updatedDependencies,
|
476
|
-
UpdatedDependencyFiles = updatedFiles,
|
477
|
-
BaseCommitSha = baseCommitSha,
|
478
|
-
CommitMessage = PullRequestTextGenerator.GetPullRequestCommitMessage(job, updateOperationsPerformed, dependencyGroupName: null),
|
479
|
-
PrTitle = PullRequestTextGenerator.GetPullRequestTitle(job, updateOperationsPerformed, dependencyGroupName: null),
|
480
|
-
PrBody = PullRequestTextGenerator.GetPullRequestBody(job, updateOperationsPerformed, dependencyGroupName: null),
|
481
|
-
DependencyGroup = null,
|
482
|
-
};
|
483
|
-
}
|
484
|
-
}
|
485
|
-
|
486
|
-
return null;
|
487
|
-
}
|
488
|
-
|
489
107
|
internal static IEnumerable<(string ProjectPath, Dependency Dependency)> GetUpdateOperations(WorkspaceDiscoveryResult discovery)
|
490
108
|
{
|
491
109
|
// discovery is grouped by project/file then dependency, but we want to pivot and return a list of update operations sorted by dependency name then file path
|
@@ -534,146 +152,6 @@ public class RunWorker
|
|
534
152
|
}
|
535
153
|
}
|
536
154
|
|
537
|
-
internal static IncrementMetric GetIncrementMetric(Job job)
|
538
|
-
{
|
539
|
-
var isSecurityUpdate = job.AllowedUpdates.Any(a => a.UpdateType == UpdateType.Security) || job.SecurityUpdatesOnly;
|
540
|
-
var metricOperation = isSecurityUpdate ?
|
541
|
-
(job.UpdatingAPullRequest ? "update_security_pr" : "create_security_pr")
|
542
|
-
: (job.UpdatingAPullRequest ? "update_version_pr" : "group_update_all_versions");
|
543
|
-
var increment = new IncrementMetric()
|
544
|
-
{
|
545
|
-
Metric = "updater.started",
|
546
|
-
Tags = { ["operation"] = metricOperation },
|
547
|
-
};
|
548
|
-
return increment;
|
549
|
-
}
|
550
|
-
|
551
|
-
internal static (bool, MessageBase?) UpdatePermittedAndMessage(Job job, Dependency dependency)
|
552
|
-
{
|
553
|
-
if (dependency.Name.Equals("Microsoft.NET.Sdk", StringComparison.OrdinalIgnoreCase))
|
554
|
-
{
|
555
|
-
// this can't be updated
|
556
|
-
// TODO: pull this out of discovery?
|
557
|
-
return (false, null);
|
558
|
-
}
|
559
|
-
|
560
|
-
if (dependency.Version is null)
|
561
|
-
{
|
562
|
-
// if we don't know the version, there's nothing we can do
|
563
|
-
// TODO: pull this out of discovery?
|
564
|
-
return (false, null);
|
565
|
-
}
|
566
|
-
|
567
|
-
var version = NuGetVersion.Parse(dependency.Version);
|
568
|
-
var dependencyInfo = GetDependencyInfo(job, dependency);
|
569
|
-
var isVulnerable = dependencyInfo.Vulnerabilities.Any(v => v.IsVulnerable(version));
|
570
|
-
MessageBase? message = null;
|
571
|
-
var allowed = job.AllowedUpdates.Any(allowedUpdate =>
|
572
|
-
{
|
573
|
-
// check name restriction, if any
|
574
|
-
if (allowedUpdate.DependencyName is not null)
|
575
|
-
{
|
576
|
-
var matcher = new Matcher(StringComparison.OrdinalIgnoreCase)
|
577
|
-
.AddInclude(allowedUpdate.DependencyName);
|
578
|
-
var result = matcher.Match(dependency.Name);
|
579
|
-
if (!result.HasMatches)
|
580
|
-
{
|
581
|
-
return false;
|
582
|
-
}
|
583
|
-
}
|
584
|
-
|
585
|
-
var isSecurityUpdate = allowedUpdate.UpdateType == UpdateType.Security || job.SecurityUpdatesOnly;
|
586
|
-
if (isSecurityUpdate)
|
587
|
-
{
|
588
|
-
if (isVulnerable)
|
589
|
-
{
|
590
|
-
// try to match to existing PR
|
591
|
-
var dependencyVersion = NuGetVersion.Parse(dependency.Version);
|
592
|
-
var existingPullRequests = job.GetAllExistingPullRequests()
|
593
|
-
.Where(pr => pr.Item2.Any(d => d.DependencyName.Equals(dependency.Name, StringComparison.OrdinalIgnoreCase) && d.DependencyVersion >= dependencyVersion))
|
594
|
-
.ToArray();
|
595
|
-
if (existingPullRequests.Length > 0)
|
596
|
-
{
|
597
|
-
// found a matching pr...
|
598
|
-
if (job.UpdatingAPullRequest)
|
599
|
-
{
|
600
|
-
// ...and we've been asked to update it
|
601
|
-
return true;
|
602
|
-
}
|
603
|
-
else
|
604
|
-
{
|
605
|
-
// ...but no update requested => don't perform any update and report error
|
606
|
-
var existingPrVersion = existingPullRequests[0].Item2.First(d => d.DependencyName.Equals(dependency.Name, StringComparison.OrdinalIgnoreCase)).DependencyVersion;
|
607
|
-
message = new PullRequestExistsForLatestVersion(dependency.Name, existingPrVersion.ToString());
|
608
|
-
return false;
|
609
|
-
}
|
610
|
-
}
|
611
|
-
else
|
612
|
-
{
|
613
|
-
// no matching pr...
|
614
|
-
if (job.UpdatingAPullRequest)
|
615
|
-
{
|
616
|
-
// ...but we've been asked to perform an update => no update possible, nothing to report
|
617
|
-
return false;
|
618
|
-
}
|
619
|
-
else
|
620
|
-
{
|
621
|
-
// ...and no update specifically requested => create new
|
622
|
-
return true;
|
623
|
-
}
|
624
|
-
}
|
625
|
-
}
|
626
|
-
else
|
627
|
-
{
|
628
|
-
// not vulnerable => no longer needed
|
629
|
-
var specificJobDependencies = job.SecurityAdvisories
|
630
|
-
.Select(a => a.DependencyName)
|
631
|
-
.Concat(job.Dependencies)
|
632
|
-
.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
633
|
-
if (specificJobDependencies.Contains(dependency.Name))
|
634
|
-
{
|
635
|
-
message = new SecurityUpdateNotNeeded(dependency.Name);
|
636
|
-
}
|
637
|
-
}
|
638
|
-
|
639
|
-
return false;
|
640
|
-
}
|
641
|
-
else
|
642
|
-
{
|
643
|
-
// not a security update, so only update if...
|
644
|
-
// ...we've been explicitly asked to update this
|
645
|
-
if (job.Dependencies.Any(d => d.Equals(dependency.Name, StringComparison.OrdinalIgnoreCase)))
|
646
|
-
{
|
647
|
-
return true;
|
648
|
-
}
|
649
|
-
|
650
|
-
// ...no specific update being performed, do it if it's not transitive
|
651
|
-
return !dependency.IsTransitive;
|
652
|
-
}
|
653
|
-
});
|
654
|
-
|
655
|
-
return (allowed, message);
|
656
|
-
}
|
657
|
-
|
658
|
-
internal static ImmutableArray<Requirement> GetIgnoredRequirementsForDependency(Job job, string dependencyName)
|
659
|
-
{
|
660
|
-
var ignoreConditions = job.IgnoreConditions
|
661
|
-
.Where(c => c.DependencyName.Equals(dependencyName, StringComparison.OrdinalIgnoreCase))
|
662
|
-
.ToArray();
|
663
|
-
if (ignoreConditions.Length == 1 && ignoreConditions[0].VersionRequirement is null)
|
664
|
-
{
|
665
|
-
// if only one match with no version requirement, ignore all versions
|
666
|
-
return [Requirement.Parse("> 0.0.0")];
|
667
|
-
}
|
668
|
-
|
669
|
-
var ignoredVersions = ignoreConditions
|
670
|
-
.Select(c => c.VersionRequirement)
|
671
|
-
.Where(r => r is not null)
|
672
|
-
.Cast<Requirement>()
|
673
|
-
.ToImmutableArray();
|
674
|
-
return ignoredVersions;
|
675
|
-
}
|
676
|
-
|
677
155
|
internal static DependencyInfo GetDependencyInfo(Job job, Dependency dependency)
|
678
156
|
{
|
679
157
|
var dependencyVersion = NuGetVersion.Parse(dependency.Version!);
|
@@ -161,7 +161,7 @@ internal class CreateSecurityUpdatePullRequestHandler : IUpdateHandler
|
|
161
161
|
{
|
162
162
|
var commitMessage = PullRequestTextGenerator.GetPullRequestCommitMessage(job, [.. updateOperationsPerformed], null);
|
163
163
|
var prTitle = PullRequestTextGenerator.GetPullRequestTitle(job, [.. updateOperationsPerformed], null);
|
164
|
-
var prBody = PullRequestTextGenerator.
|
164
|
+
var prBody = await PullRequestTextGenerator.GetPullRequestBodyAsync(job, [.. updateOperationsPerformed], [.. updatedDependencies], experimentsManager);
|
165
165
|
await apiHandler.CreatePullRequest(new CreatePullRequest()
|
166
166
|
{
|
167
167
|
Dependencies = [.. updatedDependencies],
|
data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/UpdateHandlers/GroupUpdateAllVersionsHandler.cs
CHANGED
@@ -155,7 +155,7 @@ internal class GroupUpdateAllVersionsHandler : IUpdateHandler
|
|
155
155
|
{
|
156
156
|
var commitMessage = PullRequestTextGenerator.GetPullRequestCommitMessage(job, [.. updateOperationsPerformed], group.Name);
|
157
157
|
var prTitle = PullRequestTextGenerator.GetPullRequestTitle(job, [.. updateOperationsPerformed], group.Name);
|
158
|
-
var prBody = PullRequestTextGenerator.
|
158
|
+
var prBody = await PullRequestTextGenerator.GetPullRequestBodyAsync(job, [.. updateOperationsPerformed], [.. updatedDependencies], experimentsManager);
|
159
159
|
await apiHandler.CreatePullRequest(new CreatePullRequest()
|
160
160
|
{
|
161
161
|
Dependencies = [.. updatedDependencies],
|
@@ -251,7 +251,7 @@ internal class GroupUpdateAllVersionsHandler : IUpdateHandler
|
|
251
251
|
{
|
252
252
|
var commitMessage = PullRequestTextGenerator.GetPullRequestCommitMessage(job, [.. updateOperationsPerformed], null);
|
253
253
|
var prTitle = PullRequestTextGenerator.GetPullRequestTitle(job, [.. updateOperationsPerformed], null);
|
254
|
-
var prBody = PullRequestTextGenerator.
|
254
|
+
var prBody = await PullRequestTextGenerator.GetPullRequestBodyAsync(job, [.. updateOperationsPerformed], [.. updatedDependencies], experimentsManager);
|
255
255
|
await apiHandler.CreatePullRequest(new CreatePullRequest()
|
256
256
|
{
|
257
257
|
Dependencies = [.. updatedDependencies],
|
@@ -154,7 +154,7 @@ internal class RefreshGroupUpdatePullRequestHandler : IUpdateHandler
|
|
154
154
|
|
155
155
|
var commitMessage = PullRequestTextGenerator.GetPullRequestCommitMessage(job, [.. updateOperationsPerformed], null);
|
156
156
|
var prTitle = PullRequestTextGenerator.GetPullRequestTitle(job, [.. updateOperationsPerformed], null);
|
157
|
-
var prBody = PullRequestTextGenerator.
|
157
|
+
var prBody = await PullRequestTextGenerator.GetPullRequestBodyAsync(job, [.. updateOperationsPerformed], [.. updatedDependencies], experimentsManager);
|
158
158
|
var existingPullRequest = job.GetExistingPullRequestForDependencies(rawDependencies, considerVersions: true);
|
159
159
|
if (existingPullRequest is not null)
|
160
160
|
{
|
@@ -161,7 +161,7 @@ internal class RefreshSecurityUpdatePullRequestHandler : IUpdateHandler
|
|
161
161
|
{
|
162
162
|
var commitMessage = PullRequestTextGenerator.GetPullRequestCommitMessage(job, [.. updateOperationsPerformed], null);
|
163
163
|
var prTitle = PullRequestTextGenerator.GetPullRequestTitle(job, [.. updateOperationsPerformed], null);
|
164
|
-
var prBody = PullRequestTextGenerator.
|
164
|
+
var prBody = await PullRequestTextGenerator.GetPullRequestBodyAsync(job, [.. updateOperationsPerformed], [.. updatedDependencies], experimentsManager);
|
165
165
|
|
166
166
|
var existingPullRequest = job.GetExistingPullRequestForDependencies(rawDependencies, considerVersions: true);
|
167
167
|
if (existingPullRequest is not null)
|
@@ -151,7 +151,7 @@ internal class RefreshVersionUpdatePullRequestHandler : IUpdateHandler
|
|
151
151
|
{
|
152
152
|
var commitMessage = PullRequestTextGenerator.GetPullRequestCommitMessage(job, [.. updateOperationsPerformed], null);
|
153
153
|
var prTitle = PullRequestTextGenerator.GetPullRequestTitle(job, [.. updateOperationsPerformed], null);
|
154
|
-
var prBody = PullRequestTextGenerator.
|
154
|
+
var prBody = await PullRequestTextGenerator.GetPullRequestBodyAsync(job, [.. updateOperationsPerformed], [.. updatedDependencies], experimentsManager);
|
155
155
|
|
156
156
|
var existingPullRequest = job.GetExistingPullRequestForDependencies(rawDependencies, considerVersions: true);
|
157
157
|
if (existingPullRequest is not null)
|
@@ -250,7 +250,7 @@ public class FileWriterWorker
|
|
250
250
|
initialTopLevelDependencies,
|
251
251
|
desiredDependencies,
|
252
252
|
resolvedDependencies.Value,
|
253
|
-
new ExperimentsManager()
|
253
|
+
new ExperimentsManager(),
|
254
254
|
_logger);
|
255
255
|
var filteredUpdateOperations = computedUpdateOperations
|
256
256
|
.Where(op =>
|
@@ -1,5 +1,6 @@
|
|
1
1
|
using System.Collections.Immutable;
|
2
2
|
using System.Text.RegularExpressions;
|
3
|
+
using System.Xml;
|
3
4
|
using System.Xml.Linq;
|
4
5
|
|
5
6
|
using NuGet.Versioning;
|
@@ -369,7 +370,7 @@ public class XmlFileWriter : IFileWriter
|
|
369
370
|
{
|
370
371
|
foreach (var (path, contents) in filesAndContents)
|
371
372
|
{
|
372
|
-
await WriteFileContentsAsync(repoContentsPath, path, contents
|
373
|
+
await WriteFileContentsAsync(repoContentsPath, path, contents);
|
373
374
|
}
|
374
375
|
}
|
375
376
|
|
@@ -433,10 +434,16 @@ public class XmlFileWriter : IFileWriter
|
|
433
434
|
return contents;
|
434
435
|
}
|
435
436
|
|
436
|
-
private static async Task WriteFileContentsAsync(DirectoryInfo repoContentsPath, string path,
|
437
|
+
private static async Task WriteFileContentsAsync(DirectoryInfo repoContentsPath, string path, XDocument document)
|
437
438
|
{
|
438
439
|
var fullPath = Path.Join(repoContentsPath.FullName, path);
|
439
|
-
|
440
|
+
var writerSettings = new XmlWriterSettings()
|
441
|
+
{
|
442
|
+
Async = true,
|
443
|
+
OmitXmlDeclaration = document.Declaration is null,
|
444
|
+
};
|
445
|
+
using var writer = XmlWriter.Create(fullPath, writerSettings);
|
446
|
+
await document.SaveAsync(writer, CancellationToken.None);
|
440
447
|
}
|
441
448
|
|
442
449
|
public static string CreateUpdatedVersionRangeString(VersionRange existingRange, NuGetVersion existingVersion, NuGetVersion requiredVersion)
|