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

Commit

Permalink
feat: Support custom templates for commits + PRs
Browse files Browse the repository at this point in the history
This commit introduces mustache templates for commit messages, and pull
request titles and bodies.

The design consists of templates with predefined properties. A custom
template can be provided.

Stubble has been chosen as the template renderer.

It is possible to define additional context for the templates, this also
includes delegates. These can be provided as the value of a "_delegates"
key in the context.
  • Loading branch information
CrispyDrone committed Jan 23, 2021
1 parent 18d6cdb commit 1dd5f23
Show file tree
Hide file tree
Showing 65 changed files with 2,553 additions and 1,034 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using NuKeeper.Abstractions.Output;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;

Expand Down Expand Up @@ -60,6 +61,8 @@ public void MissingFileReturnsNoSettings()
Assert.That(data.Platform, Is.Null);
Assert.That(data.BranchNameTemplate, Is.Null);
Assert.That(data.DeleteBranchAfterMerge, Is.Null);
Assert.That(data.CommitMessageTemplate, Is.Null);
Assert.That(data.Context, Is.Null);
}

[Test]
Expand Down Expand Up @@ -92,6 +95,8 @@ public void EmptyConfigReturnsNoSettings()
Assert.That(data.Platform, Is.Null);
Assert.That(data.BranchNameTemplate, Is.Null);
Assert.That(data.DeleteBranchAfterMerge, Is.Null);
Assert.That(data.CommitMessageTemplate, Is.Null);
Assert.That(data.Context, Is.Null);
}

private const string FullFileData = @"{
Expand All @@ -116,7 +121,9 @@ public void EmptyConfigReturnsNoSettings()
""OutputFileName"" : ""out_42.txt"",
""LogDestination"" : ""file"",
""Platform"" : ""Bitbucket"",
""DeleteBranchAfterMerge"": ""true""
""DeleteBranchAfterMerge"": ""true"",
""CommitMessageTemplate"": ""📦 Automatic update from {{packageName}} to {{packageVersion}}"",
""Context"": { ""company"": ""NuKeeper"", ""issue"": ""JIRA-001"" }
}";

[Test]
Expand All @@ -139,6 +146,17 @@ public void PopulatedConfigReturnsAllStringSettings()
Assert.That(data.OutputFileName, Is.EqualTo("out_42.txt"));
Assert.That(data.BranchNameTemplate, Is.EqualTo("nukeeper/MyBranch"));
Assert.That(data.DeleteBranchAfterMerge, Is.EqualTo(true));
Assert.That(data.CommitMessageTemplate, Is.EqualTo("📦 Automatic update from {{packageName}} to {{packageVersion}}"));
Assert.That(
data.Context,
Is.EquivalentTo(
new Dictionary<string, object>
{
{ "company", "NuKeeper" },
{ "issue", "JIRA-001" }
}
)
);
}

[Test]
Expand Down Expand Up @@ -206,7 +224,9 @@ public void ConfigKeysAreCaseInsensitive()
""vErBoSiTy"": ""Q"",
""CHANGE"": ""PATCH"",
""bRanCHNamETempLATe"": ""nukeeper/MyBranch"",
""deLeTEBranCHafTERMerge"": ""true""
""deLeTEBranCHafTERMerge"": ""true"",
""coMmItmESsageTeMpLate"": ""📦 Automatic update from {{packageName}} to {{packageVersion}}"",
""cOntExT"": { ""company"": ""NuKeeper"", ""issue"": ""JIRA-001"" }
}";

var path = MakeTestFile(configData);
Expand All @@ -230,6 +250,17 @@ public void ConfigKeysAreCaseInsensitive()
Assert.That(data.Change, Is.EqualTo(VersionChange.Patch));
Assert.That(data.BranchNameTemplate, Is.EqualTo("nukeeper/MyBranch"));
Assert.That(data.DeleteBranchAfterMerge, Is.EqualTo(true));
Assert.That(data.CommitMessageTemplate, Is.EqualTo("📦 Automatic update from {{packageName}} to {{packageVersion}}"));
Assert.That(
data.Context,
Is.EquivalentTo(
new Dictionary<string, string>
{
{ "company", "NuKeeper" },
{ "issue", "JIRA-001" }
}
)
);
}

[Test]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using NuKeeper.Abstractions.CollaborationPlatform;

namespace NuKeeper.Abstractions.CollaborationModels
{
public class CommitUpdateMessageTemplate : UpdateMessageTemplate
{
private const string CommitEmoji = "📦";

public CommitUpdateMessageTemplate()
: base(new StubbleTemplateRenderer())
{
PackageEmoji = CommitEmoji;
}

public static string DefaultTemplate { get; } =
"{{#packageEmoji}}{{packageEmoji}} {{/packageEmoji}}Automatic update of {{^multipleChanges}}{{#packages}}{{Name}} to {{Version}}{{/packages}}{{/multipleChanges}}{{#multipleChanges}}{{packageCount}} packages{{/multipleChanges}}";

public override string Value
{
get
{
return CustomTemplate ?? DefaultTemplate;
}
}

public string CustomTemplate { get; set; }

public object PackageEmoji
{
get
{
Context.TryGetValue(Constants.Template.PackageEmoji, out var packageEmoji);
return packageEmoji;
}
set
{
Context[Constants.Template.PackageEmoji] = value;
}
}

public override void Clear()
{
base.Clear();
PackageEmoji = CommitEmoji;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using NuKeeper.Abstractions.CollaborationPlatform;

namespace NuKeeper.Abstractions.CollaborationModels
{
public class DefaultPullRequestBodyTemplate : UpdateMessageTemplate
{
public DefaultPullRequestBodyTemplate()
: base(new StubbleTemplateRenderer()) { }

public static string DefaultTemplate { get; } =
@"{{#multipleChanges}}{{packageCount}} packages were updated in {{projectsUpdated}} project{{#multipleProjects}}s{{/multipleProjects}}:
{{#packages}}`{{Name}}`{{^Last}}, {{/Last}}{{/packages}}
<details>
<summary>Details of updated packages</summary>
{{/multipleChanges}}
{{#packages}}NuKeeper has generated a {{ActualChange}} update of `{{Name}}` to `{{Version}}`{{^MultipleUpdates}} from `{{FromVersion}}`{{/MultipleUpdates}}
{{#MultipleUpdates}}{{ProjectsUpdated}} versions of `{{Name}}` were found in use: {{#Updates}}`{{FromVersion}}`{{^Last}}, {{/Last}}{{/Updates}}{{/MultipleUpdates}}
{{#Publication}}`{{Name}} {{Version}}` was published at `{{Date}}`, {{Ago}}{{/Publication}}
{{#LatestVersion}}There is also a higher version, `{{Name}} {{Version}}`{{#Publication}} published at `{{Date}}`, {{Ago}}{{/Publication}}, but this was not applied as only `{{AllowedChange}}` version changes are allowed.
{{/LatestVersion}}
{{ProjectsUpdated}} project update{{#MultipleProjectsUpdated}}s{{/MultipleProjectsUpdated}}:
{{#Updates}}
Updated `{{SourceFilePath}}` to `{{Name}}` `{{ToVersion}}` from `{{FromVersion}}`
{{/Updates}}
{{#IsFromNuget}}
[{{Name}} {{Version}} on NuGet.org]({{Url}})
{{/IsFromNuget}}
{{/packages}}
{{#multipleChanges}}
</details>
{{/multipleChanges}}
{{#footer}}
{{WarningMessage}}
**NuKeeper**: {{NuKeeperUrl}}
{{/footer}}
";

public string CustomTemplate { get; set; }

public override string Value => CustomTemplate ?? DefaultTemplate;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using NuKeeper.Abstractions.CollaborationPlatform;

namespace NuKeeper.Abstractions.CollaborationModels
{
public class DefaultPullRequestTitleTemplate : UpdateMessageTemplate
{
public DefaultPullRequestTitleTemplate()
: base(new StubbleTemplateRenderer()) { }

public static string DefaultTemplate { get; } =
"Automatic update of {{^multipleChanges}}{{#packages}}{{Name}} to {{Version}}{{/packages}}{{/multipleChanges}}{{#multipleChanges}}{{packageCount}} packages{{/multipleChanges}}";

public string CustomTemplate { get; set; }

public override string Value => CustomTemplate ?? DefaultTemplate;
}
}
10 changes: 10 additions & 0 deletions NuKeeper.Abstractions/CollaborationModels/FooterTemplate.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace NuKeeper.Abstractions.CollaborationModels
{
public class FooterTemplate
{
#pragma warning disable CA1056 // Uri properties should not be strings
public string NuKeeperUrl { get; set; }
#pragma warning restore CA1056 // Uri properties should not be strings
public string WarningMessage { get; set; }
}
}
11 changes: 11 additions & 0 deletions NuKeeper.Abstractions/CollaborationModels/LatestPackageTemplate.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace NuKeeper.Abstractions.CollaborationModels
{
public class LatestPackageTemplate
{
public string Version { get; set; }
#pragma warning disable CA1056 // Uri properties should not be strings
public string Url { get; set; }
#pragma warning restore CA1056 // Uri properties should not be strings
public PublicationTemplate Publication { get; set; }
}
}
32 changes: 32 additions & 0 deletions NuKeeper.Abstractions/CollaborationModels/PackageTemplate.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#pragma warning disable CA1819 // Properties should not return arrays
#pragma warning disable CA1056 // Uri properties should not be strings

using System;
using System.Linq;

namespace NuKeeper.Abstractions.CollaborationModels
{
public class PackageTemplate
{
public string Name { get; set; }
public string Version { get; set; }
public string FromVersion => MultipleUpdates ?
string.Empty
: Updates.FirstOrDefault()?.FromVersion;
public string AllowedChange { get; set; }
public string ActualChange { get; set; }
public PublicationTemplate Publication { get; set; }
public int ProjectsUpdated =>
Updates?.Length ?? 0;
public LatestPackageTemplate LatestVersion { get; set; }
public string Url { get; set; }
public string SourceUrl { get; set; }
public bool IsFromNuget { get; set; }
public UpdateTemplate[] Updates { get; set; }
public bool MultipleProjectsUpdated => Updates?.Length > 1;
public bool MultipleUpdates => Updates?
.Select(u => u.FromVersion)
.Distinct(StringComparer.InvariantCultureIgnoreCase)
.Count() > 1;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace NuKeeper.Abstractions.CollaborationModels
{
public class PublicationTemplate
{
public string Date { get; set; }
public string Ago { get; set; }
}
}
Loading

0 comments on commit 1dd5f23

Please sign in to comment.