public void GitFlowPullRequestBranch()
    {
        using (var fixture = new EmptyRepositoryFixture())
        {
            fixture.SequenceDiagram.Participant("master");
            fixture.SequenceDiagram.Participant("develop");

            // GitFlow setup
            fixture.Repository.MakeACommit();
            fixture.ApplyTag("1.2.0");
            fixture.BranchTo("develop");

            // Branch to develop
            fixture.MakeACommit();
            fixture.AssertFullSemver("1.3.0-alpha.1");

            // Open Pull Request
            fixture.BranchTo("pull/2/merge", "pr");
            fixture.SequenceDiagram.Activate("pull/2/merge");
            fixture.AssertFullSemver("1.3.0-PullRequest0002.1");
            fixture.MakeACommit();
            fixture.AssertFullSemver("1.3.0-PullRequest0002.2");

            // Merge into develop
            fixture.Checkout("develop");
            fixture.MergeNoFF("pull/2/merge");
            fixture.SequenceDiagram.Destroy("pull/2/merge");
            fixture.SequenceDiagram.NoteOver("Feature branches/pr's should\r\n" +
                             "be deleted once merged", "pull/2/merge");
            fixture.AssertFullSemver("1.3.0-alpha.3");
            Console.WriteLine(fixture.SequenceDiagram.GetDiagram());
        }
    }
    public void GitFlowPullRequestBranch()
    {
        using (var fixture = new EmptyRepositoryFixture(new Config()))
        {
            fixture.Participant("master");
            fixture.Participant("develop");

            // GitFlow setup
            fixture.Repository.MakeACommit();
            fixture.ApplyTag("1.2.0");
            fixture.BranchTo("develop");

            // Branch to develop
            fixture.MakeACommit();
            fixture.AssertFullSemver("1.3.0-unstable.1");

            // Open Pull Request
            fixture.BranchTo("pull/2/merge", "pr");
            fixture.Activate("pull/2/merge");
            fixture.AssertFullSemver("1.3.0-PullRequest.2+1");
            fixture.MakeACommit();
            fixture.AssertFullSemver("1.3.0-PullRequest.2+2");

            // Merge into develop
            fixture.Checkout("develop");
            fixture.MergeNoFF("pull/2/merge");
            fixture.Destroy("pull/2/merge");
            fixture.NoteOver("Feature branches/pr's should\r\n" +
                             "be deleted once merged", "pull/2/merge");
            fixture.AssertFullSemver("1.3.0-unstable.3");
        }
    }
    public void GitFlowFeatureBranch()
    {
        using (var fixture = new EmptyRepositoryFixture())
        {
            fixture.SequenceDiagram.Participant("master");
            fixture.SequenceDiagram.Participant("develop");

            // GitFlow setup
            fixture.Repository.MakeACommit();
            fixture.ApplyTag("1.2.0");
            fixture.BranchTo("develop");

            // Branch to develop
            fixture.MakeACommit();
            fixture.AssertFullSemver("1.3.0-unstable.1");

            // Open Pull Request
            fixture.BranchTo("feature/myfeature", "feature");
            fixture.SequenceDiagram.Activate("feature/myfeature");
            fixture.AssertFullSemver("1.3.0-myfeature.1+1");
            fixture.MakeACommit();
            fixture.AssertFullSemver("1.3.0-myfeature.1+2");

            // Merge into develop
            fixture.Checkout("develop");
            fixture.MergeNoFF("feature/myfeature");
            fixture.SequenceDiagram.Destroy("feature/myfeature");
            fixture.SequenceDiagram.NoteOver("Feature branches should\r\n" +
                             "be deleted once merged", "feature/myfeature");
            fixture.AssertFullSemver("1.3.0-unstable.3");
        }
    }
    public void GitFlowHotfixBranch()
    {
        using (var fixture = new EmptyRepositoryFixture())
        {
            fixture.SequenceDiagram.Participant("develop");
            fixture.SequenceDiagram.Participant("master");

            fixture.Repository.MakeACommit();
            fixture.ApplyTag("1.2.0");

            // Create hotfix branch
            fixture.Checkout("master");
            fixture.BranchTo("hotfix/1.2.1", "hotfix");
            fixture.SequenceDiagram.Activate("hotfix/1.2.1");
            fixture.MakeACommit();
            fixture.MakeACommit();
            fixture.AssertFullSemver("1.2.1-beta.1+2");

            // Apply beta.1 tag should be exact tag
            fixture.ApplyTag("1.2.1-beta.1");
            fixture.AssertFullSemver("1.2.1-beta.1");
            fixture.Checkout("master");
            fixture.MergeNoFF("hotfix/1.2.1");
            fixture.SequenceDiagram.Destroy("hotfix/1.2.1");
            fixture.SequenceDiagram.NoteOver("Hotfix branches are deleted once merged", "hotfix/1.2.1");
            fixture.ApplyTag("1.2.1");
        }
    }
Beispiel #5
0
        public void NormalisationOfTag()
        {
            using (var fixture = new EmptyRepositoryFixture(new Config()))
            {
                fixture.Repository.MakeACommit();

                fixture.Repository.Checkout(fixture.Repository.CreateBranch("feature/foo"));
                fixture.Repository.MakeACommit();

                fixture.BranchTo("release/2.0.0");
                fixture.MakeACommit();
                fixture.MakeATaggedCommit("2.0.0-rc.1");
                fixture.Checkout("master");
                fixture.MergeNoFF("release/2.0.0");
                fixture.Repository.Branches.Remove(fixture.Repository.FindBranch("release/2.0.0"));
                var remoteTagSha = fixture.Repository.Tags["2.0.0-rc.1"].Target.Sha;
                
                using (var localFixture = fixture.CloneRepository())
                {
                    localFixture.Checkout(remoteTagSha);
                    GitHelper.NormalizeGitDirectory(localFixture.RepositoryPath, new Authentication(), noFetch: false, currentBranch: string.Empty);

                    localFixture.AssertFullSemver("2.0.0-rc.1");
                }
            }
        }
        public void NormalisationOfTag()
        {
            using (var fixture = new EmptyRepositoryFixture())
            {
                fixture.Repository.MakeACommit();

                fixture.Repository.Checkout(fixture.Repository.CreateBranch("feature/foo"));
                fixture.Repository.MakeACommit();

                fixture.BranchTo("release/2.0.0");
                fixture.MakeACommit();
                fixture.MakeATaggedCommit("2.0.0-rc.1");
                fixture.Checkout("master");
                fixture.MergeNoFF("release/2.0.0");
                fixture.Repository.Branches.Remove(fixture.Repository.Branches["release/2.0.0"]);
                var remoteTagSha = fixture.Repository.Tags["2.0.0-rc.1"].Target.Sha;

                using (var localFixture = fixture.CloneRepository())
                {
                    localFixture.Checkout(remoteTagSha);
                    GitRepositoryHelper.NormalizeGitDirectory(localFixture.RepositoryPath, new AuthenticationInfo(), noFetch: false, currentBranch: string.Empty);

                    localFixture.Repository.Head.FriendlyName.ShouldBe("(no branch)");
                    localFixture.Repository.Head.Tip.Sha.ShouldBe(remoteTagSha);
                }
            }
        }
    public void GitFlowMajorRelease()
    {
        using (var fixture = new EmptyRepositoryFixture(new Config()))
        {
            fixture.Participant("master");
            fixture.Participant("develop");

            fixture.Repository.MakeACommit();
            fixture.ApplyTag("1.3.0");

            // GitFlow setup
            fixture.BranchTo("develop");
            fixture.MakeACommit();

            // Create release branch
            fixture.BranchTo("release/2.0.0", "release");
            fixture.Activate("release/2.0.0");
            fixture.AssertFullSemver("2.0.0-beta.1+0");

            // Make another commit on develop
            fixture.Checkout("develop");
            fixture.MakeACommit();
            fixture.AssertFullSemver("1.4.0-unstable.2");

            // Make a commit to release-2.0.0
            fixture.Checkout("release/2.0.0");
            fixture.MakeACommit();
            fixture.AssertFullSemver("2.0.0-beta.1+1");

            // Apply beta.1 tag should be exact tag
            fixture.ApplyTag("2.0.0-beta.1");
            fixture.AssertFullSemver("2.0.0-beta.1");

            // Make a commit after a tag should bump up the beta
            fixture.MakeACommit();
            fixture.AssertFullSemver("2.0.0-beta.2+2");

            // Complete release
            fixture.Checkout("master");
            fixture.MergeNoFF("release/2.0.0");
            fixture.Checkout("develop");
            fixture.MergeNoFF("release/2.0.0");
            fixture.Destroy("release/2.0.0");
            fixture.NoteOver("Release branches are deleted once merged", "release/2.0.0");

            fixture.Checkout("master");
            fixture.AssertFullSemver("2.0.0+0");
            fixture.ApplyTag("2.0.0");
            fixture.AssertFullSemver("2.0.0");

            // Not 0 for commit count as we can't know the increment rules of the merged branch
            fixture.Checkout("develop");
            fixture.AssertFullSemver("2.1.0-unstable.2");
        }
    }
 public void InheritVersionFromReleaseBranch()
 {
     using (var fixture = new EmptyRepositoryFixture())
     {
         fixture.MakeATaggedCommit("1.0.0");
         fixture.BranchTo("develop");
         fixture.MakeACommit();
         fixture.BranchTo("release/2.0.0");
         fixture.MakeACommit();
         fixture.MakeACommit();
         fixture.Checkout("develop");
         fixture.AssertFullSemver("1.1.0-alpha.1");
         fixture.MakeACommit();
         fixture.AssertFullSemver("2.1.0-alpha.1");
         fixture.MergeNoFF("release/2.0.0");
         fixture.AssertFullSemver("2.1.0-alpha.4");
         fixture.BranchTo("feature/MyFeature");
         fixture.MakeACommit();
         fixture.AssertFullSemver("2.1.0-MyFeature.1+3");
     }
 }
 public void TheReadmeSample()
 {
     using (LogHelper.Capture(_outputHelper, LogProvider.SetCurrentLogProvider))
     {
         using (var fixture = new EmptyRepositoryFixture())
         {
             fixture.MakeACommit();
             fixture.MakeACommit();
             fixture.MakeATaggedCommit("1.0.0");
             fixture.BranchTo("develop");
             fixture.MakeACommit();
             fixture.Checkout("master");
             fixture.MergeNoFF("develop");
         }
     }
 }
        public void VerifyForwardMerge()
        {
            using var fixture = new EmptyRepositoryFixture();
            fixture.Repository.MakeACommit("1");
            fixture.MakeATaggedCommit("1.0.0");
            fixture.MakeACommit(); // 1.0.1

            fixture.BranchTo("feature/foo", "foo");
            fixture.MakeACommit();
            fixture.AssertFullSemver(config, "1.0.2-foo.1");
            fixture.MakeACommit();
            fixture.AssertFullSemver(config, "1.0.2-foo.2");

            fixture.Checkout("master");
            fixture.MakeACommit();
            fixture.AssertFullSemver(config, "1.0.2");
            fixture.Checkout("feature/foo");
            // This may seem surprising, but this happens because we branched off mainline
            // and incremented. Mainline has then moved on. We do not follow mainline
            // in feature branches, you need to merge mainline in to get the mainline version
            fixture.AssertFullSemver(config, "1.0.2-foo.2");
            fixture.MergeNoFF("master");
            fixture.AssertFullSemver(config, "1.0.3-foo.3");
        }
            public void ShouldPickUpVersionFromMasterAfterReleaseBranchCreated()
            {
                var config = new Config
                {
                    Branches = new Dictionary<string, BranchConfig>
                    {
                        {
                            "master", new BranchConfig()
                            {
                                TracksReleaseBranches = true,
                                Regex = "master"
                            }
                        }
                    }
                };

                using (var fixture = new EmptyRepositoryFixture())
                {
                    // Create release branch
                    fixture.MakeACommit();
                    fixture.BranchTo("release/1.0");
                    fixture.MakeACommit();
                    fixture.Checkout("master");
                    fixture.MakeACommit();
                    fixture.AssertFullSemver(config, "1.0.1+1");

                    // create a misnamed feature branch (i.e. it uses the default config) from master and verify the version
                    fixture.BranchTo("misnamed");
                    fixture.AssertFullSemver(config, "1.0.1-misnamed.1+1");
                }
            }
    public void GitHubFlowMajorRelease()
    {
        using (var fixture = new EmptyRepositoryFixture(new Config()))
        {
            fixture.Participant("master");

            fixture.Repository.MakeACommit();
            fixture.ApplyTag("1.3.0");

            // Create release branch
            fixture.BranchTo("release/2.0.0", "release");
            fixture.Activate("release/2.0.0");
            fixture.MakeACommit();
            fixture.AssertFullSemver("2.0.0-beta.1+1");
            fixture.MakeACommit();
            fixture.AssertFullSemver("2.0.0-beta.1+2");

            // Apply beta.1 tag should be exact tag
            fixture.ApplyTag("2.0.0-beta.1");
            fixture.AssertFullSemver("2.0.0-beta.1");

            // Make a commit after a tag should bump up the beta
            fixture.MakeACommit();
            fixture.AssertFullSemver("2.0.0-beta.2+3");

            // Complete release
            fixture.Checkout("master");
            fixture.MergeNoFF("release/2.0.0");
            fixture.Destroy("release/2.0.0");
            fixture.NoteOver("Release branches are deleted once merged", "release/2.0.0");

            fixture.AssertFullSemver("2.0.0+0");
            fixture.ApplyTag("2.0.0");
            fixture.AssertFullSemver("2.0.0");
            fixture.MakeACommit();
            fixture.Repository.DumpGraph();
            fixture.AssertFullSemver("2.0.1+1");
        }
    }
    public void GitFlowSupportHotfixRelease()
    {
        using (var fixture = new EmptyRepositoryFixture(new Config()))
        {
            fixture.Participant("develop");
            fixture.Participant("master");

            fixture.Repository.MakeACommit();
            fixture.ApplyTag("1.3.0");

            // GitFlow setup
            fixture.Repository.MakeACommit();
            fixture.BranchTo("develop");
            fixture.NoteOver("Create 2.0.0 release and complete", "develop", "master");
            fixture.Checkout("master");
            fixture.ApplyTag("2.0.0");

            // Create hotfix branch
            fixture.Checkout("1.3.0");
            fixture.BranchToFromTag("support/1.x", "1.3.0", "master", "support");
            fixture.MakeACommit();
            fixture.AssertFullSemver("1.3.1+1");

            fixture.BranchTo("hotfix/1.3.1", "hotfix2");
            fixture.Activate("hotfix/1.3.1");
            fixture.MakeACommit();
            fixture.MakeACommit();
            fixture.AssertFullSemver("1.3.1-beta.1+3");

            // Apply beta.1 tag should be exact tag
            fixture.ApplyTag("1.3.1-beta.1");
            fixture.AssertFullSemver("1.3.1-beta.1");
            fixture.Checkout("support/1.x");
            fixture.MergeNoFF("hotfix/1.3.1");
            fixture.Destroy("hotfix/1.3.1");
            fixture.NoteOver("Hotfix branches are deleted once merged", "hotfix/1.3.1");
            fixture.AssertFullSemver("1.3.1+4");
            fixture.ApplyTag("1.3.1");
            fixture.AssertFullSemver("1.3.1");
        }
    }
    public void VerifyMergingMasterIntoAFeatureBranchWorksWithMultipleBranches()
    {
        using (var fixture = new EmptyRepositoryFixture())
        {
            fixture.MakeACommit("first in master");

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

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

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

            fixture.Checkout("feature/foo");
            fixture.MergeNoFF("master");
            fixture.MakeACommit("second in foo");

            fixture.Checkout("feature/bar");
            fixture.MergeNoFF("master");
            fixture.MakeACommit("second in bar");

            fixture.Checkout("master");
            fixture.MakeATaggedCommit("1.0.0");

            fixture.MergeNoFF("feature/foo");
            fixture.MergeNoFF("feature/bar");
            fixture.AssertFullSemver(config, "1.0.2");
        }
    }
        public void WhenPreventIncrementOfMergedBranchVersionIsSetToFalseForDevelopCommitsSinceVersionSourceShouldNotGoDownWhenMergingHotfixToDevelop()
        {
            var config = new Config
            {
                VersioningMode = VersioningMode.ContinuousDeployment,
                Branches       = new Dictionary <string, BranchConfig>
                {
                    { "develop", new BranchConfig {
                          PreventIncrementOfMergedBranchVersion = false
                      } },
                    { "hotfix", new BranchConfig {
                          PreventIncrementOfMergedBranchVersion = true, Regex = "^(origin/)?hotfix[/-]"
                      } },
                }
            };

            using var fixture = new EmptyRepositoryFixture();
            fixture.MakeACommit();
            fixture.BranchTo("develop");
            fixture.MakeATaggedCommit("1.0.0");
            fixture.Repository.MakeCommits(1);

            fixture.Checkout("develop");
            fixture.Repository.MakeCommits(3);
            fixture.AssertFullSemver("1.1.0-alpha.4", config);

            const string ReleaseBranch = "release/1.1.0";

            Commands.Checkout(fixture.Repository, fixture.Repository.CreateBranch(ReleaseBranch));
            fixture.Repository.MakeCommits(3);
            fixture.AssertFullSemver("1.1.0-beta.3", config);

            // Simulate a GitFlow release finish.
            fixture.Checkout("master");
            fixture.MergeNoFF(ReleaseBranch);
            fixture.ApplyTag("v1.1.0");
            fixture.Checkout("develop");

            // Simulate some work done on develop while the release branch was open.
            fixture.Repository.MakeCommits(2);
            fixture.MergeNoFF(ReleaseBranch);
            fixture.Repository.Branches.Remove(ReleaseBranch);
            fixture.AssertFullSemver("1.2.0-alpha.6", config);

            // Create hotfix for defects found in release/1.1.0
            const string HotfixBranch = "hotfix/1.1.1";

            fixture.Checkout("master");
            Commands.Checkout(fixture.Repository, fixture.Repository.CreateBranch(HotfixBranch));
            fixture.Repository.MakeCommits(3);

            // Hotfix finish
            fixture.Checkout("master");
            fixture.Repository.MergeNoFF(HotfixBranch);
            fixture.Repository.ApplyTag("v1.1.1");

            // Verify develop version
            fixture.Checkout("develop");
            // Simulate some work done on develop while the hotfix branch was open.
            fixture.Repository.MakeCommits(3);
            fixture.AssertFullSemver("1.2.0-alpha.9", config);
            fixture.Repository.MergeNoFF(HotfixBranch);
            fixture.AssertFullSemver("1.2.0-alpha.19", config);

            fixture.Repository.Branches.Remove(HotfixBranch);
            fixture.AssertFullSemver("1.2.0-alpha.19", config);
        }
Beispiel #16
0
        public void VerifyIncrementConfigIsHonoured()
        {
            var minorIncrementConfig = new Config
            {
                VersioningMode = VersioningMode.Mainline,
                Increment      = IncrementStrategy.Minor,
                Branches       = new Dictionary <string, BranchConfig>
                {
                    {
                        MainBranch,
                        new BranchConfig
                        {
                            Increment = IncrementStrategy.Minor,
                            Name      = MainBranch,
                            Regex     = MainBranch
                        }
                    },
                    {
                        "feature",
                        new BranchConfig
                        {
                            Increment = IncrementStrategy.Minor,
                            Name      = "feature",
                            Regex     = "features?[/-]"
                        }
                    }
                }
            };

            using var fixture = new EmptyRepositoryFixture();
            fixture.Repository.MakeACommit("1");
            fixture.MakeATaggedCommit("1.0.0");

            fixture.BranchTo("feature/foo", "foo");
            fixture.MakeACommit("2");
            fixture.AssertFullSemver("1.1.0-foo.1", minorIncrementConfig);
            fixture.MakeACommit("2.1");
            fixture.AssertFullSemver("1.1.0-foo.2", minorIncrementConfig);
            fixture.Checkout(MainBranch);
            fixture.MergeNoFF("feature/foo");

            fixture.AssertFullSemver("1.1.0", minorIncrementConfig);

            fixture.BranchTo("feature/foo2", "foo2");
            fixture.MakeACommit("3 +semver: patch");
            fixture.AssertFullSemver("1.1.1-foo2.1", minorIncrementConfig);
            fixture.Checkout(MainBranch);
            fixture.MergeNoFF("feature/foo2");
            fixture.AssertFullSemver("1.1.1", minorIncrementConfig);

            fixture.BranchTo("feature/foo3", "foo3");
            fixture.MakeACommit("4");
            fixture.Checkout(MainBranch);
            fixture.MergeNoFF("feature/foo3");
            fixture.SequenceDiagram.NoteOver("Merge message contains '+semver: patch'", MainBranch);
            var commit = fixture.Repository.Head.Tip;

            // Put semver increment in merge message
            fixture.Repository.Commit(commit.Message + " +semver: patch", commit.Author, commit.Committer, new CommitOptions
            {
                AmendPreviousCommit = true
            });
            fixture.AssertFullSemver("1.1.2", minorIncrementConfig);

            fixture.BranchTo("feature/foo4", "foo4");
            fixture.MakeACommit("5 +semver: major");
            fixture.AssertFullSemver("2.0.0-foo4.1", minorIncrementConfig);
            fixture.Checkout(MainBranch);
            fixture.MergeNoFF("feature/foo4");
            fixture.AssertFullSemver("2.0.0", config);

            // We should evaluate any commits not included in merge commit calculations for direct commit/push or squash to merge commits
            fixture.MakeACommit("6 +semver: major");
            fixture.AssertFullSemver("3.0.0", minorIncrementConfig);
            fixture.MakeACommit("7");
            fixture.AssertFullSemver("3.1.0", minorIncrementConfig);
            fixture.MakeACommit("8 +semver: patch");
            fixture.AssertFullSemver("3.1.1", minorIncrementConfig);

            // Finally verify that the merge commits still function properly
            fixture.BranchTo("feature/foo5", "foo5");
            fixture.MakeACommit("9 +semver: patch");
            fixture.AssertFullSemver("3.1.2-foo5.1", minorIncrementConfig);
            fixture.Checkout(MainBranch);
            fixture.MergeNoFF("feature/foo5");
            fixture.AssertFullSemver("3.1.2", minorIncrementConfig);

            // One more direct commit for good measure
            fixture.MakeACommit("10 +semver: patch");
            fixture.AssertFullSemver("3.1.3", minorIncrementConfig);
            // And we can commit without bumping semver
            fixture.MakeACommit("11 +semver: none");
            fixture.AssertFullSemver("3.1.3", minorIncrementConfig);
            Console.WriteLine(fixture.SequenceDiagram.GetDiagram());
        }
    public void PickUpVersionFromMasterMarkedWithIsTracksReleaseBranches()
    {
        var config = new Config
        {
            VersioningMode = VersioningMode.ContinuousDelivery,
            Branches = new Dictionary<string, BranchConfig>
                {
                    {
                        "master", new BranchConfig()
                        {
                            Tag = "pre",
                            TracksReleaseBranches = true,
                        }
                    },
                    {
                        "release", new BranchConfig()
                        {
                            IsReleaseBranch = true,
                            Tag = "rc",
                        }
                    }
                }
        };

        using (var fixture = new EmptyRepositoryFixture())
        {
            fixture.MakeACommit();

            // create a release branch and tag a release
            fixture.BranchTo("release/0.10.0");
            fixture.MakeACommit();
            fixture.MakeACommit();
            fixture.AssertFullSemver(config, "0.10.0-rc.1+2");

            // switch to master and verify the version
            fixture.Checkout("master");
            fixture.MakeACommit();
            fixture.AssertFullSemver(config, "0.10.1-pre.1+1");

            // create a feature branch from master and verify the version
            fixture.BranchTo("MyFeatureD");
            fixture.AssertFullSemver(config, "0.10.1-MyFeatureD.1+1");
        }
    }
    public void GitHubFlowMajorRelease()
    {
        using (var fixture = new EmptyRepositoryFixture())
        {
            fixture.SequenceDiagram.Participant("master");

            fixture.Repository.MakeACommit();
            fixture.ApplyTag("1.3.0");

            // Create release branch
            fixture.BranchTo("release/2.0.0", "release");
            fixture.SequenceDiagram.Activate("release/2.0.0");
            fixture.MakeACommit();
            fixture.AssertFullSemver("2.0.0-beta.1+1");
            fixture.MakeACommit();
            fixture.AssertFullSemver("2.0.0-beta.1+2");

            // Apply beta.1 tag should be exact tag
            fixture.ApplyTag("2.0.0-beta.1");
            fixture.AssertFullSemver("2.0.0-beta.1");

            // test that the CommitsSinceVersionSource should still return commit count
            var version = fixture.GetVersion(new Config());
            version.CommitsSinceVersionSource.ShouldBe("2");

            // Make a commit after a tag should bump up the beta
            fixture.MakeACommit();
            fixture.AssertFullSemver("2.0.0-beta.2+3");

            // Complete release
            fixture.Checkout("master");
            fixture.MergeNoFF("release/2.0.0");
            fixture.SequenceDiagram.Destroy("release/2.0.0");
            fixture.SequenceDiagram.NoteOver("Release branches are deleted once merged", "release/2.0.0");

            fixture.AssertFullSemver("2.0.0+0");
            fixture.ApplyTag("2.0.0");
            fixture.AssertFullSemver("2.0.0");
            fixture.MakeACommit();
            fixture.Repository.DumpGraph();
            fixture.AssertFullSemver("2.0.1+1");
        }
    }
    public void ShouldPickUpVersionFromDevelopAfterReleaseBranchMergedBack()
    {
        using (var fixture = new EmptyRepositoryFixture())
        {
            // Create develop and release branches
            fixture.MakeACommit();
            fixture.BranchTo("develop");
            fixture.MakeACommit();
            fixture.BranchTo("release/1.0");
            fixture.MakeACommit();

            // merge release into develop
            fixture.Checkout("develop");
            fixture.MergeNoFF("release/1.0");
            fixture.AssertFullSemver("1.1.0-alpha.2");

            // create a feature branch from develop and verify the version
            fixture.BranchTo("feature/test");
            fixture.AssertFullSemver("1.1.0-test.1+2");
        }
    }
    public void MergedFeatureBranchesToMasterImpliesRelease()
    {
        using (var fixture = new EmptyRepositoryFixture())
        {
            fixture.Repository.MakeACommit("1");
            fixture.MakeATaggedCommit("1.0.0");

            fixture.BranchTo("feature/foo", "foo");
            fixture.MakeACommit("2");
            fixture.AssertFullSemver(config, "1.0.1-foo.1");
            fixture.MakeACommit("2.1");
            fixture.AssertFullSemver(config, "1.0.1-foo.2");
            fixture.Checkout("master");
            fixture.MergeNoFF("feature/foo");

            fixture.AssertFullSemver(config, "1.0.1");

            fixture.BranchTo("feature/foo2", "foo2");
            fixture.MakeACommit("3 +semver: minor");
            fixture.AssertFullSemver(config, "1.1.0-foo2.1");
            fixture.Checkout("master");
            fixture.MergeNoFF("feature/foo2");
            fixture.AssertFullSemver(config, "1.1.0");

            fixture.BranchTo("feature/foo3", "foo3");
            fixture.MakeACommit("4");
            fixture.Checkout("master");
            fixture.MergeNoFF("feature/foo3");
            fixture.SequenceDiagram.NoteOver("Merge message contains '+semver: minor'", "master");
            var commit = fixture.Repository.Head.Tip;
            // Put semver increment in merge message
            fixture.Repository.Commit(commit.Message + " +semver: minor", commit.Author, commit.Committer, new CommitOptions
            {
                AmendPreviousCommit = true
            });
            fixture.AssertFullSemver(config, "1.2.0");

            fixture.BranchTo("feature/foo4", "foo4");
            fixture.MakeACommit("5 +semver: major");
            fixture.AssertFullSemver(config, "2.0.0-foo4.1");
            fixture.Checkout("master");
            fixture.MergeNoFF("feature/foo4");
            fixture.AssertFullSemver(config, "2.0.0");

            // We should evaluate any commits not included in merge commit calculations for direct commit/push or squash to merge commits
            fixture.MakeACommit("6 +semver: major");
            fixture.AssertFullSemver(config, "3.0.0");
            fixture.MakeACommit("7 +semver: minor");
            fixture.AssertFullSemver(config, "3.1.0");
            fixture.MakeACommit("8");
            fixture.AssertFullSemver(config, "3.1.1");

            // Finally verify that the merge commits still function properly
            fixture.BranchTo("feature/foo5", "foo5");
            fixture.MakeACommit("9 +semver: minor");
            fixture.AssertFullSemver(config, "3.2.0-foo5.1");
            fixture.Checkout("master");
            fixture.MergeNoFF("feature/foo5");
            fixture.AssertFullSemver(config, "3.2.0");

            // One more direct commit for good measure
            fixture.MakeACommit("10 +semver: minor");
            fixture.AssertFullSemver(config, "3.3.0");
            // And we can commit without bumping semver
            fixture.MakeACommit("11 +semver: none");
            fixture.AssertFullSemver(config, "3.3.0");
            Console.WriteLine(fixture.SequenceDiagram.GetDiagram());
        }
    }
    public void VerifyPullRequestsActLikeContinuousDelivery()
    {
        using (var fixture = new EmptyRepositoryFixture())
        {
            fixture.Repository.MakeACommit("1");
            fixture.MakeATaggedCommit("1.0.0");
            fixture.MakeACommit();
            fixture.AssertFullSemver(config, "1.0.1");

            fixture.BranchTo("feature/foo", "foo");
            fixture.MakeACommit();
            fixture.MakeACommit();
            fixture.Repository.CreatePullRequestRef("feature/foo", "master", normalise: true, prNumber: 8);
            fixture.AssertFullSemver(config, "1.0.2-PullRequest0008.3");
        }
    }
    public void VerifyForwardMerge()
    {
        using (var fixture = new EmptyRepositoryFixture())
        {
            fixture.Repository.MakeACommit("1");
            fixture.MakeATaggedCommit("1.0.0");
            fixture.MakeACommit(); // 1.0.1

            fixture.BranchTo("feature/foo", "foo");
            fixture.MakeACommit();
            fixture.MakeACommit();
            fixture.AssertFullSemver(config, "1.0.2-foo.2");

            fixture.Checkout("master");
            fixture.MakeACommit();
            fixture.AssertFullSemver(config, "1.0.2");
            fixture.Checkout("feature/foo");
            fixture.MergeNoFF("master");
            fixture.AssertFullSemver(config, "1.0.3-foo.3");
        }
    }
    public void SupportBranches()
    {
        using (var fixture = new EmptyRepositoryFixture())
        {
            fixture.Repository.MakeACommit("1");
            fixture.MakeATaggedCommit("1.0.0");
            fixture.MakeACommit(); // 1.0.1
            fixture.MakeACommit(); // 1.0.2
            fixture.AssertFullSemver(config, "1.0.2");

            fixture.BranchTo("support/1.0", "support10");
            fixture.AssertFullSemver(config, "1.0.3");

            // Move master on
            fixture.Checkout("master");
            fixture.MakeACommit("+semver: major"); // 2.0.0 (on master)
            fixture.AssertFullSemver(config, "2.0.0");

            // Continue on support/1.0
            fixture.Checkout("support/1.0");
            fixture.MakeACommit(); // 1.0.4
            fixture.MakeACommit(); // 1.0.5
            fixture.AssertFullSemver(config, "1.0.5");
            fixture.BranchTo("feature/foo", "foo");
            fixture.AssertFullSemver(config, "1.0.5-foo.0");
            fixture.MakeACommit();
            fixture.AssertFullSemver(config, "1.0.5-foo.1");
            fixture.MakeACommit();
            fixture.AssertFullSemver(config, "1.0.5-foo.2");
            fixture.Repository.CreatePullRequestRef("feature/foo", "support/1.0", normalise: true, prNumber: 7);
            fixture.AssertFullSemver(config, "1.0.5-PullRequest0007.3");
        }
    }
    public void VerifySupportForwardMerge()
    {
        using (var fixture = new EmptyRepositoryFixture())
        {
            fixture.Repository.MakeACommit("1");
            fixture.MakeATaggedCommit("1.0.0");
            fixture.MakeACommit(); // 1.0.1

            fixture.BranchTo("support/1.0", "support10");
            fixture.MakeACommit();
            fixture.MakeACommit();

            fixture.Checkout("master");
            fixture.MakeACommit("+semver: minor");
            fixture.AssertFullSemver(config, "1.1.0");
            fixture.MergeNoFF("support/1.0");
            fixture.AssertFullSemver(config, "1.1.1");
            fixture.MakeACommit();
            fixture.AssertFullSemver(config, "1.1.2");
            fixture.Checkout("support/1.0");
            fixture.AssertFullSemver(config, "1.0.4");

            fixture.BranchTo("feature/foo", "foo");
            fixture.MakeACommit();
            fixture.MakeACommit();
            fixture.AssertFullSemver(config, "1.0.4-foo.2"); // TODO This probably should be 1.0.5
        }
    }
    public void VerifyMergingMasterToFeatureDoesNotStopMasterCommitsIncrementingVersion()
    {
        using (var fixture = new EmptyRepositoryFixture())
        {
            fixture.MakeACommit("first in master");

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

            fixture.Checkout("master");
            fixture.MakeATaggedCommit("1.0.0");
            fixture.MakeACommit("third in master");

            fixture.Checkout("feature/foo");
            fixture.MergeNoFF("master");
            fixture.MakeACommit("second in foo");

            fixture.Checkout("master");
            fixture.MergeNoFF("feature/foo");
            fixture.AssertFullSemver(config, "1.0.2");
        }
    }
        public void FindsCorrectMergeBaseForMultipleForwardMerges()
        {
            //*403b294 44 minutes ago(develop)
            //|\
            //| *306b243 45 minutes ago(HEAD -> release-2.0.0)
            //| *4cf5969 47 minutes ago
            //| *4814083 51 minutes ago
            //* | cddd3cc 49 minutes ago
            //* | 2b2b52a 53 minutes ago
            //|\ \
            //| |/
            //| *8113776 54 minutes ago
            //| *3c0235e 56 minutes ago
            //|/
            //*f6f1283 58 minutes ago(main)

            using var fixture = new EmptyRepositoryFixture();
            fixture.MakeACommit("initial");
            fixture.BranchTo("develop");
            var fixtureRepository        = fixture.Repository.ToGitRepository();
            var expectedReleaseMergeBase = fixtureRepository.Head.Tip;

            // Create release from develop
            fixture.BranchTo("release-2.0.0");

            // Make some commits on release
            fixture.MakeACommit("release 1");
            fixture.MakeACommit("release 2");

            // First forward merge release to develop
            fixture.Checkout("develop");
            fixture.MergeNoFF("release-2.0.0");

            // Make some new commit on release
            fixture.Checkout("release-2.0.0");
            fixture.MakeACommit("release 3 - after first merge");

            // Make new commit on develop
            fixture.Checkout("develop");
            // Checkout to release (no new commits)
            fixture.Checkout("release-2.0.0");
            fixture.Checkout("develop");
            fixture.MakeACommit("develop after merge");

            // Checkout to release (no new commits)
            fixture.Checkout("release-2.0.0");

            // Make some new commit on release
            fixture.MakeACommit("release 4");
            fixture.MakeACommit("release 5");
            var expectedDevelopMergeBase = fixtureRepository.Head.Tip;

            // Second merge release to develop
            fixture.Checkout("develop");
            fixture.MergeNoFF("release-2.0.0");

            // Checkout to release (no new commits)
            fixture.Checkout("release-2.0.0");

            var develop = fixtureRepository.FindBranch("develop");
            var release = fixtureRepository.FindBranch("release-2.0.0");

            var gitRepoMetadataProvider = new RepositoryStore(log, fixtureRepository);

            var releaseBranchMergeBase = gitRepoMetadataProvider.FindMergeBase(release, develop);

            var developMergeBase = gitRepoMetadataProvider.FindMergeBase(develop, release);

            fixtureRepository.DumpGraph(Console.WriteLine);

            releaseBranchMergeBase.ShouldBe(expectedReleaseMergeBase);
            developMergeBase.ShouldBe(expectedDevelopMergeBase);
        }
    public void GitFlowMinorRelease()
    {
        using (var fixture = new EmptyRepositoryFixture())
        {
            fixture.SequenceDiagram.Participant("master");
            fixture.SequenceDiagram.Participant("develop");

            // GitFlow setup
            fixture.Repository.MakeACommit();
            fixture.ApplyTag("1.2.1");

            // GitFlow setup
            fixture.BranchTo("develop");
            fixture.MakeACommit();

            // Create release branch
            fixture.BranchTo("release/1.3.0", "release");
            fixture.SequenceDiagram.Activate("release/1.3.0");
            fixture.AssertFullSemver("1.3.0-beta.1+0");

            // Make another commit on develop
            fixture.Checkout("develop");
            fixture.MakeACommit();
            fixture.AssertFullSemver("1.4.0-alpha.1");

            // Make a commit to release-1.3.0
            fixture.Checkout("release/1.3.0");
            fixture.MakeACommit();
            fixture.AssertFullSemver("1.3.0-beta.1+1");

            // Apply beta.1 tag should be exact tag
            fixture.ApplyTag("1.3.0-beta.1");
            fixture.AssertFullSemver("1.3.0-beta.1");

            // Make a commit after a tag should bump up the beta
            fixture.MakeACommit();
            fixture.AssertFullSemver("1.3.0-beta.2+2");

            // Complete release
            fixture.Checkout("master");
            fixture.MergeNoFF("release/1.3.0");
            fixture.Checkout("develop");
            fixture.MergeNoFF("release/1.3.0");
            fixture.SequenceDiagram.Destroy("release/1.3.0");
            fixture.SequenceDiagram.NoteOver("Release branches are deleted once merged", "release/1.3.0");

            fixture.Checkout("master");
            fixture.ApplyTag("1.3.0");
            fixture.AssertFullSemver("1.3.0");

            // Not 0 for commit count as we can't know the increment rules of the merged branch
            fixture.Checkout("develop");
            fixture.AssertFullSemver("1.4.0-alpha.4");
            Console.WriteLine(fixture.SequenceDiagram.GetDiagram());
        }
    }
    public void GitFlowSupportMinorRelease()
    {
        using (var fixture = new EmptyRepositoryFixture())
        {
            fixture.SequenceDiagram.Participant("develop");
            fixture.SequenceDiagram.Participant("master");

            fixture.Repository.MakeACommit();
            fixture.ApplyTag("1.3.0");

            // GitFlow setup
            fixture.Repository.MakeACommit();
            fixture.BranchTo("develop");
            fixture.SequenceDiagram.NoteOver("Create 2.0.0 release and complete", "develop", "master");
            fixture.Checkout("master");
            fixture.ApplyTag("2.0.0");

            // Create hotfix branch
            fixture.Checkout("1.3.0");
            fixture.BranchToFromTag("support/1.x", "1.3.0", "master", "support");
            fixture.SequenceDiagram.NoteOver("Create 1.3.1 release and complete", "master", "support/1.x");
            fixture.Repository.MakeACommit();
            fixture.ApplyTag("1.3.1");

            fixture.BranchTo("release/1.4.0", "supportRelease");
            fixture.SequenceDiagram.Activate("release/1.4.0");
            fixture.MakeACommit();
            fixture.MakeACommit();
            fixture.AssertFullSemver("1.4.0-beta.1+2");

            // Apply beta.1 tag should be exact tag
            fixture.ApplyTag("1.4.0-beta.1");
            fixture.AssertFullSemver("1.4.0-beta.1");
            fixture.Checkout("support/1.x");
            fixture.MergeNoFF("release/1.4.0");
            fixture.SequenceDiagram.Destroy("release/1.4.0");
            fixture.SequenceDiagram.NoteOver("Release branches are deleted once merged", "release/1.4.0");
            fixture.AssertFullSemver("1.4.0+0");
            fixture.ApplyTag("1.4.0");
            fixture.AssertFullSemver("1.4.0");
        }
    }
        public void ShouldPickUpVersionFromMasterAfterReleaseBranchCreated()
        {
            using (var fixture = new EmptyRepositoryFixture())
            {
                // Create develop and release branches
                fixture.MakeACommit();
                fixture.BranchTo("develop");
                fixture.MakeACommit();
                fixture.BranchTo("release/1.0");
                fixture.MakeACommit();
                fixture.Checkout("develop");
                fixture.MakeACommit();
                fixture.AssertFullSemver("1.1.0-alpha.1");

                // create a misnamed feature branch (i.e. it uses the default config) from develop and verify the version
                fixture.BranchTo("misnamed");
                fixture.AssertFullSemver("1.1.0-misnamed.1+1");
            }
        }
    public void MergedFeatureBranchesToMasterImpliesRelease()
    {
        using (var fixture = new EmptyRepositoryFixture())
        {
            fixture.Repository.MakeACommit("1");
            fixture.MakeATaggedCommit("1.0.0");

            fixture.BranchTo("feature/foo", "foo");
            fixture.MakeACommit("2");
            fixture.AssertFullSemver(config, "1.0.1-foo.1");
            fixture.MakeACommit("2.1");
            fixture.AssertFullSemver(config, "1.0.1-foo.2");
            fixture.Checkout("master");
            fixture.MergeNoFF("feature/foo");

            fixture.AssertFullSemver(config, "1.0.1");

            fixture.BranchTo("feature/foo2", "foo2");
            fixture.MakeACommit("3 +semver: minor");
            fixture.AssertFullSemver(config, "1.1.0-foo2.1");
            fixture.Checkout("master");
            fixture.MergeNoFF("feature/foo2");
            fixture.AssertFullSemver(config, "1.1.0");

            fixture.BranchTo("feature/foo3", "foo3");
            fixture.MakeACommit("4");
            fixture.Checkout("master");
            fixture.MergeNoFF("feature/foo3");
            fixture.SequenceDiagram.NoteOver("Merge message contains '+semver: minor'", "master");
            var commit = fixture.Repository.Head.Tip;
            // Put semver increment in merge message
            fixture.Repository.Commit(commit.Message + " +semver: minor", commit.Author, commit.Committer, new CommitOptions
            {
                AmendPreviousCommit = true
            });
            fixture.AssertFullSemver(config, "1.2.0");

            fixture.BranchTo("feature/foo4", "foo4");
            fixture.MakeACommit("5 +semver: major");
            fixture.AssertFullSemver(config, "2.0.0-foo4.1");
            fixture.Checkout("master");
            fixture.MergeNoFF("feature/foo4");
            fixture.AssertFullSemver(config, "2.0.0");

            // We should evaluate any commits not included in merge commit calculations for direct commit/push or squash to merge commits
            fixture.MakeACommit("6 +semver: major");
            fixture.AssertFullSemver(config, "3.0.0");
            fixture.MakeACommit("7 +semver: minor");
            fixture.AssertFullSemver(config, "3.1.0");
            fixture.MakeACommit("8");
            fixture.AssertFullSemver(config, "3.1.1");

            // Finally verify that the merge commits still function properly
            fixture.BranchTo("feature/foo5", "foo5");
            fixture.MakeACommit("9 +semver: minor");
            fixture.AssertFullSemver(config, "3.2.0-foo5.1");
            fixture.Checkout("master");
            fixture.MergeNoFF("feature/foo5");
            fixture.AssertFullSemver(config, "3.2.0");

            // One more direct commit for good measure
            fixture.MakeACommit("10 +semver: minor");
            fixture.AssertFullSemver(config, "3.3.0");
            // And we can commit without bumping semver
            fixture.MakeACommit("11 +semver: none");
            fixture.AssertFullSemver(config, "3.3.0");
            Console.WriteLine(fixture.SequenceDiagram.GetDiagram());
        }
    }
        public void ShouldPickUpVersionFromMasterAfterReleaseBranchMergedBack()
        {
            var config = new Config
            {
                Branches = new Dictionary<string, BranchConfig>
                {
                    {
                        "master", new BranchConfig()
                        {
                            TracksReleaseBranches = true,
                            Regex = "master"
                        }
                    }
                }
            };

            using (var fixture = new EmptyRepositoryFixture())
            {
                // Create release branch
                fixture.MakeACommit();
                fixture.BranchTo("release/1.0");
                fixture.MakeACommit();

                // merge release into master
                fixture.Checkout("master");
                fixture.MergeNoFF("release/1.0");
                fixture.AssertFullSemver(config, "1.0.1+2");

                // create a feature branch from master and verify the version
                fixture.BranchTo("feature/test");
                fixture.AssertFullSemver(config, "1.0.1-test.1+2");
            }
        }