Skip to content
This repository has been archived by the owner on Jul 12, 2022. It is now read-only.

Fix allowed change to work per version #1029

Merged
merged 2 commits into from
Oct 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions NuKeeper.Inspection.Tests/NuGetApi/BulkPackageLookupTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public async Task CanLookupOnePackage()
Assert.That(results, Is.Not.Null);
Assert.That(results, Is.Not.Empty);
Assert.That(results.Count, Is.EqualTo(1));
Assert.That(results.ContainsKey("foo"), Is.True);
Assert.That(results.ElementAt(0).Key.Id, Is.EqualTo("foo"));
}

[Test]
Expand Down Expand Up @@ -106,10 +106,11 @@ public async Task CanLookupTwoPackages()
VersionChange.Major,
UsePrerelease.FromPrerelease);

var packages = results.Select(kvp => kvp.Key);
Assert.That(results.Count, Is.EqualTo(2));
Assert.That(results.ContainsKey("foo"), Is.True);
Assert.That(results.ContainsKey("bar"), Is.True);
Assert.That(results.ContainsKey("fish"), Is.False);
Assert.That(packages, Has.Some.Matches<PackageIdentity>(pi => pi.Id == "foo"));
Assert.That(packages, Has.Some.Matches<PackageIdentity>(pi => pi.Id == "bar"));
Assert.That(packages, Has.None.Matches<PackageIdentity>(pi => pi.Id == "fish"));
}

[Test]
Expand Down Expand Up @@ -163,9 +164,10 @@ await apiLookup.Received(1).FindVersionUpdate(Arg.Is<PackageIdentity>(
pi => pi.Id == "foo" && pi.Version == new NuGetVersion(1, 3, 4)),
Arg.Any<NuGetSources>(), Arg.Any<VersionChange>(), Arg.Any<UsePrerelease>());

var packages = results.Select(kvp => kvp.Key);
Assert.That(results.Count, Is.EqualTo(1));
Assert.That(results.ContainsKey("foo"), Is.True);
Assert.That(results.ContainsKey("bar"), Is.False);
Assert.That(packages, Has.Some.Matches<PackageIdentity>(pi => pi.Id == "foo"));
Assert.That(packages, Has.None.Matches<PackageIdentity>(pi => pi.Id == "bar"));
}

private static void ApiHasNewVersionForPackage(IApiPackageLookup lookup, string packageName)
Expand Down
129 changes: 129 additions & 0 deletions NuKeeper.Inspection.Tests/NuGetApi/PackageUpdatesLookupTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
using NSubstitute;
using NUnit.Framework;
using NuGet.Configuration;
using NuGet.Packaging.Core;
using NuGet.Versioning;
using NuKeeper.Abstractions.Configuration;
using NuKeeper.Abstractions.NuGet;
using NuKeeper.Abstractions.NuGetApi;
using NuKeeper.Abstractions.RepositoryInspection;
using NuKeeper.Inspection.NuGetApi;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace NuKeeper.Inspection.Tests.NuGetApi
{
[TestFixture]
public class PackageUpdatesLookupTests
{
IApiPackageLookup _apiPackageLookup;

[SetUp]
public void Initialize()
{
_apiPackageLookup = Substitute.For<IApiPackageLookup>();

_apiPackageLookup
.FindVersionUpdate(
Arg.Any<PackageIdentity>(),
Arg.Any<NuGetSources>(),
VersionChange.Minor,
Arg.Any<UsePrerelease>()
)
.Returns(ci =>
GetPackageLookupResult(
(PackageIdentity)ci[0],
(VersionChange)ci[2]
)
);
}

[Test]
public async Task FindUpdatesForPackages_OnePackageDifferentVersionsInDifferentProjects_RespectsAllowedChangeForEachVersionIndependently()
{
var packagesInProjects = new List<PackageInProject>
{
MakePackageInProject("foo.bar", "6.0.1", "root", "myprojectA"),
MakePackageInProject("foo.bar", "10.2.1", "root", "myprojectB")
};
var sut = MakePackageUpdatesLookup();

var result = await sut.FindUpdatesForPackages(
packagesInProjects,
new NuGetSources("https://api.nuget.com/"),
VersionChange.Minor,
UsePrerelease.Never
);

var versionUpdates = result.Select(p => p.SelectedVersion.ToNormalizedString());
#pragma warning disable CA1307 // Specify StringComparison
Assert.That(versionUpdates, Has.Some.Matches<string>(version => version.StartsWith("6.")));
Assert.That(versionUpdates, Has.Some.Matches<string>(version => version.StartsWith("10.")));
#pragma warning restore CA1307 // Specify StringComparison
}

private static PackageLookupResult GetPackageLookupResult(
PackageIdentity package,
VersionChange versionChange
)
{
var packageName = package.Id;
var major = package.Version.Major;
var minor = package.Version.Minor;
var patch = package.Version.Patch;

return new PackageLookupResult(
versionChange,
MakePackageSearchMetadata(packageName, $"{major + 1}.0.0"),
MakePackageSearchMetadata(packageName, $"{major}.{minor+1}.0"),
MakePackageSearchMetadata(packageName, $"{major}.{minor}.{patch+1}")
);
}

private static PackageSearchMetadata MakePackageSearchMetadata(
string packageName,
string version,
string source = "https://api.nuget.com/"
)
{
return new PackageSearchMetadata(
new PackageIdentity(
packageName,
new NuGetVersion(version)
),
new PackageSource(source),
null,
null
);
}

private static PackageInProject MakePackageInProject(
string packageName,
string version,
string rootDir,
string relativeDir
)
{
return new PackageInProject(
packageName,
version,
new PackagePath(
rootDir,
relativeDir,
PackageReferenceType.PackagesConfig
)
);
}

private PackageUpdatesLookup MakePackageUpdatesLookup()
{
return new PackageUpdatesLookup(
new BulkPackageLookup(
_apiPackageLookup,
Substitute.For<IPackageLookupResultReporter>()
)
);
}
}
}
44 changes: 29 additions & 15 deletions NuKeeper.Inspection/NuGetApi/BulkPackageLookup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,42 +22,56 @@ public BulkPackageLookup(
_lookupReporter = lookupReporter;
}

public async Task<IDictionary<string, PackageLookupResult>> FindVersionUpdates(
public async Task<IDictionary<PackageIdentity, PackageLookupResult>> FindVersionUpdates(
IEnumerable<PackageIdentity> packages,
NuGetSources sources,
VersionChange allowedChange,
UsePrerelease usePrerelease)
UsePrerelease usePrerelease
)
{
var latestOfEach = packages
.GroupBy(pi => pi.Id.ToUpperInvariant())
.Select(HighestVersion);

var lookupTasks = latestOfEach
.Select(id => _packageLookup.FindVersionUpdate(id, sources, allowedChange, usePrerelease))
var lookupTasks = packages
.Distinct()
.GroupBy(pi => (pi.Id, MaxVersion: GetMaxVersion(pi, allowedChange)))
.Select(HighestVersion)
.Select(id => new { Package = id, Update = _packageLookup.FindVersionUpdate(id, sources, allowedChange, usePrerelease) })
.ToList();

await Task.WhenAll(lookupTasks);
await Task.WhenAll(lookupTasks.Select(l => l.Update));

var result = new Dictionary<string, PackageLookupResult>(StringComparer.OrdinalIgnoreCase);
var result = new Dictionary<PackageIdentity, PackageLookupResult>();

foreach (var lookupTask in lookupTasks)
{
var serverVersions = lookupTask.Result;
ProcessLookupResult(serverVersions, result);
ProcessLookupResult(lookupTask.Package, lookupTask.Update.Result, result);
}

return result;
}

private void ProcessLookupResult(PackageLookupResult packageLookup, IDictionary<string, PackageLookupResult> result)
private static string GetMaxVersion(PackageIdentity pi, VersionChange allowedChange)
{
return allowedChange switch
{
VersionChange.Major => "X.X.X",
VersionChange.Minor => $"{pi.Version.Major}.X.X",
VersionChange.Patch => $"{pi.Version.Major}.{pi.Version.Minor}.X",
VersionChange.None => $"{pi.Version.Major}.{pi.Version.Minor}.{pi.Version.Patch}",
_ => throw new ArgumentOutOfRangeException(nameof(allowedChange)),
};
}

private void ProcessLookupResult(
PackageIdentity package,
PackageLookupResult packageLookup,
IDictionary<PackageIdentity, PackageLookupResult> result
)
{
var selectedVersion = packageLookup.Selected();

if (selectedVersion?.Identity?.Version != null)
{
_lookupReporter.Report(packageLookup);
var packageId = selectedVersion.Identity.Id;
result.Add(packageId, packageLookup);
result.Add(package, packageLookup);
}
}

Expand Down
2 changes: 1 addition & 1 deletion NuKeeper.Inspection/NuGetApi/IBulkPackageLookup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace NuKeeper.Inspection.NuGetApi
{
public interface IBulkPackageLookup
{
Task<IDictionary<string, PackageLookupResult>> FindVersionUpdates(
Task<IDictionary<PackageIdentity, PackageLookupResult>> FindVersionUpdates(
IEnumerable<PackageIdentity> packages,
NuGetSources sources,
VersionChange allowedChange,
Expand Down
2 changes: 1 addition & 1 deletion NuKeeper.Inspection/NuGetApi/PackageUpdatesLookup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public async Task<IReadOnlyCollection<PackageUpdateSet>> FindUpdatesForPackages(
var matchVersion = latestPackage.Selected().Identity.Version;

var updatesForThisPackage = packages
.Where(p => p.Id.Equals(packageId,StringComparison.InvariantCultureIgnoreCase) && p.Version < matchVersion)
.Where(p => p.Identity.Equals(packageId) && p.Version < matchVersion)
.ToList();

if (updatesForThisPackage.Count > 0)
Expand Down
15 changes: 8 additions & 7 deletions NuKeeper.Integration.Tests/NuGet/Api/BulkPackageLookupTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,10 @@ public async Task CanFindUpdateForOneWellKnownPackage()
packages, NuGetSources.GlobalFeed, VersionChange.Major,
UsePrerelease.FromPrerelease);

var updatedPackages = results.Select(p => p.Key);
Assert.That(results, Is.Not.Null);
Assert.That(results.Count, Is.EqualTo(1));
Assert.That(results, Does.ContainKey("Moq"));
Assert.That(updatedPackages, Has.Some.Matches<PackageIdentity>(p => p.Id == "Moq"));
}

[Test]
Expand All @@ -45,10 +46,11 @@ public async Task CanFindUpdateForTwoWellKnownPackages()
packages, NuGetSources.GlobalFeed, VersionChange.Major,
UsePrerelease.FromPrerelease);

var updatedPackages = results.Select(p => p.Key);
Assert.That(results, Is.Not.Null);
Assert.That(results.Count, Is.EqualTo(2));
Assert.That(results, Does.ContainKey("Moq"));
Assert.That(results, Does.ContainKey("Newtonsoft.Json"));
Assert.That(updatedPackages, Has.Some.Matches<PackageIdentity>(p => p.Id == "Moq"));
Assert.That(updatedPackages, Has.Some.Matches<PackageIdentity>(p => p.Id == "Newtonsoft.Json"));
}

[Test]
Expand All @@ -68,8 +70,6 @@ public async Task FindsSingleUpdateForPackageDifferingOnlyByCase()

Assert.That(results, Is.Not.Null);
Assert.That(results.Count, Is.EqualTo(1));
Assert.That(results.ContainsKey("NUnit"), "results.ContainsKey('NUnit')");
Assert.That(results.ContainsKey("nunit"), "results.ContainsKey('nunit')");
}

[Test]
Expand Down Expand Up @@ -120,10 +120,11 @@ public async Task ValidPackagesWorkDespiteInvalidPackages()
packages, NuGetSources.GlobalFeed, VersionChange.Major,
UsePrerelease.FromPrerelease);

var updatedPackages = results.Select(p => p.Key);
Assert.That(results, Is.Not.Null);
Assert.That(results.Count, Is.EqualTo(2));
Assert.That(results, Does.ContainKey("Moq"));
Assert.That(results, Does.ContainKey("Newtonsoft.Json"));
Assert.That(updatedPackages, Has.Some.Matches<PackageIdentity>(p => p.Id == "Moq"));
Assert.That(updatedPackages, Has.Some.Matches<PackageIdentity>(p => p.Id == "Newtonsoft.Json"));
}

private BulkPackageLookup BuildBulkPackageLookup()
Expand Down