Skip to content

Feature/fix mainline feature branch bump #1224

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using GitVersionCore.Tests;
using LibGit2Sharp;
using NUnit.Framework;
using System.Collections.Generic;

public class MainlineDevelopmentMode
{
Expand Down Expand Up @@ -206,7 +207,7 @@ public void VerifyMergingMasterToFeatureDoesNotCauseBranchCommitsToIncrementVers

fixture.BranchTo("feature/foo", "foo");
fixture.MakeACommit("first in foo");

fixture.Checkout("master");
fixture.MakeACommit("second in master");

Expand Down Expand Up @@ -303,6 +304,41 @@ public void VerifyMergingMasterIntoAFeatureBranchWorksWithMultipleBranches()
fixture.AssertFullSemver(config, "1.0.2");
}
}

[Test]
public void MergingFeatureBranchThatIncrementsMinorNumberIncrementsMinorVersionOfMaster()
{
var currentConfig = new Config
{
VersioningMode = VersioningMode.Mainline,
Branches = new Dictionary<string, BranchConfig>
{
{
"feature", new BranchConfig
{
VersioningMode = VersioningMode.ContinuousDeployment,
Increment = IncrementStrategy.Minor
}
}
}
};

using (var fixture = new EmptyRepositoryFixture())
{
fixture.MakeACommit("first in master");
fixture.MakeATaggedCommit("1.0.0");
fixture.AssertFullSemver(currentConfig, "1.0.0");

fixture.BranchTo("feature/foo", "foo");
fixture.MakeACommit("first in foo");
fixture.MakeACommit("second in foo");
fixture.AssertFullSemver(currentConfig, "1.1.0-foo.2");

fixture.Checkout("master");
fixture.MergeNoFF("feature/foo");
fixture.AssertFullSemver(currentConfig, "1.1.0");
}
}
}

static class CommitExtensions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,12 @@ Another commit message
Commit message including a IP-number https://10.50.1.1
A commit message")]
[TestCase(@"Merge branch 'release/Sprint_2.0_Holdings_Computed_Balances'")]
[TestCase(@"Merge branch 'feature/fix-for-08.14-push'")]
[TestCase(@"Merge branch 'develop' of http://10.0.6.3/gitblit/r/... into develop")]
[TestCase(@"Merge branch 'master' of http://172.16.3.10:8082/r/asu_tk/p_sd")]
[TestCase(@"Merge branch 'master' of http://212.248.89.56:8082/r/asu_tk/p_sd")]
[TestCase(@"Merge branch 'DEMO' of http://10.10.10.121/gitlab/mtolland/orcid into DEMO")]
public void MergeMessagesThatIsNotRelatedToGitVersion(string commitMessage)
{

var parents = GetParents(true);

AssertMergeMessage(commitMessage, null, parents);
Expand Down
51 changes: 10 additions & 41 deletions src/GitVersionCore/BranchConfigurationCalculator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,50 +13,21 @@ public class BranchConfigurationCalculator
/// </summary>
public static BranchConfig GetBranchConfiguration(GitVersionContext context, Branch targetBranch, IList<Branch> excludedInheritBranches = null)
{
var matchingBranches = LookupBranchConfiguration(context.FullConfiguration, targetBranch).ToArray();

BranchConfig branchConfiguration;
if (matchingBranches.Length > 0)
{
branchConfiguration = matchingBranches[0];

if (matchingBranches.Length > 1)
{
Logger.WriteWarning(string.Format(
"Multiple branch configurations match the current branch branchName of '{0}'. Using the first matching configuration, '{1}'. Matching configurations include: '{2}'",
targetBranch.FriendlyName,
branchConfiguration.Name,
string.Join("', '", matchingBranches.Select(b => b.Name))));
}
}
else
var matchingBranches = context.FullConfiguration.GetConfigForBranch(targetBranch.FriendlyName);

if (matchingBranches == null)
{
Logger.WriteInfo(string.Format(
"No branch configuration found for branch {0}, falling back to default configuration",
targetBranch.FriendlyName));

branchConfiguration = new BranchConfig { Name = string.Empty };
ConfigurationProvider.ApplyBranchDefaults(context.FullConfiguration, branchConfiguration, "");
}

return branchConfiguration.Increment == IncrementStrategy.Inherit ?
InheritBranchConfiguration(context, targetBranch, branchConfiguration, excludedInheritBranches) :
branchConfiguration;
}

static IEnumerable<BranchConfig> LookupBranchConfiguration(Config config, Branch currentBranch)
{
if (config == null)
{
throw new ArgumentNullException(nameof(config));
}

if (currentBranch == null)
{
throw new ArgumentNullException(nameof(currentBranch));
matchingBranches = new BranchConfig { Name = string.Empty };
ConfigurationProvider.ApplyBranchDefaults(context.FullConfiguration, matchingBranches, "");
}

return config.Branches.Where(b => Regex.IsMatch(currentBranch.FriendlyName, "^" + b.Value.Regex, RegexOptions.IgnoreCase)).Select(kvp => kvp.Value);
return matchingBranches.Increment == IncrementStrategy.Inherit ?
InheritBranchConfiguration(context, targetBranch, matchingBranches, excludedInheritBranches) :
matchingBranches;
}

static BranchConfig InheritBranchConfiguration(GitVersionContext context, Branch targetBranch, BranchConfig branchConfiguration, IList<Branch> excludedInheritBranches)
Expand All @@ -77,11 +48,9 @@ static BranchConfig InheritBranchConfiguration(GitVersionContext context, Branch
{
excludedInheritBranches = repository.Branches.Where(b =>
{
var branchConfig = LookupBranchConfiguration(config, b).ToArray();
var branchConfig = config.GetConfigForBranch(b.FriendlyName);

// NOTE: if length is 0 we couldn't find the configuration for the branch e.g. "origin/master"
// NOTE: if the length is greater than 1 we cannot decide which merge strategy to pick
return (branchConfig.Length != 1) || (branchConfig.Length == 1 && branchConfig[0].Increment == IncrementStrategy.Inherit);
return branchConfig != null && branchConfig.Increment == IncrementStrategy.Inherit;
}).ToList();
}
// Add new excluded branches.
Expand Down
29 changes: 29 additions & 0 deletions src/GitVersionCore/Configuration/Config.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
namespace GitVersion
{
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
using YamlDotNet.Serialization;

public class Config
Expand Down Expand Up @@ -89,6 +91,33 @@ public Dictionary<string, BranchConfig> Branches
}
}

public BranchConfig GetConfigForBranch(string branchName)
{
if (branchName == null) throw new ArgumentNullException(nameof(branchName));
var matches = Branches
.Where(b => Regex.IsMatch(branchName, "^" + b.Value.Regex, RegexOptions.IgnoreCase));

try
{
return matches
.Select(kvp => kvp.Value)
.SingleOrDefault();
}
catch (InvalidOperationException)
{
var matchingConfigs = string.Join("\n - ", matches.Select(m => m.Key));
var picked = matches
.Select(kvp => kvp.Value)
.First();

Logger.WriteWarning(
$"Multiple branch configurations match the current branch branchName of '{branchName}'. " +
$"Using the first matching configuration, '{picked}'. Matching configurations include: '{matchingConfigs}'");

return picked;
}
}

T MergeObjects<T>(T target, T source)
{
typeof(T).GetProperties()
Expand Down
2 changes: 2 additions & 0 deletions src/GitVersionCore/GitVersionCore.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,12 @@
<Compile Include="Helpers\ThreadSleep.cs" />
<Compile Include="IncrementStrategyFinder.cs" />
<Compile Include="LoggerWrapper.cs" />
<Compile Include="MergeMessage.cs" />
<Compile Include="OutputVariables\VersionVariables.cs" />
<Compile Include="SemanticVersionExtensions.cs" />
<Compile Include="SemanticVersionFormatValues.cs" />
<Compile Include="VerbosityLevel.cs" />
<Compile Include="VersionCalculation\MainlineVersionCalculator.cs" />
<Compile Include="VersionFilters\MinDateVersionFilter.cs" />
<Compile Include="VersionFilters\IVersionFilter.cs" />
<Compile Include="VersionFilters\ShaVersionFilter.cs" />
Expand Down
89 changes: 89 additions & 0 deletions src/GitVersionCore/MergeMessage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
using System;
using System.Linq;
using System.Text.RegularExpressions;

namespace GitVersion
{
class MergeMessage
{
static Regex parseMergeMessage = new Regex(
@"^Merge (branch|tag) '(?<Branch>[^']*)'",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
static Regex parseGitHubPullMergeMessage = new Regex(
@"^Merge pull request #(?<PullRequestNumber>\d*) (from|in) (?<Source>.*)",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
static Regex smartGitMergeMessage = new Regex(
@"^Finish (?<Branch>.*)",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
private string mergeMessage;
private Config config;

public MergeMessage(string mergeMessage, Config config)
{
this.mergeMessage = mergeMessage;
this.config = config;

var lastIndexOf = mergeMessage.LastIndexOf("into", StringComparison.OrdinalIgnoreCase);
if (lastIndexOf != -1)
{
// If we have into in the merge message the rest should be the target branch
TargetBranch = mergeMessage.Substring(lastIndexOf + 5);
}

MergedBranch = ParseBranch();

// Remove remotes and branch prefixes like release/ feature/ hotfix/ etc
var toMatch = Regex.Replace(MergedBranch, @"^(\w+[-/])*", "", RegexOptions.IgnoreCase);
toMatch = Regex.Replace(toMatch, $"^{config.TagPrefix}", "");
// We don't match if the version is likely an ip (i.e starts with http://)
var versionMatch = new Regex(@"^(?<!://)\d+\.\d+(\.*\d+)*");
var version = versionMatch.Match(toMatch);

if (version.Success)
{
SemanticVersion val;
if (SemanticVersion.TryParse(version.Value, config.TagPrefix, out val))
{
Version = val;
}
}
}

private string ParseBranch()
{
var match = parseMergeMessage.Match(mergeMessage);
if (match.Success)
{
return match.Groups["Branch"].Value;
}

match = smartGitMergeMessage.Match(mergeMessage);
if (match.Success)
{
return match.Groups["Branch"].Value;
}

match = parseGitHubPullMergeMessage.Match(mergeMessage);
if (match.Success)
{
IsMergedPullRequest = true;
int pullNumber;
if (int.TryParse(match.Groups["PullRequestNumber"].Value, out pullNumber))
{
PullRequestNumber = pullNumber;
}
var from = match.Groups["Source"].Value;
// We could remove/separate the remote name at this point?
return from;
}

return "";
}

public string TargetBranch { get; }
public string MergedBranch { get; }
public bool IsMergedPullRequest { get; private set; }
public int? PullRequestNumber { get; private set; }
public SemanticVersion Version { get; }
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
namespace GitVersion.VersionCalculation.BaseVersionCalculators
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using LibGit2Sharp;

/// <summary>
Expand All @@ -21,7 +19,7 @@ public override IEnumerable<BaseVersion> GetVersions(GitVersionContext context)
.SelectMany(c =>
{
SemanticVersion semanticVersion;
if (TryParse(c, context.Configuration, out semanticVersion))
if (TryParse(c, context, out semanticVersion))
{
var shouldIncrement = !context.Configuration.PreventIncrementForMergedBranchVersion;
return new[]
Expand All @@ -34,35 +32,21 @@ public override IEnumerable<BaseVersion> GetVersions(GitVersionContext context)
return baseVersions;
}

static bool TryParse(Commit mergeCommit, EffectiveConfiguration configuration, out SemanticVersion semanticVersion)
static bool TryParse(Commit mergeCommit, GitVersionContext context, out SemanticVersion semanticVersion)
{
semanticVersion = Inner(mergeCommit, configuration);
semanticVersion = Inner(mergeCommit, context);
return semanticVersion != null;
}

static SemanticVersion Inner(Commit mergeCommit, EffectiveConfiguration configuration)
static SemanticVersion Inner(Commit mergeCommit, GitVersionContext context)
{
if (mergeCommit.Parents.Count() < 2)
{
return null;
}

var commitMessage = mergeCommit.Message;
var lastIndexOf = commitMessage.LastIndexOf("into", StringComparison.OrdinalIgnoreCase);
if (lastIndexOf != -1)
commitMessage = commitMessage.Substring(0, lastIndexOf);

//TODO: Make the version prefixes customizable
var possibleVersions = Regex.Matches(commitMessage, @"^.*?(([rR]elease|[hH]otfix|[aA]lpha)-|-v|/|/v|'|Finish )(?<PossibleVersions>(?<!://)\d+\.\d+(\.*\d+)*)")
.Cast<Match>()
.Select(m => m.Groups["PossibleVersions"].Value);

return possibleVersions
.Select(part =>
{
SemanticVersion v;
return SemanticVersion.TryParse(part, configuration.GitTagPrefix, out v) ? v : null;
}).FirstOrDefault(v => v != null);
var mergeMessage = new MergeMessage(mergeCommit.Message, context.FullConfiguration);
return mergeMessage.Version;
}
}
}
Loading