diff --git a/BREAKING_CHANGES.md b/BREAKING_CHANGES.md index 7ac3dde2dc..0b3037c4db 100644 --- a/BREAKING_CHANGES.md +++ b/BREAKING_CHANGES.md @@ -31,7 +31,7 @@ * The `useBranchName` magic string has been removed. Instead use `{BranchName}` for `label`. * The `BranchPrefixToTrim` configuration property has been removed. `RegularExpression` is now used to capture named groups instead. * Default `RegularExpression` for feature branches is changed from `^features?[/-]` to `^features?[/-](?.+)` to support using `{BranchName}` out-of-the-box - * Default `RegularExpression` for unknown branches is changed from `.*` to `(?.*)` to support using `{BranchName}` out-of-the-box + * Default `RegularExpression` for unknown branches is changed from `.*` to `(?.+)` to support using `{BranchName}` out-of-the-box * The `Mainline` mode and the related implementation has been removed completely. The new `TrunkBased` version strategy should be used instead. * The branch related property `is-mainline` in the configuration system has been renamed to `is-main-branch` * The versioning mode has been renamed to deployment mode and consists of following values: diff --git a/src/GitVersion.Configuration/SupportedWorkflows/GitFlow/v1.yml b/src/GitVersion.Configuration/SupportedWorkflows/GitFlow/v1.yml index b659a13f3b..c3a60438a3 100644 --- a/src/GitVersion.Configuration/SupportedWorkflows/GitFlow/v1.yml +++ b/src/GitVersion.Configuration/SupportedWorkflows/GitFlow/v1.yml @@ -1,6 +1,7 @@ assembly-versioning-scheme: MajorMinorPatch assembly-file-versioning-scheme: MajorMinorPatch tag-prefix: '[vV]?' +version-in-branch-pattern: (?[vV]?\d+(\.\d+)?(\.\d+)?).* major-version-bump-message: '\+semver:\s?(breaking|major)' minor-version-bump-message: '\+semver:\s?(feature|minor)' patch-version-bump-message: '\+semver:\s?(fix|patch)' @@ -10,10 +11,14 @@ commit-date-format: yyyy-MM-dd merge-message-formats: {} update-build-number: true semantic-version-format: Strict -strategies: [ConfigNext, MergeMessage, TaggedCommit, TrackReleaseBranches, VersionInBranchName] +strategies: +- ConfiguredNextVersion +- MergeMessage +- TaggedCommit +- TrackReleaseBranches +- VersionInBranchName branches: develop: - mode: ContinuousDeployment label: alpha increment: Minor prevent-increment-of-merged-branch-version: false @@ -38,6 +43,7 @@ branches: is-main-branch: true pre-release-weight: 55000 release: + mode: ManualDeployment label: beta increment: None prevent-increment-of-merged-branch-version: true @@ -53,7 +59,7 @@ branches: is-main-branch: false pre-release-weight: 30000 feature: - mode: ContinuousDelivery + mode: ManualDeployment label: '{BranchName}' increment: Inherit regex: ^features?[/-](?.+) @@ -80,7 +86,7 @@ branches: - hotfix pre-release-weight: 30000 hotfix: - mode: ContinuousDelivery + mode: ManualDeployment label: beta increment: Inherit regex: ^hotfix(es)?[/-] @@ -89,6 +95,7 @@ branches: - main - support - hotfix + is-release-branch: true pre-release-weight: 30000 support: label: '' @@ -103,10 +110,10 @@ branches: is-main-branch: true pre-release-weight: 55000 unknown: - mode: ContinuousDelivery + mode: ManualDeployment label: '{BranchName}' increment: Inherit - regex: (?.*) + regex: (?.+) source-branches: - main - develop diff --git a/src/GitVersion.Configuration/SupportedWorkflows/GitHubFlow/v1.yml b/src/GitVersion.Configuration/SupportedWorkflows/GitHubFlow/v1.yml index 3556395487..588dc246c1 100644 --- a/src/GitVersion.Configuration/SupportedWorkflows/GitHubFlow/v1.yml +++ b/src/GitVersion.Configuration/SupportedWorkflows/GitHubFlow/v1.yml @@ -1,6 +1,7 @@ assembly-versioning-scheme: MajorMinorPatch assembly-file-versioning-scheme: MajorMinorPatch tag-prefix: '[vV]?' +version-in-branch-pattern: (?[vV]?\d+(\.\d+)?(\.\d+)?).* major-version-bump-message: '\+semver:\s?(breaking|major)' minor-version-bump-message: '\+semver:\s?(feature|minor)' patch-version-bump-message: '\+semver:\s?(fix|patch)' @@ -10,7 +11,12 @@ commit-date-format: yyyy-MM-dd merge-message-formats: {} update-build-number: true semantic-version-format: Strict -strategies: [ConfigNext, MergeMessage, TaggedCommit, TrackReleaseBranches, VersionInBranchName] +strategies: +- ConfiguredNextVersion +- MergeMessage +- TaggedCommit +- TrackReleaseBranches +- VersionInBranchName branches: main: label: '' @@ -25,6 +31,7 @@ branches: is-main-branch: true pre-release-weight: 55000 release: + mode: ManualDeployment label: beta increment: None prevent-increment-of-merged-branch-version: true @@ -38,7 +45,7 @@ branches: is-main-branch: false pre-release-weight: 30000 feature: - mode: ContinuousDelivery + mode: ManualDeployment label: '{BranchName}' increment: Inherit regex: ^features?[/-](?.+) @@ -59,10 +66,10 @@ branches: - feature pre-release-weight: 30000 unknown: - mode: ContinuousDelivery + mode: ManualDeployment label: '{BranchName}' increment: Inherit - regex: (?.*) + regex: (?.+) source-branches: - main - release diff --git a/src/GitVersion.Configuration/SupportedWorkflows/TrunkBased/v1.yml b/src/GitVersion.Configuration/SupportedWorkflows/TrunkBased/v1.yml index 3289a1b7b9..eec0ab5973 100644 --- a/src/GitVersion.Configuration/SupportedWorkflows/TrunkBased/v1.yml +++ b/src/GitVersion.Configuration/SupportedWorkflows/TrunkBased/v1.yml @@ -1,6 +1,7 @@ assembly-versioning-scheme: MajorMinorPatch assembly-file-versioning-scheme: MajorMinorPatch tag-prefix: '[vV]?' +version-in-branch-pattern: (?[vV]?\d+(\.\d+)?(\.\d+)?).* major-version-bump-message: '\+semver:\s?(breaking|major)' minor-version-bump-message: '\+semver:\s?(feature|minor)' patch-version-bump-message: '\+semver:\s?(fix|patch)' @@ -10,7 +11,9 @@ commit-date-format: yyyy-MM-dd merge-message-formats: {} update-build-number: true semantic-version-format: Strict -strategies: [TrunkBased, ConfiguredNextVersion] +strategies: +- TrunkBased +- ConfiguredNextVersion branches: main: mode: ContinuousDeployment @@ -48,7 +51,7 @@ branches: unknown: mode: ManualDeployment increment: Inherit - regex: (?.*) + regex: (?.+) source-branches: - main - release diff --git a/src/GitVersion.Core.Tests/IntegrationTests/OtherBranchScenarios.cs b/src/GitVersion.Core.Tests/IntegrationTests/OtherBranchScenarios.cs index 1fd1446dd7..ba1130977f 100644 --- a/src/GitVersion.Core.Tests/IntegrationTests/OtherBranchScenarios.cs +++ b/src/GitVersion.Core.Tests/IntegrationTests/OtherBranchScenarios.cs @@ -1,5 +1,6 @@ using GitVersion.Configuration; using GitVersion.Core.Tests.Helpers; +using GitVersion.VersionCalculation; using LibGit2Sharp; namespace GitVersion.Core.Tests.IntegrationTests; @@ -7,6 +8,73 @@ namespace GitVersion.Core.Tests.IntegrationTests; [TestFixture] public class OtherBranchScenarios : TestBase { + [TestCase("", "NotAVersion", "2.0.0-1", "1.9.0", "1.9.0", "1.9.1-1")] + [TestCase("", "1.5.0", "1.5.0", "1.9.0", "1.9.0", "1.9.1-1")] + [TestCase("prefix", "1.5.0", "2.0.0-1", "1.9.0", "2.0.0-1", "2.0.0-2")] + [TestCase("prefix", "1.5.0", "2.0.0-1", "prefix1.9.0", "1.9.0", "1.9.1-1")] + [TestCase("prefix", "prefix1.5.0", "1.5.0", "1.9.0", "1.5.0", "1.5.1-1")] + public void CanUseCommitMessagesToBumpVersion_TagsTakePriorityOnlyIfVersions( + string tagPrefix, + string firstTag, + string expectedAfterFirstTag, + string secondTag, + string expectedAfterSecondTag, + string expectedVersionAfterNewCommit) + { + var configuration = GitFlowConfigurationBuilder.New + .WithTagPrefix(tagPrefix) + .Build(); + + using var fixture = new EmptyRepositoryFixture(); + var repo = fixture.Repository; + + repo.MakeATaggedCommit($"{tagPrefix}1.0.0"); + repo.MakeACommit("+semver:major"); + fixture.AssertFullSemver("2.0.0-1", configuration); + + repo.ApplyTag(firstTag); + fixture.AssertFullSemver(expectedAfterFirstTag, configuration); + + repo.ApplyTag(secondTag); + fixture.AssertFullSemver(expectedAfterSecondTag, configuration); + + repo.MakeACommit(); + fixture.AssertFullSemver(expectedVersionAfterNewCommit, configuration); + } + + [TestCase("", null, "1.9.0-1", "2.0.0-1+1", ExpectedResult = "1.9.0-1")] + [TestCase("", "", "1.9.0-1", "2.0.0-1+1", ExpectedResult = "1.9.0-1")] + [TestCase("", "foo", "1.9.0-1", "2.0.0-foo.1+1", ExpectedResult = "2.0.0-foo.1+1")] + [TestCase("", "bar", "1.9.0-1", "2.0.0-bar.1+1", ExpectedResult = "2.0.0-bar.1+1")] + [TestCase("prefix", null, "1.9.0-1", "2.0.0-1+1", ExpectedResult = "2.0.0-1+1")] + [TestCase("prefix", "", "1.9.0-1", "2.0.0-1+1", ExpectedResult = "2.0.0-1+1")] + [TestCase("prefix", "foo", "1.9.0-1", "2.0.0-foo.1+1", ExpectedResult = "2.0.0-foo.1+1")] + [TestCase("prefix", "bar", "1.9.0-1", "2.0.0-bar.1+1", ExpectedResult = "2.0.0-bar.1+1")] + + [TestCase("", null, "2.1.0-1", "2.0.0-1+1", ExpectedResult = "2.1.0-1")] + [TestCase("", "", "2.1.0-1", "2.0.0-1+1", ExpectedResult = "2.1.0-1")] + [TestCase("", "foo", "2.1.0-1", "2.0.0-foo.1+1", ExpectedResult = "2.1.0-foo.1+1")] + [TestCase("", "bar", "2.1.0-1", "2.0.0-bar.1+1", ExpectedResult = "2.1.0-bar.1+1")] + [TestCase("prefix", null, "2.1.0-1", "2.0.0-1+1", ExpectedResult = "2.0.0-1+1")] + [TestCase("prefix", "", "2.1.0-1", "2.0.0-1+1", ExpectedResult = "2.0.0-1+1")] + [TestCase("prefix", "foo", "2.1.0-1", "2.0.0-foo.1+1", ExpectedResult = "2.0.0-foo.1+1")] + [TestCase("prefix", "bar", "2.1.0-1", "2.0.0-bar.1+1", ExpectedResult = "2.0.0-bar.1+1")] + public string WhenTaggingACommitAsPreRelease(string tagPrefix, string? label, string tag, string expectedVersion) + { + var configuration = GitFlowConfigurationBuilder.New.WithLabel(null).WithTagPrefix(tagPrefix) + .WithBranch("main", _ => _.WithLabel(label).WithDeploymentMode(DeploymentMode.ManualDeployment)) + .Build(); + + using EmptyRepositoryFixture fixture = new("main"); + + fixture.MakeATaggedCommit($"{tagPrefix}1.0.0"); + fixture.MakeACommit("+semver:major"); + fixture.AssertFullSemver(expectedVersion, configuration); + fixture.ApplyTag(tag); + + return fixture!.GetVersion(configuration).FullSemVer; + } + /// /// https://github.com/GitTools/GitVersion/issues/2340 /// @@ -34,7 +102,7 @@ public void ShouldOnlyConsiderTagsMatchingOfCurrentBranch() public void CanTakeVersionFromReleaseBranch() { var configuration = GitFlowConfigurationBuilder.New - .WithBranch("release", _ => _.WithLabel("{BranchName}").WithRegularExpression("(?.*)")) + .WithBranch("release", _ => _.WithLabel("{BranchName}").WithRegularExpression("(?.+)")) .Build(); using var fixture = new EmptyRepositoryFixture(); @@ -52,7 +120,7 @@ public void CanTakeVersionFromReleaseBranch() public void CanTakeVersionFromHotfixBranch() { var configuration = GitFlowConfigurationBuilder.New - .WithBranch("hotfix", _ => _.WithLabel("{BranchName}").WithRegularExpression("(?.*)")) + .WithBranch("hotfix", _ => _.WithLabel("{BranchName}").WithRegularExpression("(?.+)")) .Build(); using var fixture = new EmptyRepositoryFixture(); @@ -112,7 +180,7 @@ public void LabelIsBranchNameForBranchesWithoutPrefixedBranchName(string label, var configuration = GitFlowConfigurationBuilder.New .WithBranch("other", builder => builder .WithIncrement(IncrementStrategy.Patch) - .WithRegularExpression("(?.*)") + .WithRegularExpression("(?.+)") .WithSourceBranches() .WithLabel(label)) .Build(); diff --git a/src/GitVersion.Core/Core/ITaggedSemanticVersionRepository.cs b/src/GitVersion.Core/Core/ITaggedSemanticVersionRepository.cs index f23044fb6f..ecb4b063c1 100644 --- a/src/GitVersion.Core/Core/ITaggedSemanticVersionRepository.cs +++ b/src/GitVersion.Core/Core/ITaggedSemanticVersionRepository.cs @@ -16,7 +16,7 @@ ILookup GetTaggedSemanticVersionsOfMergeTarget( string? tagPrefix, SemanticVersionFormat format); - ILookup GetTaggedSemanticVersionsOfMainlineBranches( + ILookup GetTaggedSemanticVersionsOfMainBranches( string? tagPrefix, SemanticVersionFormat format, params IBranch[] excludeBranches); @@ -25,4 +25,6 @@ ILookup GetTaggedSemanticVersionsOfReleaseBranc string? tagPrefix, SemanticVersionFormat format, params IBranch[] excludeBranches); + + ILookup GetTaggedSemanticVersions(string? tagPrefix, SemanticVersionFormat format); } diff --git a/src/GitVersion.Core/Core/TaggedSemanticVersionRepository.cs b/src/GitVersion.Core/Core/TaggedSemanticVersionRepository.cs index 5f24743346..0a6c377d10 100644 --- a/src/GitVersion.Core/Core/TaggedSemanticVersionRepository.cs +++ b/src/GitVersion.Core/Core/TaggedSemanticVersionRepository.cs @@ -87,7 +87,7 @@ public ILookup GetAllTaggedSemanticVersions(IBr if (!configuration.IsMainBranch && !configuration.IsReleaseBranch) { - var semanticVersionsOfMainlineBranches = GetTaggedSemanticVersionsOfMainlineBranches( + var semanticVersionsOfMainlineBranches = GetTaggedSemanticVersionsOfMainBranches( tagPrefix: configuration.TagPrefix, format: configuration.SemanticVersionFormat, excludeBranches: branch @@ -188,7 +188,7 @@ public ILookup GetTaggedSemanticVersionsOfMerge return result; } - public ILookup GetTaggedSemanticVersionsOfMainlineBranches( + public ILookup GetTaggedSemanticVersionsOfMainBranches( string? tagPrefix, SemanticVersionFormat format, params IBranch[] excludeBranches) { tagPrefix ??= string.Empty; @@ -236,7 +236,7 @@ IEnumerable GetElements() return GetElements().Distinct().ToLookup(element => element.Tag.Commit, element => element); } - private ILookup GetTaggedSemanticVersions(string? tagPrefix, SemanticVersionFormat format) + public ILookup GetTaggedSemanticVersions(string? tagPrefix, SemanticVersionFormat format) { tagPrefix ??= string.Empty; diff --git a/src/GitVersion.Core/PublicAPI.Unshipped.txt b/src/GitVersion.Core/PublicAPI.Unshipped.txt index a0a180be0b..1d9b77e537 100644 --- a/src/GitVersion.Core/PublicAPI.Unshipped.txt +++ b/src/GitVersion.Core/PublicAPI.Unshipped.txt @@ -693,7 +693,7 @@ GitVersion.VersionCalculation.DeploymentMode.ManualDeployment = 0 -> GitVersion. GitVersion.VersionCalculation.IEffectiveBranchConfigurationFinder GitVersion.VersionCalculation.IEffectiveBranchConfigurationFinder.GetConfigurations(GitVersion.IBranch! branch, GitVersion.Configuration.IGitVersionConfiguration! configuration) -> System.Collections.Generic.IEnumerable! GitVersion.VersionCalculation.IIncrementStrategyFinder -GitVersion.VersionCalculation.IIncrementStrategyFinder.DetermineIncrementedField(GitVersion.ICommit! currentCommit, GitVersion.VersionCalculation.BaseVersion! baseVersion, GitVersion.Configuration.EffectiveConfiguration! configuration) -> GitVersion.VersionField +GitVersion.VersionCalculation.IIncrementStrategyFinder.DetermineIncrementedField(GitVersion.ICommit! currentCommit, GitVersion.VersionCalculation.BaseVersion! baseVersion, GitVersion.Configuration.EffectiveConfiguration! configuration, string? label) -> GitVersion.VersionField GitVersion.VersionCalculation.IIncrementStrategyFinder.GetIncrementForcedByCommit(GitVersion.ICommit! commit, GitVersion.Configuration.EffectiveConfiguration! configuration) -> GitVersion.VersionField GitVersion.VersionCalculation.IIncrementStrategyFinder.GetIncrementForCommits(string? majorVersionBumpMessage, string? minorVersionBumpMessage, string? patchVersionBumpMessage, string? noBumpMessage, GitVersion.ICommit![]! commits) -> GitVersion.VersionField? GitVersion.VersionCalculation.IIncrementStrategyFinder.GetMergedCommits(GitVersion.ICommit! mergeCommit, int index) -> System.Collections.Generic.IEnumerable! diff --git a/src/GitVersion.Core/VersionCalculation/Abstractions/IIncrementStrategyFinder.cs b/src/GitVersion.Core/VersionCalculation/Abstractions/IIncrementStrategyFinder.cs index 3ae1f61f25..fb8817767f 100644 --- a/src/GitVersion.Core/VersionCalculation/Abstractions/IIncrementStrategyFinder.cs +++ b/src/GitVersion.Core/VersionCalculation/Abstractions/IIncrementStrategyFinder.cs @@ -4,7 +4,8 @@ namespace GitVersion.VersionCalculation; public interface IIncrementStrategyFinder { - VersionField DetermineIncrementedField(ICommit currentCommit, BaseVersion baseVersion, EffectiveConfiguration configuration); + VersionField DetermineIncrementedField( + ICommit currentCommit, BaseVersion baseVersion, EffectiveConfiguration configuration, string? label); VersionField? GetIncrementForCommits( string? majorVersionBumpMessage, string? minorVersionBumpMessage, string? patchVersionBumpMessage, string? noBumpMessage, diff --git a/src/GitVersion.Core/VersionCalculation/IncrementStrategyFinder.cs b/src/GitVersion.Core/VersionCalculation/IncrementStrategyFinder.cs index 6121118ead..e3224c1785 100644 --- a/src/GitVersion.Core/VersionCalculation/IncrementStrategyFinder.cs +++ b/src/GitVersion.Core/VersionCalculation/IncrementStrategyFinder.cs @@ -1,6 +1,7 @@ using System.Collections.Concurrent; using System.Text.RegularExpressions; using GitVersion.Configuration; +using GitVersion.Core; using GitVersion.Extensions; namespace GitVersion.VersionCalculation; @@ -16,7 +17,6 @@ internal class IncrementStrategyFinder : IIncrementStrategyFinder private readonly Dictionary commitIncrementCache = []; private readonly Dictionary> headCommitsMapCache = []; private readonly Dictionary headCommitsCache = []; - private readonly Lazy> tagsShaCache; private static readonly Regex DefaultMajorPatternRegex = new(DefaultMajorPattern, RegexOptions.Compiled | RegexOptions.IgnoreCase); private static readonly Regex DefaultMinorPatternRegex = new(DefaultMinorPattern, RegexOptions.Compiled | RegexOptions.IgnoreCase); @@ -24,19 +24,23 @@ internal class IncrementStrategyFinder : IIncrementStrategyFinder private static readonly Regex DefaultNoBumpPatternRegex = new(DefaultNoBumpPattern, RegexOptions.Compiled | RegexOptions.IgnoreCase); private readonly IGitRepository repository; + private readonly ITaggedSemanticVersionRepository taggedSemanticVersionRepository; - public IncrementStrategyFinder(IGitRepository repository) + public IncrementStrategyFinder(IGitRepository repository, ITaggedSemanticVersionRepository taggedSemanticVersionRepository) { this.repository = repository.NotNull(); - this.tagsShaCache = new(ReadRepositoryTagsSha); + this.repository = repository.NotNull(); + this.taggedSemanticVersionRepository = taggedSemanticVersionRepository; } - public VersionField DetermineIncrementedField(ICommit currentCommit, BaseVersion baseVersion, EffectiveConfiguration configuration) + public VersionField DetermineIncrementedField( + ICommit currentCommit, BaseVersion baseVersion, EffectiveConfiguration configuration, string? label) { baseVersion.NotNull(); configuration.NotNull(); - var commitMessageIncrement = FindCommitMessageIncrement(configuration, baseVersion.BaseVersionSource, currentCommit); + var commitMessageIncrement = FindCommitMessageIncrement( + configuration, baseVersion.BaseVersionSource, currentCommit, label); var defaultIncrement = configuration.Increment.ToVersionField(); @@ -76,18 +80,25 @@ public VersionField DetermineIncrementedField(ICommit currentCommit, BaseVersion : null; } - private VersionField? FindCommitMessageIncrement(EffectiveConfiguration configuration, ICommit? baseCommit, ICommit? currentCommit) + private VersionField? FindCommitMessageIncrement( + EffectiveConfiguration configuration, ICommit? baseCommit, ICommit? currentCommit, string? label) { if (configuration.CommitMessageIncrementing == CommitMessageIncrementMode.Disabled) { return null; } + //get tags with valid version - depends on configuration (see #3757) + var targetShas = new Lazy>(() => + this.taggedSemanticVersionRepository.GetTaggedSemanticVersions(configuration.TagPrefix, configuration.SemanticVersionFormat) + .SelectMany(_ => _).Where(_ => _.Value.IsMatchForBranchSpecificLabel(label)).Select(_ => _.Tag.TargetSha).ToHashSet() + ); + var commits = GetIntermediateCommits(baseCommit, currentCommit); // consider commit messages since latest tag only (see #3071) commits = commits .Reverse() - .TakeWhile(x => !this.tagsShaCache.Value.Contains(x.Sha)) + .TakeWhile(x => !targetShas.Value.Contains(x.Sha)) .Reverse(); if (configuration.CommitMessageIncrementing == CommitMessageIncrementMode.MergeMessageOnly) @@ -104,8 +115,6 @@ public VersionField DetermineIncrementedField(ICommit currentCommit, BaseVersion ); } - private IReadOnlySet ReadRepositoryTagsSha() => repository.Tags.Select(t => t.TargetSha).ToHashSet(); - private static Regex TryGetRegexOrDefault(string? messageRegex, Regex defaultRegex) => messageRegex == null ? defaultRegex diff --git a/src/GitVersion.Core/VersionCalculation/VersionCalculators/NextVersionCalculator.cs b/src/GitVersion.Core/VersionCalculation/VersionCalculators/NextVersionCalculator.cs index a3fe2c45dd..5c20357243 100644 --- a/src/GitVersion.Core/VersionCalculation/VersionCalculators/NextVersionCalculator.cs +++ b/src/GitVersion.Core/VersionCalculation/VersionCalculators/NextVersionCalculator.cs @@ -219,7 +219,8 @@ private SemanticVersion GetIncrementedVersion(EffectiveBranchConfiguration confi var incrementStrategy = incrementStrategyFinder.DetermineIncrementedField( currentCommit: Context.CurrentCommit, baseVersion: baseVersion, - configuration: configuration.Value + configuration: configuration.Value, + label: label ); return baseVersion.GetSemanticVersion().Increment(incrementStrategy, label); }