From 2739d80df39a49e40f68eddb470de9faf3313c2a Mon Sep 17 00:00:00 2001 From: Daniel Medina Date: Fri, 22 Nov 2019 08:16:47 -0300 Subject: [PATCH] Adding target branch for Bitbucket plataform; Creating a specific commit worder for bitbucket plataform. (#900) --- NuKeeper.BitBucket/BitbucketCommitWorder.cs | 224 ++++++++++++++++++ NuKeeper.BitBucket/BitbucketPlatform.cs | 3 +- NuKeeper.BitBucket/BitbucketSettingsReader.cs | 3 +- .../Collaboration/CollaborationFactory.cs | 2 +- NuKeeper/NuKeeper.csproj | 2 +- 5 files changed, 229 insertions(+), 5 deletions(-) create mode 100644 NuKeeper.BitBucket/BitbucketCommitWorder.cs diff --git a/NuKeeper.BitBucket/BitbucketCommitWorder.cs b/NuKeeper.BitBucket/BitbucketCommitWorder.cs new file mode 100644 index 000000000..523698d94 --- /dev/null +++ b/NuKeeper.BitBucket/BitbucketCommitWorder.cs @@ -0,0 +1,224 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NuGet.Packaging.Core; +using NuGet.Versioning; +using NuKeeper.Abstractions.CollaborationPlatform; +using NuKeeper.Abstractions.Formats; +using NuKeeper.Abstractions.RepositoryInspection; + +namespace NuKeeper.BitBucket +{ + public class BitbucketCommitWorder : ICommitWorder + { + private const string CommitEmoji = "📦"; + + public string MakePullRequestTitle(IReadOnlyCollection updates) + { + if (updates.Count == 1) + { + return PackageTitle(updates.First()); + } + + return $"Automatic update of {updates.Count} packages"; + } + + private static string PackageTitle(PackageUpdateSet updates) + { + return $"Automatic update of {updates.SelectedId} to {updates.SelectedVersion}"; + } + + public string MakeCommitMessage(PackageUpdateSet updates) + { + return $":{CommitEmoji}: {PackageTitle(updates)}"; + } + + public string MakeCommitDetails(IReadOnlyCollection updates) + { + var builder = new StringBuilder(); + + if (updates.Count > 1) + { + MultiPackagePrefix(updates, builder); + } + + foreach (var update in updates) + { + builder.AppendLine(MakeCommitVersionDetails(update)); + } + + AddCommitFooter(builder); + + return builder.ToString(); + } + + private static void MultiPackagePrefix(IReadOnlyCollection updates, StringBuilder builder) + { + var packageNames = updates + .Select(p => CodeQuote(p.SelectedId)) + .JoinWithCommas(); + + var projects = updates.SelectMany( + u => u.CurrentPackages) + .Select(p => p.Path.FullName) + .Distinct() + .ToList(); + + var projectOptS = (projects.Count > 1) ? "s" : string.Empty; + + builder.AppendLine($"{updates.Count} packages were updated in {projects.Count} project{projectOptS}:"); + builder.AppendLine(packageNames); + builder.AppendLine(""); + builder.AppendLine("**Details of updated packages**"); + builder.AppendLine(""); + } + + private static string MakeCommitVersionDetails(PackageUpdateSet updates) + { + var versionsInUse = updates.CurrentPackages + .Select(u => u.Version) + .Distinct() + .ToList(); + + var oldVersions = versionsInUse + .Select(v => CodeQuote(v.ToString())) + .ToList(); + + var minOldVersion = versionsInUse.Min(); + + var newVersion = CodeQuote(updates.SelectedVersion.ToString()); + var packageId = CodeQuote(updates.SelectedId); + + var changeLevel = ChangeLevel(minOldVersion, updates.SelectedVersion); + + var builder = new StringBuilder(); + + if (oldVersions.Count == 1) + { + builder.AppendLine($"NuKeeper has generated a {changeLevel} update of {packageId} to {newVersion} from {oldVersions.JoinWithCommas()}"); + } + else + { + builder.AppendLine($"NuKeeper has generated a {changeLevel} update of {packageId} to {newVersion}"); + builder.AppendLine($"{oldVersions.Count} versions of {packageId} were found in use: {oldVersions.JoinWithCommas()}"); + } + + if (updates.Selected.Published.HasValue) + { + var packageWithVersion = CodeQuote(updates.SelectedId + " " + updates.SelectedVersion); + var pubDateString = CodeQuote(DateFormat.AsUtcIso8601(updates.Selected.Published)); + var pubDate = updates.Selected.Published.Value.UtcDateTime; + var ago = TimeSpanFormat.Ago(pubDate, DateTime.UtcNow); + + builder.AppendLine($"{packageWithVersion} was published at {pubDateString}, {ago}"); + } + + var highestVersion = updates.Packages.Major?.Identity.Version; + if (highestVersion != null && (highestVersion > updates.SelectedVersion)) + { + LogHighestVersion(updates, highestVersion, builder); + } + + builder.AppendLine(); + + if (updates.CurrentPackages.Count == 1) + { + builder.AppendLine("1 project update:"); + } + else + { + builder.AppendLine($"{updates.CurrentPackages.Count} project updates:"); + } + + foreach (var current in updates.CurrentPackages) + { + var line = $"Updated {CodeQuote(current.Path.RelativePath)} to {packageId} {CodeQuote(updates.SelectedVersion.ToString())} from {CodeQuote(current.Version.ToString())}"; + builder.AppendLine(line); + } + + if (SourceIsPublicNuget(updates.Selected.Source.SourceUri)) + { + builder.AppendLine(NugetPackageLink(updates.Selected.Identity)); + } + + return builder.ToString(); + } + + private static void AddCommitFooter(StringBuilder builder) + { + builder.AppendLine(); + builder.AppendLine("This is an automated update. Merge only if it passes tests"); + builder.AppendLine("**NuKeeper**: https://github.com/NuKeeperDotNet/NuKeeper"); + } + + private static string ChangeLevel(NuGetVersion oldVersion, NuGetVersion newVersion) + { + if (newVersion.Major > oldVersion.Major) + { + return "major"; + } + + if (newVersion.Minor > oldVersion.Minor) + { + return "minor"; + } + + if (newVersion.Patch > oldVersion.Patch) + { + return "patch"; + } + + if (!newVersion.IsPrerelease && oldVersion.IsPrerelease) + { + return "out of beta"; + } + + return string.Empty; + } + + private static void LogHighestVersion(PackageUpdateSet updates, NuGetVersion highestVersion, StringBuilder builder) + { + var allowedChange = CodeQuote(updates.AllowedChange.ToString()); + var highest = CodeQuote(updates.SelectedId + " " + highestVersion); + + var highestPublishedAt = HighestPublishedAt(updates.Packages.Major.Published); + + builder.AppendLine( + $"There is also a higher version, {highest}{highestPublishedAt}, " + + $"but this was not applied as only {allowedChange} version changes are allowed."); + } + + private static string HighestPublishedAt(DateTimeOffset? highestPublishedAt) + { + if (!highestPublishedAt.HasValue) + { + return string.Empty; + } + + var highestPubDate = highestPublishedAt.Value; + var formattedPubDate = CodeQuote(DateFormat.AsUtcIso8601(highestPubDate)); + var highestAgo = TimeSpanFormat.Ago(highestPubDate.UtcDateTime, DateTime.UtcNow); + + return $" published at {formattedPubDate}, {highestAgo}"; + } + + private static string CodeQuote(string value) + { + return "`" + value + "`"; + } + + private static bool SourceIsPublicNuget(Uri sourceUrl) + { + return + sourceUrl != null && + sourceUrl.ToString().StartsWith("https://api.nuget.org/", StringComparison.OrdinalIgnoreCase); + } + + private static string NugetPackageLink(PackageIdentity package) + { + var url = $"https://www.nuget.org/packages/{package.Id}/{package.Version}"; + return $"[{package.Id} {package.Version} on NuGet.org]({url})"; + } + } +} diff --git a/NuKeeper.BitBucket/BitbucketPlatform.cs b/NuKeeper.BitBucket/BitbucketPlatform.cs index 936db6dfc..1d580094c 100644 --- a/NuKeeper.BitBucket/BitbucketPlatform.cs +++ b/NuKeeper.BitBucket/BitbucketPlatform.cs @@ -36,8 +36,7 @@ public void Initialise(AuthSettings settings) public Task GetCurrentUser() { - - return Task.FromResult(new User(_settings.Username, "", "")); + return Task.FromResult(new User(_settings.Username, _settings.Username, _settings.Username)); } public async Task OpenPullRequest(ForkData target, PullRequestRequest request, IEnumerable labels) diff --git a/NuKeeper.BitBucket/BitbucketSettingsReader.cs b/NuKeeper.BitBucket/BitbucketSettingsReader.cs index 7da84ea34..ce37775ca 100644 --- a/NuKeeper.BitBucket/BitbucketSettingsReader.cs +++ b/NuKeeper.BitBucket/BitbucketSettingsReader.cs @@ -72,7 +72,8 @@ public Task RepositorySettings(Uri repositoryUri, string tar ApiUri = new Uri("https://api.bitbucket.org/2.0/"), RepositoryUri = repositoryUri, RepositoryName = repoName, - RepositoryOwner = owner + RepositoryOwner = owner, + RemoteInfo = targetBranch != null ? new RemoteInfo { BranchName = targetBranch } : null }); } } diff --git a/NuKeeper/Collaboration/CollaborationFactory.cs b/NuKeeper/Collaboration/CollaborationFactory.cs index acd19a7a0..49faf2bfe 100644 --- a/NuKeeper/Collaboration/CollaborationFactory.cs +++ b/NuKeeper/Collaboration/CollaborationFactory.cs @@ -153,7 +153,7 @@ private void CreateForPlatform() CollaborationPlatform = new BitbucketPlatform(_nuKeeperLogger); RepositoryDiscovery = new BitbucketRepositoryDiscovery(_nuKeeperLogger); ForkFinder = new BitbucketForkFinder(CollaborationPlatform, _nuKeeperLogger, forkMode); - CommitWorder = new DefaultCommitWorder(); + CommitWorder = new BitbucketCommitWorder(); break; case Platform.BitbucketLocal: diff --git a/NuKeeper/NuKeeper.csproj b/NuKeeper/NuKeeper.csproj index 7431150cd..352ffa2b3 100644 --- a/NuKeeper/NuKeeper.csproj +++ b/NuKeeper/NuKeeper.csproj @@ -1,4 +1,4 @@ - + Exe true