Skip to content

Commit e9da07f

Browse files
committed
Merge pull request #489 from thogil/commit-message-strategy
Add support for indicating change severity in commit messages
2 parents eca5ac8 + f3947a9 commit e9da07f

17 files changed

+219
-18
lines changed

src/GitVersionCore.Tests/ConfigProviderTests.CanWriteOutEffectiveConfiguration.approved.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
mode: ContinuousDelivery
33
tag-prefix: '[vV]'
44
continuous-delivery-fallback-tag: ci
5+
major-version-bump-message: '\+semver:\s?(breaking|major)'
6+
minor-version-bump-message: '\+semver:\s?(feature|minor)'
7+
patch-version-bump-message: '\+semver:\s?(fix|patch)'
8+
commit-message-incrementing: Enabled
59
branches:
610
master:
711
mode: ContinuousDelivery

src/GitVersionCore.Tests/TestEffectiveConfiguration.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,16 @@ public TestEffectiveConfiguration(
1414
bool preventIncrementForMergedBranchVersion = false,
1515
string tagNumberPattern = null,
1616
string continuousDeploymentFallbackTag = "ci",
17-
bool trackMergeTarget = false) :
17+
bool trackMergeTarget = false,
18+
string majorMessage = null,
19+
string minorMessage = null,
20+
string patchMessage = null,
21+
CommitMessageIncrementMode commitMessageMode = CommitMessageIncrementMode.Enabled) :
1822
base(assemblyVersioningScheme, versioningMode, gitTagPrefix, tag, nextVersion, IncrementStrategy.Patch,
1923
branchPrefixToTrim, preventIncrementForMergedBranchVersion, tagNumberPattern, continuousDeploymentFallbackTag,
20-
trackMergeTarget)
24+
trackMergeTarget,
25+
majorMessage, minorMessage, patchMessage,
26+
commitMessageMode)
2127
{
2228
}
2329
}

src/GitVersionCore/Configuration/BranchConfig.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ public BranchConfig(BranchConfig branchConfiguration)
1616
PreventIncrementOfMergedBranchVersion = branchConfiguration.PreventIncrementOfMergedBranchVersion;
1717
TagNumberPattern = branchConfiguration.TagNumberPattern;
1818
TrackMergeTarget = branchConfiguration.TrackMergeTarget;
19+
CommitMessageIncrementing = branchConfiguration.CommitMessageIncrementing;
1920
}
2021

2122
[YamlMember(Alias = "mode")]
@@ -38,5 +39,8 @@ public BranchConfig(BranchConfig branchConfiguration)
3839

3940
[YamlMember(Alias = "track-merge-target")]
4041
public bool? TrackMergeTarget { get; set; }
42+
43+
[YamlMember(Alias = "commit-message-incrementing")]
44+
public CommitMessageIncrementMode? CommitMessageIncrementing { get; set; }
4145
}
4246
}

src/GitVersionCore/Configuration/Config.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,18 @@ public class Config
2323
[YamlMember(Alias = "next-version")]
2424
public string NextVersion { get; set; }
2525

26+
[YamlMember(Alias = "major-version-bump-message")]
27+
public string MajorVersionBumpMessage { get; set; }
28+
29+
[YamlMember(Alias = "minor-version-bump-message")]
30+
public string MinorVersionBumpMessage { get; set; }
31+
32+
[YamlMember(Alias = "patch-version-bump-message")]
33+
public string PatchVersionBumpMessage { get; set; }
34+
35+
[YamlMember(Alias = "commit-message-incrementing")]
36+
public CommitMessageIncrementMode? CommitMessageIncrementing { get; set; }
37+
2638
[YamlMember(Alias = "branches")]
2739
public Dictionary<string, BranchConfig> Branches
2840
{

src/GitVersionCore/Configuration/ConfigurationProvider.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ public static void ApplyDefaultsTo(Config config)
2424
config.TagPrefix = config.TagPrefix ?? DefaultTagPrefix;
2525
config.VersioningMode = config.VersioningMode ?? VersioningMode.ContinuousDelivery;
2626
config.ContinuousDeploymentFallbackTag = config.ContinuousDeploymentFallbackTag ?? "ci";
27+
config.MajorVersionBumpMessage = config.MajorVersionBumpMessage ?? IncrementStrategyFinder.DefaultMajorPattern;
28+
config.MinorVersionBumpMessage = config.MinorVersionBumpMessage ?? IncrementStrategyFinder.DefaultMinorPattern;
29+
config.PatchVersionBumpMessage = config.PatchVersionBumpMessage ?? IncrementStrategyFinder.DefaultPatchPattern;
30+
config.CommitMessageIncrementing = config.CommitMessageIncrementing ?? CommitMessageIncrementMode.Enabled;
2731
var configBranches = config.Branches.ToList();
2832

2933
ApplyBranchDefaults(config, GetOrCreateBranchDefaults(config, "master"), defaultTag: string.Empty, defaultPreventIncrement: true);

src/GitVersionCore/Configuration/IncrementStrategy.cs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
namespace GitVersion
22
{
3+
using System;
4+
35
public enum IncrementStrategy
46
{
57
None,
@@ -9,6 +11,26 @@ public enum IncrementStrategy
911
/// <summary>
1012
/// Uses the increment strategy from the branch the current branch was branched from
1113
/// </summary>
12-
Inherit
14+
Inherit
15+
}
16+
17+
public static class IncrementStrategyExtensions
18+
{
19+
public static VersionField ToVersionField(this IncrementStrategy strategy)
20+
{
21+
switch (strategy)
22+
{
23+
case IncrementStrategy.None:
24+
return VersionField.None;
25+
case IncrementStrategy.Major:
26+
return VersionField.Major;
27+
case IncrementStrategy.Minor:
28+
return VersionField.Minor;
29+
case IncrementStrategy.Patch:
30+
return VersionField.Patch;
31+
default:
32+
throw new ArgumentOutOfRangeException("strategy", strategy, null);
33+
}
34+
}
1335
}
1436
}

src/GitVersionCore/EffectiveConfiguration.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ public EffectiveConfiguration(
1313
bool preventIncrementForMergedBranchVersion,
1414
string tagNumberPattern,
1515
string continuousDeploymentFallbackTag,
16-
bool trackMergeTarget)
16+
bool trackMergeTarget,
17+
string majorVersionBumpMessage,
18+
string minorVersionBumpMessage,
19+
string patchVersionBumpMessage,
20+
CommitMessageIncrementMode commitMessageIncrementing)
1721
{
1822
AssemblyVersioningScheme = assemblyVersioningScheme;
1923
VersioningMode = versioningMode;
@@ -26,6 +30,10 @@ public EffectiveConfiguration(
2630
TagNumberPattern = tagNumberPattern;
2731
ContinuousDeploymentFallbackTag = continuousDeploymentFallbackTag;
2832
TrackMergeTarget = trackMergeTarget;
33+
MajorVersionBumpMessage = majorVersionBumpMessage;
34+
MinorVersionBumpMessage = minorVersionBumpMessage;
35+
PatchVersionBumpMessage = patchVersionBumpMessage;
36+
CommitMessageIncrementing = commitMessageIncrementing;
2937
}
3038

3139
public VersioningMode VersioningMode { get; private set; }
@@ -55,5 +63,13 @@ public EffectiveConfiguration(
5563
public string ContinuousDeploymentFallbackTag { get; private set; }
5664

5765
public bool TrackMergeTarget { get; private set; }
66+
67+
public string MajorVersionBumpMessage { get; private set; }
68+
69+
public string MinorVersionBumpMessage { get; private set; }
70+
71+
public string PatchVersionBumpMessage { get; private set; }
72+
73+
public CommitMessageIncrementMode CommitMessageIncrementing { get; private set; }
5874
}
5975
}

src/GitVersionCore/FodyWeavers.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?xml version="1.0" encoding="utf-8"?>
1+
<?xml version="1.0" encoding="utf-8"?>
22
<Weavers VerifyAssembly="true">
33
<Caseless/>
44
<JetBrainsAnnotations/>

src/GitVersionCore/GitVersionContext.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,23 +91,33 @@ void CalculateEffectiveConfiguration()
9191
throw new Exception(string.Format("Configuration value for 'TrackMergeTarget' for branch {0} has no value. (this should not happen, please report an issue)", currentBranchConfig.Key));
9292
if (!configuration.AssemblyVersioningScheme.HasValue)
9393
throw new Exception("Configuration value for 'AssemblyVersioningScheme' has no value. (this should not happen, please report an issue)");
94+
if (!configuration.CommitMessageIncrementing.HasValue)
95+
throw new Exception("Configuration value for 'CommitMessageIncrementing' has no value. (this should not happen, please report an issue)");
9496

9597
var versioningMode = currentBranchConfig.Value.VersioningMode.Value;
9698
var tag = currentBranchConfig.Value.Tag;
9799
var tagNumberPattern = currentBranchConfig.Value.TagNumberPattern;
98100
var incrementStrategy = currentBranchConfig.Value.Increment.Value;
99101
var preventIncrementForMergedBranchVersion = currentBranchConfig.Value.PreventIncrementOfMergedBranchVersion.Value;
100102
var trackMergeTarget = currentBranchConfig.Value.TrackMergeTarget.Value;
101-
103+
102104
var nextVersion = configuration.NextVersion;
103105
var assemblyVersioningScheme = configuration.AssemblyVersioningScheme.Value;
104106
var gitTagPrefix = configuration.TagPrefix;
107+
var majorMessage = configuration.MajorVersionBumpMessage;
108+
var minorMessage = configuration.MinorVersionBumpMessage;
109+
var patchMessage = configuration.MinorVersionBumpMessage;
110+
111+
var commitMessageVersionBump = currentBranchConfig.Value.CommitMessageIncrementing ?? configuration.CommitMessageIncrementing.Value;
112+
105113
Configuration = new EffectiveConfiguration(
106114
assemblyVersioningScheme, versioningMode, gitTagPrefix,
107115
tag, nextVersion, incrementStrategy, currentBranchConfig.Key,
108116
preventIncrementForMergedBranchVersion,
109117
tagNumberPattern, configuration.ContinuousDeploymentFallbackTag,
110-
trackMergeTarget);
118+
trackMergeTarget,
119+
majorMessage, minorMessage, patchMessage,
120+
commitMessageVersionBump);
111121
}
112122
}
113123
}

src/GitVersionCore/GitVersionCore.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@
113113
<Compile Include="Helpers\IFileSystem.cs" />
114114
<Compile Include="Helpers\ProcessHelper.cs" />
115115
<Compile Include="Helpers\ServiceMessageEscapeHelper.cs" />
116+
<Compile Include="IncrementStrategyFinder.cs" />
116117
<Compile Include="OutputVariables\VersionVariables.cs" />
117118
<Compile Include="Extensions\ExtensionMethods.git.cs" />
118119
<Compile Include="SemanticVersionExtensions.cs" />
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
namespace GitVersion
2+
{
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Text.RegularExpressions;
6+
using VersionCalculation.BaseVersionCalculators;
7+
using LibGit2Sharp;
8+
9+
public enum CommitMessageIncrementMode
10+
{
11+
Enabled,
12+
Disabled,
13+
MergeMessageOnly
14+
}
15+
16+
public static class IncrementStrategyFinder
17+
{
18+
public const string DefaultMajorPattern = @"\+semver:\s?(breaking|major)";
19+
public const string DefaultMinorPattern = @"\+semver:\s?(feature|minor)";
20+
public const string DefaultPatchPattern = @"\+semver:\s?(fix|patch)";
21+
22+
public static VersionField? DetermineIncrementedField(GitVersionContext context, BaseVersion baseVersion)
23+
{
24+
var commitMessageIncrement = FindCommitMessageIncrement(context, baseVersion);
25+
var defaultIncrement = context.Configuration.Increment.ToVersionField();
26+
27+
// use the default branch config increment strategy if there are no commit message overrides
28+
if (commitMessageIncrement == null)
29+
{
30+
return baseVersion.ShouldIncrement ? defaultIncrement : (VersionField?)null;
31+
}
32+
33+
// cap the commit message severity to minor for alpha versions
34+
if (baseVersion.SemanticVersion < new SemanticVersion(1) && commitMessageIncrement > VersionField.Minor)
35+
{
36+
commitMessageIncrement = VersionField.Minor;
37+
}
38+
39+
// don't increment for less than the branch config increment, if the absense of commit messages would have
40+
// still resulted in an increment of configuration.Increment
41+
if (baseVersion.ShouldIncrement && commitMessageIncrement < defaultIncrement)
42+
{
43+
return defaultIncrement;
44+
}
45+
46+
return commitMessageIncrement;
47+
}
48+
49+
private static VersionField? FindCommitMessageIncrement(GitVersionContext context, BaseVersion baseVersion)
50+
{
51+
if (context.Configuration.CommitMessageIncrementing == CommitMessageIncrementMode.Disabled)
52+
{
53+
return null;
54+
}
55+
56+
var commits = GetIntermediateCommits(context.Repository, baseVersion.BaseVersionSource, context.CurrentCommit);
57+
58+
if (context.Configuration.CommitMessageIncrementing == CommitMessageIncrementMode.MergeMessageOnly)
59+
{
60+
commits = commits.Where(c => c.Parents.Count() > 1);
61+
}
62+
63+
var majorRegex = CreateRegex(context.Configuration.MajorVersionBumpMessage ?? DefaultMajorPattern);
64+
var minorRegex = CreateRegex(context.Configuration.MinorVersionBumpMessage ?? DefaultMinorPattern);
65+
var patchRegex = CreateRegex(context.Configuration.PatchVersionBumpMessage ?? DefaultPatchPattern);
66+
67+
var increments = commits
68+
.Select(c => FindIncrementFromMessage(c.Message, majorRegex, minorRegex, patchRegex))
69+
.Where(v => v != null)
70+
.Select(v => v.Value)
71+
.ToList();
72+
73+
if (increments.Any())
74+
{
75+
return increments.Max();
76+
}
77+
78+
return null;
79+
}
80+
81+
private static IEnumerable<Commit> GetIntermediateCommits(IRepository repo, Commit baseCommit, Commit headCommit)
82+
{
83+
var filter = new CommitFilter
84+
{
85+
Since = headCommit,
86+
Until = baseCommit,
87+
SortBy = CommitSortStrategies.Topological | CommitSortStrategies.Reverse
88+
};
89+
90+
return repo.Commits.QueryBy(filter);
91+
}
92+
93+
private static VersionField? FindIncrementFromMessage(string message, Regex major, Regex minor, Regex patch)
94+
{
95+
if (major.IsMatch(message)) return VersionField.Major;
96+
if (minor.IsMatch(message)) return VersionField.Minor;
97+
if (patch.IsMatch(message)) return VersionField.Patch;
98+
99+
return null;
100+
}
101+
102+
private static Regex CreateRegex(string pattern)
103+
{
104+
return new Regex(pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase);
105+
}
106+
}
107+
}

src/GitVersionCore/SemanticVersion.cs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -281,25 +281,25 @@ public string ToString(string format, IFormatProvider formatProvider = null)
281281
}
282282
}
283283

284-
public SemanticVersion IncrementVersion(IncrementStrategy incrementStrategy)
284+
public SemanticVersion IncrementVersion(VersionField incrementStrategy)
285285
{
286286
var incremented = new SemanticVersion(this);
287287
if (!incremented.PreReleaseTag.HasTag())
288288
{
289289
switch (incrementStrategy)
290290
{
291-
case IncrementStrategy.None:
291+
case VersionField.None:
292292
break;
293-
case IncrementStrategy.Major:
293+
case VersionField.Major:
294294
incremented.Major++;
295295
incremented.Minor = 0;
296296
incremented.Patch = 0;
297297
break;
298-
case IncrementStrategy.Minor:
298+
case VersionField.Minor:
299299
incremented.Minor++;
300300
incremented.Patch = 0;
301301
break;
302-
case IncrementStrategy.Patch:
302+
case VersionField.Patch:
303303
incremented.Patch++;
304304
break;
305305
default:
@@ -318,4 +318,12 @@ public SemanticVersion IncrementVersion(IncrementStrategy incrementStrategy)
318318
return incremented;
319319
}
320320
}
321+
322+
public enum VersionField
323+
{
324+
None,
325+
Patch,
326+
Minor,
327+
Major
328+
}
321329
}

src/GitVersionCore/VersionCalculation/BaseVersionCalculator.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,13 @@ public BaseVersion GetBaseVersion(GitVersionContext context)
7474

7575
static SemanticVersion MaybeIncrement(GitVersionContext context, BaseVersion version)
7676
{
77-
return version.ShouldIncrement ? version.SemanticVersion.IncrementVersion(context.Configuration.Increment) : version.SemanticVersion;
77+
var increment = IncrementStrategyFinder.DetermineIncrementedField(context, version);
78+
if (increment != null)
79+
{
80+
return version.SemanticVersion.IncrementVersion(increment.Value);
81+
}
82+
83+
return version.SemanticVersion;
7884
}
7985
}
8086
}

src/GitVersionCore/VersionCalculation/NextVersionCalculator.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,10 @@ public SemanticVersion FindVersion(GitVersionContext context)
3838

3939
var baseVersion = baseVersionFinder.GetBaseVersion(context);
4040
var semver = baseVersion.SemanticVersion;
41-
if (baseVersion.ShouldIncrement)
41+
var increment = IncrementStrategyFinder.DetermineIncrementedField(context, baseVersion);
42+
if (increment != null)
4243
{
43-
semver = semver.IncrementVersion(context.Configuration.Increment);
44+
semver = semver.IncrementVersion(increment.Value);
4445
}
4546
else Logger.WriteInfo("Skipping version increment");
4647

src/GitVersionCore/packages.config

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@
55
<package id="JetBrainsAnnotations.Fody" version="1.0.4.0" targetFramework="net40" developmentDependency="true" />
66
<package id="LibGit2Sharp" version="0.21.0.176" targetFramework="net40" />
77
<package id="PepitaPackage" version="1.21.4" targetFramework="net40" developmentDependency="true" />
8-
<package id="Visualize.Fody" version="0.4.3.0" targetFramework="net40" developmentDependency="true" />
8+
<package id="Visualize.Fody" version="0.4.4.0" targetFramework="net40" developmentDependency="true" />
99
<package id="YamlDotNet" version="3.6.1" targetFramework="net40" />
1010
</packages>

0 commit comments

Comments
 (0)