dependabot-nuget 0.300.0 → 0.301.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/NuGetUpdater.Cli/Commands/DiscoverCommand.cs +1 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/SdkProjectDiscovery.cs +2 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/ClosePullRequest.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/CommitOptions.cs +5 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/CreatePullRequest.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/GroupPullRequest.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/Job.cs +36 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/JobErrorBase.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/MessageBase.cs +5 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/PullRequest.cs +2 -5
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/PullRequestDependency.cs +11 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/UpdatePullRequest.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/CommitOptions_IncludeScopeConverter.cs +29 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/HttpApiHandler.cs +5 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/IApiHandler.cs +1 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/PullRequestConverter.cs +35 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/PullRequestTextGenerator.cs +44 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/RunWorker.cs +205 -49
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs +76 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/MiscellaneousTests.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/PullRequestMessageTests.cs +252 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/PullRequestTextTests.cs +136 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/RunWorkerTests.cs +145 -22
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/SerializationTests.cs +15 -10
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/TestApiHandler.cs +6 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/{UpdateAllowedTests.cs → UpdatePermittedAndMessageTests.cs} +110 -6
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TestHttpServer.cs +105 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackageReference.cs +75 -0
- metadata +13 -6
@@ -1,9 +1,7 @@
|
|
1
1
|
using System.Collections.Immutable;
|
2
|
-
using System.Net;
|
3
2
|
using System.Text;
|
4
3
|
using System.Text.Json;
|
5
4
|
using System.Text.Json.Serialization;
|
6
|
-
using System.Text.RegularExpressions;
|
7
5
|
|
8
6
|
using Microsoft.Extensions.FileSystemGlobbing;
|
9
7
|
|
@@ -31,7 +29,7 @@ public class RunWorker
|
|
31
29
|
{
|
32
30
|
PropertyNamingPolicy = JsonNamingPolicy.KebabCaseLower,
|
33
31
|
WriteIndented = true,
|
34
|
-
Converters = { new JsonStringEnumConverter(), new RequirementConverter(), new VersionConverter() },
|
32
|
+
Converters = { new JsonStringEnumConverter(), new PullRequestConverter(), new RequirementConverter(), new VersionConverter() },
|
35
33
|
};
|
36
34
|
|
37
35
|
public RunWorker(string jobId, IApiHandler apiHandler, IDiscoveryWorker discoverWorker, IAnalyzeWorker analyzeWorker, IUpdaterWorker updateWorker, ILogger logger)
|
@@ -160,39 +158,61 @@ public class RunWorker
|
|
160
158
|
}
|
161
159
|
|
162
160
|
// do update
|
163
|
-
var
|
164
|
-
var
|
165
|
-
|
166
|
-
|
167
|
-
var
|
161
|
+
var existingPullRequests = job.GetAllExistingPullRequests();
|
162
|
+
var unhandledPullRequestDependenciesSet = existingPullRequests
|
163
|
+
.Select(pr => pr.Item2.Select(d => d.DependencyName).ToHashSet(StringComparer.OrdinalIgnoreCase))
|
164
|
+
.ToHashSet();
|
165
|
+
var remainingSecurityIssues = job.SecurityAdvisories
|
168
166
|
.Select(s => s.DependencyName)
|
169
167
|
.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
170
|
-
var
|
171
|
-
.Select(u => u.Dependency.Name)
|
172
|
-
.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
173
|
-
var expectedDependencyUpdateMissingInActual = expectedSecurityUpdateDependencyNames
|
174
|
-
.Except(actualUpdateDependencyNames, StringComparer.OrdinalIgnoreCase)
|
175
|
-
.OrderBy(d => d, StringComparer.OrdinalIgnoreCase)
|
176
|
-
.ToArray();
|
177
|
-
|
178
|
-
foreach (var missingSecurityUpdate in expectedDependencyUpdateMissingInActual)
|
179
|
-
{
|
180
|
-
await _apiHandler.RecordUpdateJobError(new SecurityUpdateNotNeeded(missingSecurityUpdate));
|
181
|
-
}
|
168
|
+
var updateOperations = GetUpdateOperations(discoveryResult).ToArray();
|
182
169
|
|
183
|
-
foreach (var updateOperation in
|
170
|
+
foreach (var updateOperation in updateOperations)
|
184
171
|
{
|
185
172
|
var dependency = updateOperation.Dependency;
|
186
|
-
|
173
|
+
var (isAllowed, message) = UpdatePermittedAndMessage(job, updateOperation.Dependency);
|
174
|
+
if (message is SecurityUpdateNotNeeded sec)
|
175
|
+
{
|
176
|
+
// flag this update operation as having been handled
|
177
|
+
remainingSecurityIssues.RemoveWhere(r => r.Equals(dependency.Name, StringComparison.OrdinalIgnoreCase));
|
178
|
+
|
179
|
+
// we only want to send this message if we're in the only update operation for this dependency, otherwise it's ambiguous
|
180
|
+
var updateOperationsWithSameName = updateOperations.Where(u => u.Dependency.Name.Equals(dependency.Name, StringComparison.OrdinalIgnoreCase))
|
181
|
+
.ToArray();
|
182
|
+
if (updateOperationsWithSameName.Length > 1)
|
183
|
+
{
|
184
|
+
// suppress the message
|
185
|
+
message = null;
|
186
|
+
}
|
187
|
+
}
|
188
|
+
|
189
|
+
await SendApiMessage(message);
|
190
|
+
if (!isAllowed)
|
191
|
+
{
|
192
|
+
continue;
|
193
|
+
}
|
194
|
+
|
195
|
+
_logger.Info($"Updating [{dependency.Name}] in [{updateOperation.ProjectPath}]");
|
187
196
|
|
188
197
|
var dependencyInfo = GetDependencyInfo(job, dependency);
|
189
198
|
var analysisResult = await _analyzeWorker.RunAsync(repoContentsPath.FullName, discoveryResult, dependencyInfo);
|
190
199
|
// TODO: log analysisResult
|
191
200
|
if (analysisResult.CanUpdate)
|
192
201
|
{
|
202
|
+
if (!job.UpdatingAPullRequest)
|
203
|
+
{
|
204
|
+
var existingPullRequest = job.GetExistingPullRequestForDependency(analysisResult.UpdatedDependencies.First(d => d.Name.Equals(dependency.Name, StringComparison.OrdinalIgnoreCase)));
|
205
|
+
if (existingPullRequest is not null)
|
206
|
+
{
|
207
|
+
await SendApiMessage(new PullRequestExistsForLatestVersion(dependency.Name, analysisResult.UpdatedVersion));
|
208
|
+
unhandledPullRequestDependenciesSet.RemoveWhere(handled => handled.Count == 1 && handled.Contains(dependency.Name));
|
209
|
+
continue;
|
210
|
+
}
|
211
|
+
}
|
212
|
+
|
193
213
|
// TODO: this is inefficient, but not likely causing a bottleneck
|
194
214
|
var previousDependency = discoveredUpdatedDependencies.Dependencies
|
195
|
-
.Single(d => d.Name == dependency.Name && d.Requirements.Single().File == updateOperation.
|
215
|
+
.Single(d => d.Name == dependency.Name && d.Requirements.Single().File == updateOperation.ProjectPath);
|
196
216
|
var updatedDependency = new ReportedDependency()
|
197
217
|
{
|
198
218
|
Name = dependency.Name,
|
@@ -201,7 +221,7 @@ public class RunWorker
|
|
201
221
|
[
|
202
222
|
new ReportedRequirement()
|
203
223
|
{
|
204
|
-
File = updateOperation.
|
224
|
+
File = updateOperation.ProjectPath,
|
205
225
|
Requirement = analysisResult.UpdatedVersion,
|
206
226
|
Groups = previousDependency.Requirements.Single().Groups,
|
207
227
|
Source = new RequirementSource()
|
@@ -214,7 +234,7 @@ public class RunWorker
|
|
214
234
|
PreviousRequirements = previousDependency.Requirements,
|
215
235
|
};
|
216
236
|
|
217
|
-
var updateResult = await _updaterWorker.RunAsync(repoContentsPath.FullName, updateOperation.
|
237
|
+
var updateResult = await _updaterWorker.RunAsync(repoContentsPath.FullName, updateOperation.ProjectPath, dependency.Name, dependency.Version!, analysisResult.UpdatedVersion, isTransitive: dependency.IsTransitive);
|
218
238
|
// TODO: need to report if anything was actually updated
|
219
239
|
if (updateResult.Error is null)
|
220
240
|
{
|
@@ -262,27 +282,39 @@ public class RunWorker
|
|
262
282
|
await AddUpdatedFileIfDifferentAsync(discoveryResult.Path, nonProjectFile);
|
263
283
|
}
|
264
284
|
|
265
|
-
|
285
|
+
var updatedDependencyFileList = updatedDependencyFiles
|
286
|
+
.OrderBy(kvp => kvp.Key)
|
287
|
+
.Select(kvp => kvp.Value)
|
288
|
+
.ToArray();
|
289
|
+
|
290
|
+
var resultMessage = GetPullRequestApiMessage(job, updatedDependencyFileList, actualUpdatedDependencies.ToArray(), baseCommitSha);
|
291
|
+
switch (resultMessage)
|
266
292
|
{
|
267
|
-
|
268
|
-
|
269
|
-
.
|
270
|
-
.
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
293
|
+
case ClosePullRequest close:
|
294
|
+
var closePrDependencies = close.DependencyNames.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
295
|
+
remainingSecurityIssues.RemoveWhere(closePrDependencies.Contains);
|
296
|
+
if (!unhandledPullRequestDependenciesSet.Remove(closePrDependencies))
|
297
|
+
{
|
298
|
+
// this PR was handled earlier, we don't want to now close it; suppress the message
|
299
|
+
resultMessage = null;
|
300
|
+
}
|
301
|
+
break;
|
302
|
+
case CreatePullRequest create:
|
303
|
+
var createPrDependencies = create.Dependencies.Select(d => d.Name).ToHashSet(StringComparer.OrdinalIgnoreCase);
|
304
|
+
remainingSecurityIssues.RemoveWhere(createPrDependencies.Contains);
|
305
|
+
break;
|
306
|
+
case UpdatePullRequest update:
|
307
|
+
var updatePrDependencies = update.DependencyNames.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
308
|
+
remainingSecurityIssues.RemoveWhere(updatePrDependencies.Contains);
|
309
|
+
break;
|
282
310
|
}
|
283
|
-
|
311
|
+
|
312
|
+
await SendApiMessage(resultMessage);
|
313
|
+
|
314
|
+
// for each security advisory that _didn't_ result in a pr, report it
|
315
|
+
foreach (var depName in remainingSecurityIssues)
|
284
316
|
{
|
285
|
-
|
317
|
+
await SendApiMessage(new SecurityUpdateNotNeeded(depName));
|
286
318
|
}
|
287
319
|
|
288
320
|
var result = new RunResult()
|
@@ -302,7 +334,104 @@ public class RunWorker
|
|
302
334
|
return result;
|
303
335
|
}
|
304
336
|
|
305
|
-
|
337
|
+
private async Task SendApiMessage(MessageBase? message)
|
338
|
+
{
|
339
|
+
switch (message)
|
340
|
+
{
|
341
|
+
case null:
|
342
|
+
break;
|
343
|
+
case JobErrorBase error:
|
344
|
+
await _apiHandler.RecordUpdateJobError(error);
|
345
|
+
break;
|
346
|
+
case CreatePullRequest create:
|
347
|
+
await _apiHandler.CreatePullRequest(create);
|
348
|
+
break;
|
349
|
+
case ClosePullRequest close:
|
350
|
+
await _apiHandler.ClosePullRequest(close);
|
351
|
+
break;
|
352
|
+
case UpdatePullRequest update:
|
353
|
+
await _apiHandler.UpdatePullRequest(update);
|
354
|
+
break;
|
355
|
+
default:
|
356
|
+
throw new NotSupportedException($"unsupported api message: {message.GetType().Name}");
|
357
|
+
}
|
358
|
+
}
|
359
|
+
|
360
|
+
internal static MessageBase? GetPullRequestApiMessage(Job job, DependencyFile[] updatedFiles, ReportedDependency[] updatedDependencies, string baseCommitSha)
|
361
|
+
{
|
362
|
+
updatedDependencies = updatedDependencies.OrderBy(d => d.Name, StringComparer.OrdinalIgnoreCase).ToArray();
|
363
|
+
var updatedDependenciesSet = updatedDependencies.Select(d => d.Name).ToHashSet(StringComparer.OrdinalIgnoreCase);
|
364
|
+
|
365
|
+
// all pull request dependencies with optional group name
|
366
|
+
var existingPullRequests = job.GetAllExistingPullRequests();
|
367
|
+
var existingPullRequest = existingPullRequests.FirstOrDefault(pr => pr.Item2.Select(d => d.DependencyName).All(updatedDependenciesSet.Contains));
|
368
|
+
if (existingPullRequest is null && updatedFiles.Length == 0)
|
369
|
+
{
|
370
|
+
// 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
|
371
|
+
var requestedUpdates = (job.Dependencies ?? []).ToHashSet(StringComparer.OrdinalIgnoreCase);
|
372
|
+
existingPullRequest = existingPullRequests.FirstOrDefault(pr => pr.Item2.Select(d => d.DependencyName).All(requestedUpdates.Contains));
|
373
|
+
}
|
374
|
+
|
375
|
+
var expectedSecurityUpdateDependencyNames = job.SecurityAdvisories.Select(sa => sa.DependencyName).ToHashSet(StringComparer.OrdinalIgnoreCase);
|
376
|
+
var isExpectedSecurityUpdate = updatedDependenciesSet.All(expectedSecurityUpdateDependencyNames.Contains);
|
377
|
+
|
378
|
+
if (existingPullRequest is { })
|
379
|
+
{
|
380
|
+
if (job.UpdatingAPullRequest)
|
381
|
+
{
|
382
|
+
return new UpdatePullRequest()
|
383
|
+
{
|
384
|
+
DependencyGroup = existingPullRequest.Item1,
|
385
|
+
DependencyNames = updatedDependencies.Select(d => d.Name).ToImmutableArray(),
|
386
|
+
UpdatedDependencyFiles = updatedFiles,
|
387
|
+
BaseCommitSha = baseCommitSha,
|
388
|
+
CommitMessage = PullRequestTextGenerator.GetPullRequestCommitMessage(job, updatedDependencies, updatedFiles, existingPullRequest.Item1),
|
389
|
+
PrTitle = PullRequestTextGenerator.GetPullRequestTitle(job, updatedDependencies, updatedFiles, existingPullRequest.Item1),
|
390
|
+
PrBody = PullRequestTextGenerator.GetPullRequestBody(job, updatedDependencies, updatedFiles, existingPullRequest.Item1),
|
391
|
+
};
|
392
|
+
}
|
393
|
+
else
|
394
|
+
{
|
395
|
+
if (updatedDependenciesSet.Count == 0)
|
396
|
+
{
|
397
|
+
// nothing found, close current
|
398
|
+
return new ClosePullRequest()
|
399
|
+
{
|
400
|
+
DependencyNames = [.. existingPullRequest.Item2.Select(d => d.DependencyName)],
|
401
|
+
Reason = "dependency_removed",
|
402
|
+
};
|
403
|
+
}
|
404
|
+
else
|
405
|
+
{
|
406
|
+
// found but no longer required
|
407
|
+
return new ClosePullRequest()
|
408
|
+
{
|
409
|
+
DependencyNames = [.. updatedDependenciesSet],
|
410
|
+
Reason = "up_to_date",
|
411
|
+
};
|
412
|
+
}
|
413
|
+
}
|
414
|
+
}
|
415
|
+
else
|
416
|
+
{
|
417
|
+
if (updatedDependencies.Any())
|
418
|
+
{
|
419
|
+
return new CreatePullRequest()
|
420
|
+
{
|
421
|
+
Dependencies = updatedDependencies,
|
422
|
+
UpdatedDependencyFiles = updatedFiles,
|
423
|
+
BaseCommitSha = baseCommitSha,
|
424
|
+
CommitMessage = PullRequestTextGenerator.GetPullRequestCommitMessage(job, updatedDependencies, updatedFiles),
|
425
|
+
PrTitle = PullRequestTextGenerator.GetPullRequestTitle(job, updatedDependencies, updatedFiles),
|
426
|
+
PrBody = PullRequestTextGenerator.GetPullRequestBody(job, updatedDependencies, updatedFiles),
|
427
|
+
};
|
428
|
+
}
|
429
|
+
}
|
430
|
+
|
431
|
+
return null;
|
432
|
+
}
|
433
|
+
|
434
|
+
internal static IEnumerable<(string ProjectPath, Dependency Dependency)> GetUpdateOperations(WorkspaceDiscoveryResult discovery)
|
306
435
|
{
|
307
436
|
// 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
|
308
437
|
|
@@ -364,25 +493,26 @@ public class RunWorker
|
|
364
493
|
return increment;
|
365
494
|
}
|
366
495
|
|
367
|
-
internal static bool
|
496
|
+
internal static (bool, MessageBase?) UpdatePermittedAndMessage(Job job, Dependency dependency)
|
368
497
|
{
|
369
498
|
if (dependency.Name.Equals("Microsoft.NET.Sdk", StringComparison.OrdinalIgnoreCase))
|
370
499
|
{
|
371
500
|
// this can't be updated
|
372
501
|
// TODO: pull this out of discovery?
|
373
|
-
return false;
|
502
|
+
return (false, null);
|
374
503
|
}
|
375
504
|
|
376
505
|
if (dependency.Version is null)
|
377
506
|
{
|
378
507
|
// if we don't know the version, there's nothing we can do
|
379
508
|
// TODO: pull this out of discovery?
|
380
|
-
return false;
|
509
|
+
return (false, null);
|
381
510
|
}
|
382
511
|
|
383
512
|
var version = NuGetVersion.Parse(dependency.Version);
|
384
513
|
var dependencyInfo = GetDependencyInfo(job, dependency);
|
385
514
|
var isVulnerable = dependencyInfo.Vulnerabilities.Any(v => v.IsVulnerable(version));
|
515
|
+
MessageBase? message = null;
|
386
516
|
var allowed = job.AllowedUpdates.Any(allowedUpdate =>
|
387
517
|
{
|
388
518
|
// check name restriction, if any
|
@@ -400,7 +530,33 @@ public class RunWorker
|
|
400
530
|
var isSecurityUpdate = allowedUpdate.UpdateType == UpdateType.Security || job.SecurityUpdatesOnly;
|
401
531
|
if (isSecurityUpdate)
|
402
532
|
{
|
403
|
-
|
533
|
+
if (isVulnerable)
|
534
|
+
{
|
535
|
+
// try to match to existing PR
|
536
|
+
var dependencyVersion = NuGetVersion.Parse(dependency.Version);
|
537
|
+
var existingPullRequests = job.GetAllExistingPullRequests()
|
538
|
+
.Where(pr => pr.Item2.Any(d => d.DependencyName.Equals(dependency.Name, StringComparison.OrdinalIgnoreCase) && d.DependencyVersion >= dependencyVersion))
|
539
|
+
.ToArray();
|
540
|
+
if (existingPullRequests.Length > 0)
|
541
|
+
{
|
542
|
+
var existingPrVersion = existingPullRequests[0].Item2.First(d => d.DependencyName.Equals(dependency.Name, StringComparison.OrdinalIgnoreCase)).DependencyVersion;
|
543
|
+
message = new PullRequestExistsForLatestVersion(dependency.Name, existingPrVersion.ToString());
|
544
|
+
return false;
|
545
|
+
}
|
546
|
+
}
|
547
|
+
else
|
548
|
+
{
|
549
|
+
// not vulnerable => no longer needed
|
550
|
+
var specificJobDependencies = job.SecurityAdvisories
|
551
|
+
.Select(a => a.DependencyName)
|
552
|
+
.Concat(job.Dependencies ?? [])
|
553
|
+
.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
554
|
+
if (specificJobDependencies.Contains(dependency.Name))
|
555
|
+
{
|
556
|
+
message = new SecurityUpdateNotNeeded(dependency.Name);
|
557
|
+
}
|
558
|
+
}
|
559
|
+
|
404
560
|
return isVulnerable;
|
405
561
|
}
|
406
562
|
else
|
@@ -417,7 +573,7 @@ public class RunWorker
|
|
417
573
|
}
|
418
574
|
});
|
419
575
|
|
420
|
-
return allowed;
|
576
|
+
return (allowed, message);
|
421
577
|
}
|
422
578
|
|
423
579
|
internal static ImmutableArray<Requirement> GetIgnoredRequirementsForDependency(Job job, string dependencyName)
|
@@ -1,5 +1,4 @@
|
|
1
1
|
using System.Collections.Immutable;
|
2
|
-
using System.Runtime.InteropServices;
|
3
2
|
using System.Text.Json;
|
4
3
|
|
5
4
|
using NuGetUpdater.Core.Discover;
|
@@ -1434,4 +1433,80 @@ public partial class DiscoveryWorkerTests : DiscoveryWorkerTestBase
|
|
1434
1433
|
}
|
1435
1434
|
);
|
1436
1435
|
}
|
1436
|
+
|
1437
|
+
[Fact]
|
1438
|
+
public async Task CentralPackageManagementStillWorksWithMultipleFeedsListedInConfig()
|
1439
|
+
{
|
1440
|
+
// If a repo doesn't contain a `NuGet.Config` file and `dependabot.yml` specifies a package source, a user-
|
1441
|
+
// local `NuGet.Config` file is created before the updater is run that enumerates the specified feeds as well
|
1442
|
+
// as `api.nuget.org`. If a given project is using Central Package Management a warning NU1507 will be
|
1443
|
+
// generated because of the multiple feeds listed. If that project _also_ specifies $(TreatWarningsAsErrors)
|
1444
|
+
// as true, this will cause dependency discovery to "fail". To simulate this, multiple remote NuGet sources
|
1445
|
+
// need to be listed in the `NuGet.Config` file in this test.
|
1446
|
+
using var http1 = TestHttpServer.CreateTestNuGetFeed(MockNuGetPackage.CreateSimplePackage("Package1", "1.0.0", "net9.0"));
|
1447
|
+
using var http2 = TestHttpServer.CreateTestNuGetFeed(MockNuGetPackage.CreateSimplePackage("Package2", "2.0.0", "net9.0"));
|
1448
|
+
await TestDiscoveryAsync(
|
1449
|
+
packages: [],
|
1450
|
+
experimentsManager: new ExperimentsManager() { UseDirectDiscovery = true },
|
1451
|
+
workspacePath: "/src",
|
1452
|
+
files: [
|
1453
|
+
("src/NuGet.Config", $"""
|
1454
|
+
<configuration>
|
1455
|
+
<packageSources>
|
1456
|
+
<!-- explicitly _not_ calling "clear" because we also want the upstream sources in addition to these two remote sources -->
|
1457
|
+
<add key="source_1" value="{http1.GetPackageFeedIndex()}" allowInsecureConnections="true" />
|
1458
|
+
<add key="source_2" value="{http2.GetPackageFeedIndex()}" allowInsecureConnections="true" />
|
1459
|
+
</packageSources>
|
1460
|
+
</configuration>
|
1461
|
+
"""),
|
1462
|
+
("src/project.csproj", """
|
1463
|
+
<Project Sdk="Microsoft.NET.Sdk">
|
1464
|
+
<PropertyGroup>
|
1465
|
+
<TargetFramework>net9.0</TargetFramework>
|
1466
|
+
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
1467
|
+
<MSBuildTreatWarningsAsErrors>true</MSBuildTreatWarningsAsErrors>
|
1468
|
+
</PropertyGroup>
|
1469
|
+
<ItemGroup>
|
1470
|
+
<PackageReference Include="Package1" />
|
1471
|
+
<PackageReference Include="Package2" />
|
1472
|
+
</ItemGroup>
|
1473
|
+
</Project>
|
1474
|
+
"""),
|
1475
|
+
("src/Directory.Packages.props", """
|
1476
|
+
<Project>
|
1477
|
+
<PropertyGroup>
|
1478
|
+
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
1479
|
+
</PropertyGroup>
|
1480
|
+
<ItemGroup>
|
1481
|
+
<PackageVersion Include="Package1" Version="1.0.0" />
|
1482
|
+
<PackageVersion Include="Package2" Version="2.0.0" />
|
1483
|
+
</ItemGroup>
|
1484
|
+
</Project>
|
1485
|
+
""")
|
1486
|
+
],
|
1487
|
+
expectedResult: new()
|
1488
|
+
{
|
1489
|
+
Path = "src",
|
1490
|
+
Projects = [
|
1491
|
+
new()
|
1492
|
+
{
|
1493
|
+
FilePath = "project.csproj",
|
1494
|
+
TargetFrameworks = ["net9.0"],
|
1495
|
+
Dependencies = [
|
1496
|
+
new("Package1", "1.0.0", DependencyType.PackageReference, TargetFrameworks: ["net9.0"], IsDirect: true),
|
1497
|
+
new("Package2", "2.0.0", DependencyType.PackageReference, TargetFrameworks: ["net9.0"], IsDirect: true),
|
1498
|
+
],
|
1499
|
+
Properties = [
|
1500
|
+
new("MSBuildTreatWarningsAsErrors", "false", "src/project.csproj"), // this was specifically overridden by discovery
|
1501
|
+
new("TargetFramework", "net9.0", "src/project.csproj"),
|
1502
|
+
new("TreatWarningsAsErrors", "false", "src/project.csproj"), // this was specifically overridden by discovery
|
1503
|
+
],
|
1504
|
+
ReferencedProjectPaths = [],
|
1505
|
+
ImportedFiles = ["Directory.Packages.props"],
|
1506
|
+
AdditionalFiles = [],
|
1507
|
+
}
|
1508
|
+
]
|
1509
|
+
}
|
1510
|
+
);
|
1511
|
+
}
|
1437
1512
|
}
|
@@ -58,7 +58,7 @@ public class MiscellaneousTests
|
|
58
58
|
public void GetUpdateOperations(WorkspaceDiscoveryResult discovery, (string ProjectPath, string DependencyName)[] expectedUpdateOperations)
|
59
59
|
{
|
60
60
|
var updateOperations = RunWorker.GetUpdateOperations(discovery).ToArray();
|
61
|
-
var actualUpdateOperations = updateOperations.Select(uo => (uo.
|
61
|
+
var actualUpdateOperations = updateOperations.Select(uo => (uo.ProjectPath, uo.Dependency.Name)).ToArray();
|
62
62
|
Assert.Equal(expectedUpdateOperations, actualUpdateOperations);
|
63
63
|
}
|
64
64
|
|