diff --git a/docs/input/docs/reference/modes/continuous-delivery.md b/docs/input/docs/reference/modes/continuous-delivery.md index 3b6aa456ae..ee5c1df4cf 100644 --- a/docs/input/docs/reference/modes/continuous-delivery.md +++ b/docs/input/docs/reference/modes/continuous-delivery.md @@ -24,7 +24,7 @@ Continuous delivery is good when you deploy continuously to an testing system. * 1.1.0-3 * 1.1.0-2 (tag: 1.1.0-2) <-- This is the version which has been deployed on testing * 1.1.0-1 -* 1.1.1-0 +* 1.1.0-0 Tags are not required but optional in this mode to communicate when the release is done as it's an automated process. diff --git a/docs/input/docs/reference/modes/continuous-deployment.md b/docs/input/docs/reference/modes/continuous-deployment.md index 88d7f7887e..b700c3732b 100644 --- a/docs/input/docs/reference/modes/continuous-deployment.md +++ b/docs/input/docs/reference/modes/continuous-deployment.md @@ -21,7 +21,7 @@ to deploy on production. This means that GitVersion will build * 1.2.0 * 1.1.0 (tag: 1.1.0) <-- This is the version which has been deployed on production * 1.1.0 -* 1.1.1 +* 1.1.0 Tags are required in this mode to communicate when the deployment happens on production. diff --git a/docs/input/docs/reference/modes/manual-deployment.md b/docs/input/docs/reference/modes/manual-deployment.md index e76e3e08d0..75e0fb9d74 100644 --- a/docs/input/docs/reference/modes/manual-deployment.md +++ b/docs/input/docs/reference/modes/manual-deployment.md @@ -21,7 +21,7 @@ deployed. For instance: * 1.1.0-2+1 * 1.1.0-1+2 (tag: 1.1.0-1) <-- This is the version which has been deployed on testing * 1.1.0-1+1 -* 1.1.1-1+0 +* 1.1.0-1+0 Tags are required in this mode to communicate when the release is done as it's an external manual process. diff --git a/src/GitVersion.Core.Tests/Extensions/GitToolsTestingExtensions.cs b/src/GitVersion.Core.Tests/Extensions/GitToolsTestingExtensions.cs index cfd5c713d5..7e20ec2aaf 100644 --- a/src/GitVersion.Core.Tests/Extensions/GitToolsTestingExtensions.cs +++ b/src/GitVersion.Core.Tests/Extensions/GitToolsTestingExtensions.cs @@ -138,7 +138,7 @@ public static void AssertFullSemver(this RepositoryFixtureBase fixture, string f /// /// Simulates running on build server /// - public static void InitializeRepo(this RemoteRepositoryFixture fixture) + public static void InitializeRepository(this RemoteRepositoryFixture fixture) { var gitVersionOptions = new GitVersionOptions { diff --git a/src/GitVersion.Core.Tests/IntegrationTests/OtherScenarios.cs b/src/GitVersion.Core.Tests/IntegrationTests/OtherScenarios.cs index dce46a0eb6..de62c1008f 100644 --- a/src/GitVersion.Core.Tests/IntegrationTests/OtherScenarios.cs +++ b/src/GitVersion.Core.Tests/IntegrationTests/OtherScenarios.cs @@ -26,7 +26,7 @@ public void DoNotBlowUpWhenMainAndDevelopPointAtSameCommit() Commands.Fetch(fixture.LocalRepositoryFixture.Repository, fixture.LocalRepositoryFixture.Repository.Network.Remotes.First().Name, [], new(), null); Commands.Checkout(fixture.LocalRepositoryFixture.Repository, fixture.Repository.Head.Tip); fixture.LocalRepositoryFixture.Repository.Branches.Remove(MainBranch); - fixture.InitializeRepo(); + fixture.InitializeRepository(); fixture.AssertFullSemver("1.0.1-1"); } @@ -92,7 +92,7 @@ public void DoNotBlowUpWhenDevelopAndFeatureBranchPointAtSameCommit() Commands.Fetch(fixture.LocalRepositoryFixture.Repository, fixture.LocalRepositoryFixture.Repository.Network.Remotes.First().Name, [], new(), null); Commands.Checkout(fixture.LocalRepositoryFixture.Repository, fixture.Repository.Head.Tip); fixture.LocalRepositoryFixture.Repository.Branches.Remove(MainBranch); - fixture.InitializeRepo(); + fixture.InitializeRepository(); fixture.AssertFullSemver("1.1.0-alpha.1"); } @@ -100,7 +100,7 @@ public void DoNotBlowUpWhenDevelopAndFeatureBranchPointAtSameCommit() [TestCase(false, 1)] [TestCase(true, 5)] [TestCase(false, 5)] - public void HasDirtyFlagWhenUncommittedChangesAreInRepo(bool stageFile, int numberOfFiles) + public void HasDirtyFlagWhenUncommittedChangesAreInRepository(bool stageFile, int numberOfFiles) { using var fixture = new EmptyRepositoryFixture(); fixture.MakeACommit(); @@ -133,7 +133,7 @@ public void NoDirtyFlagInCleanRepository() [TestCase(false, "1.1.0-alpha.2")] [TestCase(true, "1.2.0-alpha.1")] - public void EnsureTrackMergeTargetStrategyWhichWillLookForTaggedMergecommits(bool trackMergeTarget, string expectedVersion) + public void EnsureTrackMergeTargetStrategyWhichWillLookForTaggedMergeCommits(bool trackMergeTarget, string expectedVersion) { // * 9daa6ea 53 minutes ago (HEAD -> develop) // | * 85536f2 55 minutes ago (tag: 1.1.0, main) @@ -1283,7 +1283,7 @@ public void EnsureVersionAfterMainIsMergedBackToDevelopIsCorrectForMainline(bool } [TestCase(false, "2.0.0-alpha.3")] - [TestCase(true, "2.0.0-alpha.3")] + [TestCase(true, "3.0.0-alpha.2")] public void EnsureVersionAfterMainIsMergedBackToDevelopIsCorrectForGitFlow(bool applyTag, string semanticVersion) { var configuration = GitFlowConfigurationBuilder.New.Build(); @@ -1300,7 +1300,7 @@ public void EnsureVersionAfterMainIsMergedBackToDevelopIsCorrectForGitFlow(bool fixture.Checkout("main"); fixture.MakeACommit("C"); - if (applyTag) fixture.ApplyTag("1.0.1"); + if (applyTag) fixture.ApplyTag("2.0.0"); fixture.Checkout("develop"); fixture.MergeNoFF("main"); @@ -1380,7 +1380,8 @@ public void AlternativeSemanticVersionsShouldBeConsidered() } [TestCase(null, "6.0.0-beta.6")] - [TestCase("beta", "6.0.0-beta.21")] + [TestCase("beta", "6.0.0-beta.6")] + [TestCase("gamma", "6.0.0-gamma.21")] public void AlternativeSemanticVersionsShouldBeConsidered(string? labelOnMain, string version) { var configuration = GitFlowConfigurationBuilder.New @@ -1391,14 +1392,16 @@ public void AlternativeSemanticVersionsShouldBeConsidered(string? labelOnMain, s using var fixture = new EmptyRepositoryFixture(); fixture.MakeATaggedCommit("1.0.0"); - fixture.MakeATaggedCommit("4.0.0-beta.14"); fixture.MakeACommit("A"); + fixture.ApplyTag("4.0.0-beta.14"); + fixture.ApplyTag("4.0.0-gamma.14"); + fixture.MakeACommit("B"); fixture.MakeATaggedCommit("6.0.0-alpha.1"); fixture.MakeATaggedCommit("6.0.0-alpha.2"); fixture.MakeATaggedCommit("6.0.0-alpha.3"); - fixture.MakeACommit("B"); - fixture.MakeATaggedCommit("6.0.0-beta.5"); fixture.MakeACommit("C"); + fixture.MakeATaggedCommit("6.0.0-beta.5"); + fixture.MakeACommit("D"); fixture.AssertFullSemver(version, configuration); } diff --git a/src/GitVersion.Core.Tests/IntegrationTests/PerformanceScenarios.cs b/src/GitVersion.Core.Tests/IntegrationTests/PerformanceScenarios.cs index b79e2644d9..aad4244caf 100644 --- a/src/GitVersion.Core.Tests/IntegrationTests/PerformanceScenarios.cs +++ b/src/GitVersion.Core.Tests/IntegrationTests/PerformanceScenarios.cs @@ -12,10 +12,13 @@ public void RepositoryWithALotOfTags() using var fixture = new EmptyRepositoryFixture(); - const int maxCommits = 500; - for (int i = 0; i < maxCommits; i++) + Random random = new(4711); + SemanticVersion semanticVersion = SemanticVersion.Empty; + for (int i = 0; i < 500; i++) { - fixture.MakeATaggedCommit($"1.0.{i}"); + VersionField versionField = (VersionField)random.Next(1, 4); + semanticVersion = semanticVersion.Increment(versionField, string.Empty, forceIncrement: true); + fixture.MakeATaggedCommit(semanticVersion.ToString("j")); } fixture.BranchTo("feature"); @@ -23,9 +26,9 @@ public void RepositoryWithALotOfTags() var sw = Stopwatch.StartNew(); - fixture.AssertFullSemver($"1.0.{maxCommits}-feature.1+1", configuration); + fixture.AssertFullSemver("170.3.3-feature.1+1", configuration); sw.Stop(); - sw.ElapsedMilliseconds.ShouldBeLessThan(5000); + sw.ElapsedMilliseconds.ShouldBeLessThan(2500); } } diff --git a/src/GitVersion.Core/VersionCalculation/IncrementStrategyFinder.cs b/src/GitVersion.Core/VersionCalculation/IncrementStrategyFinder.cs index 41f75a8b34..d0f69f4bbb 100644 --- a/src/GitVersion.Core/VersionCalculation/IncrementStrategyFinder.cs +++ b/src/GitVersion.Core/VersionCalculation/IncrementStrategyFinder.cs @@ -106,7 +106,7 @@ private IReadOnlyCollection GetCommitHistory(string? tagPrefix, Semanti .ToHashSet() ); - var intermediateCommits = GetIntermediateCommits(baseVersionSource, currentCommit, ignore).ToArray(); + var intermediateCommits = this.repositoryStore.GetCommitLog(baseVersionSource, currentCommit, ignore); var commitLog = intermediateCommits.ToDictionary(element => element.Id.Sha); foreach (var intermediateCommit in intermediateCommits.Reverse()) @@ -197,7 +197,6 @@ public IEnumerable GetMergedCommits(ICommit mergeCommit, int index, IIg ICommit findMergeBase = this.repositoryStore.FindMergeBase(baseCommit, mergedCommit) ?? throw new InvalidOperationException("Cannot find the base commit of merged branch."); - return GetIntermediateCommits(findMergeBase, mergedCommit, ignore); } diff --git a/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/TaggedCommitVersionStrategy.cs b/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/TaggedCommitVersionStrategy.cs index 73aa3104f2..4e08eef9c8 100644 --- a/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/TaggedCommitVersionStrategy.cs +++ b/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/TaggedCommitVersionStrategy.cs @@ -1,6 +1,7 @@ using GitVersion.Configuration; using GitVersion.Core; using GitVersion.Extensions; +using GitVersion.Logging; namespace GitVersion.VersionCalculation; @@ -10,11 +11,13 @@ namespace GitVersion.VersionCalculation; /// Increments if the tag is not the current commit. /// internal sealed class TaggedCommitVersionStrategy( + ILog log, Lazy contextLazy, ITaggedSemanticVersionService taggedSemanticVersionService, IIncrementStrategyFinder incrementStrategyFinder) : IVersionStrategy { + private readonly ILog log = log.NotNull(); private readonly ITaggedSemanticVersionService taggedSemanticVersionService = taggedSemanticVersionService.NotNull(); private readonly Lazy contextLazy = contextLazy.NotNull(); private readonly IIncrementStrategyFinder incrementStrategyFinder = incrementStrategyFinder.NotNull(); @@ -41,16 +44,30 @@ private IEnumerable GetBaseVersionsInternal(EffectiveBranchConfigur var label = configuration.Value.GetBranchSpecificLabel(Context.CurrentBranch.Name, null); + var semanticVersionTreshold = SemanticVersion.Empty; List alternativeSemanticVersionsWithTag = []; - foreach (var semanticVersionWithTag in taggedSemanticVersions) + foreach (var semanticVersion in taggedSemanticVersions) { - if (!semanticVersionWithTag.Value.IsMatchForBranchSpecificLabel(label)) + if (!semanticVersion.Value.IsMatchForBranchSpecificLabel(label)) { - alternativeSemanticVersionsWithTag.Add(semanticVersionWithTag); + alternativeSemanticVersionsWithTag.Add(semanticVersion); continue; } - var baseVersionSource = semanticVersionWithTag.Tag.Commit; + var alternativeSemanticVersionMax = alternativeSemanticVersionsWithTag.Max()?.Value; + var highestPossibleSemanticVersion = semanticVersion.Value.Increment( + VersionField.Major, null, forceIncrement: true, alternativeSemanticVersionMax + ); + if (highestPossibleSemanticVersion.IsLessThan(semanticVersionTreshold, includePreRelease: false)) + { + this.log.Info( + $"The tag '{semanticVersion.Value}' is skipped because it provides a lower base version than other tags." + ); + alternativeSemanticVersionsWithTag.Clear(); + continue; + } + + var baseVersionSource = semanticVersion.Tag.Commit; var increment = incrementStrategyFinder.DetermineIncrementedField( currentCommit: Context.CurrentCommit, baseVersionSource: baseVersionSource, @@ -58,16 +75,17 @@ private IEnumerable GetBaseVersionsInternal(EffectiveBranchConfigur configuration: configuration.Value, label: label ); + semanticVersionTreshold = semanticVersion.Value.Increment(increment, null, forceIncrement: true); yield return new BaseVersion( - $"Git tag '{semanticVersionWithTag.Tag.Name.Friendly}'", semanticVersionWithTag.Value, baseVersionSource) + $"Git tag '{semanticVersion.Tag.Name.Friendly}'", semanticVersion.Value, baseVersionSource) { Operator = new BaseVersionOperator { Increment = increment, ForceIncrement = false, Label = label, - AlternativeSemanticVersion = alternativeSemanticVersionsWithTag.Max()?.Value + AlternativeSemanticVersion = alternativeSemanticVersionMax } }; alternativeSemanticVersionsWithTag.Clear();