Exemple #1
0
    public void ShouldHideFixSectionWhenHideIsTrue()
    {
        var plainLinkBuilder = new PlainLinkBuilder();
        var changelog        = ChangelogBuilder.CreateForPath(_testDirectory);

        changelog.Write(
            new Version(1, 1, 0),
            new DateTimeOffset(),
            plainLinkBuilder,
            new List <ConventionalCommit>
        {
            ConventionalCommitParser.Parse(new TestCommit("a360d6a307909c6e571b29d4a329fd786c5d4543", "fix: a fix")),
            ConventionalCommitParser.Parse(new TestCommit("b360d6a307909c6e571b29d4a329fd786c5d4543", "feat: a feature")),
        },
            ChangelogOptions.Default with
        {
            Sections = new[]
            {
                new ChangelogSection {
                    Type = "feat", Hidden = false, Section = "Features"
                },
                new ChangelogSection {
                    Type = "fix", Hidden = true, Section = "Bug Fixes"
                },
            }
        });
Exemple #2
0
    public void ShouldGenerateAChangelogForFixFeatAndBreakingCommits()
    {
        var plainLinkBuilder = new PlainLinkBuilder();
        var changelog        = ChangelogBuilder.CreateForPath(_testDirectory);

        changelog.Write(
            new Version(1, 1, 0),
            new DateTimeOffset(),
            plainLinkBuilder,
            new List <ConventionalCommit>
        {
            ConventionalCommitParser.Parse(new TestCommit("a360d6a307909c6e571b29d4a329fd786c5d4543", "fix: a fix")),
            ConventionalCommitParser.Parse(new TestCommit("b360d6a307909c6e571b29d4a329fd786c5d4543", "feat: a feature")),
            ConventionalCommitParser.Parse(
                new TestCommit("c360d6a307909c6e571b29d4a329fd786c5d4543", "feat: a breaking change feature\nBREAKING CHANGE: this will break everything")),
        },
            ChangelogOptions.Default);

        var changelogContents = File.ReadAllText(changelog.FilePath);

        var sb = new ChangelogStringBuilder();

        sb.Append(ChangelogOptions.Preamble);
        sb.Append("<a name=\"1.1.0\"></a>");
        sb.Append("## 1.1.0 (1-1-1)", 2);
        sb.Append("### Features", 2);
        sb.Append("* a breaking change feature");
        sb.Append("* a feature", 2);
        sb.Append("### Bug Fixes", 2);
        sb.Append("* a fix", 2);
        sb.Append("### Breaking Changes", 2);
        sb.Append("* a breaking change feature", 2);
        Assert.Equal(sb.Build(), changelogContents);
    }
Exemple #3
0
        private Changelog SetUpUpdateChangelogWhenImageIsDeleted()
        {
            var changelog = new ChangelogBuilder()
                            .SetTitle(It.IsNotNull <string>())
                            .SetContent(It.IsNotNull <string>())
                            .SetImageUrl("url")
                            .Build();

            database.Setup(d => d.ChangelogRepository.FindById(updateRequest.ChangelogId))
            .ReturnsAsync(changelog);
            mapper.Setup(m => m.Map(updateRequest, changelog)).Returns(changelog);
            database.Setup(d => d.ChangelogRepository.Update(changelog)).ReturnsAsync(true);

            return(changelog);
        }
Exemple #4
0
    public void ShouldGenerateAChangelogEvenForEmptyCommits()
    {
        var plainLinkBuilder = new PlainLinkBuilder();
        var changelog        = ChangelogBuilder.CreateForPath(_testDirectory);

        changelog.Write(
            new Version(1, 1, 0),
            new DateTimeOffset(),
            plainLinkBuilder,
            new List <ConventionalCommit>(),
            ChangelogOptions.Default);

        var wasChangelogWritten = File.Exists(Path.Join(_testDirectory, "CHANGELOG.md"));

        Assert.True(wasChangelogWritten);
    }
Exemple #5
0
        private Changelog SetUpUpdateChangelogWhenImageIsChanged(bool imageInserted)
        {
            var changelog = new ChangelogBuilder()
                            .SetTitle(It.IsNotNull <string>())
                            .SetContent(It.IsNotNull <string>())
                            .SetImageUrl(It.IsAny <string>())
                            .Build();

            database.Setup(d => d.ChangelogRepository.FindById(updateRequest.ChangelogId))
            .ReturnsAsync(changelog);
            mapper.Setup(m => m.Map(updateRequest, changelog)).Returns(changelog);
            filesManager.Setup(fm => fm.Upload(It.IsNotNull <IFormFile>(), It.IsNotNull <string>()))
            .ReturnsAsync(new FileModel("path", "url", 1));
            database.Setup(d => d.ChangelogImageRepository.Insert(It.IsNotNull <ChangelogImage>(), false))
            .ReturnsAsync(imageInserted);
            database.Setup(d => d.ChangelogRepository.Update(changelog)).ReturnsAsync(true);

            return(changelog);
        }
Exemple #6
0
    public void ShouldGenerateWithoutLiteralLineBreakCharacters()
    {
        var plainLinkBuilder = new PlainLinkBuilder();
        var changelog        = ChangelogBuilder.CreateForPath(_testDirectory);

        changelog.Write(
            new Version(1, 1, 0),
            new DateTimeOffset(),
            plainLinkBuilder,
            new List <ConventionalCommit>
        {
            ConventionalCommitParser.Parse(new TestCommit("a360d6a307909c6e571b29d4a329fd786c5d4543", "fix: a fix")),
        },
            ChangelogOptions.Default);

        var contents = File.ReadAllText(Path.Join(_testDirectory, "CHANGELOG.md"));

        contents.ShouldNotContain("\\n");
    }
Exemple #7
0
        public async Task <Changelog> CreateChangelog(CreateChangelogRequest request)
        {
            var changelog = new ChangelogBuilder()
                            .SetTitle(request.Title)
                            .SetContent(request.Content)
                            .Build();

            if (!await database.ChangelogRepository.Insert(changelog, false))
            {
                throw new DatabaseException();
            }

            if (request.Image != null)
            {
                await UploadImage(request.Image, changelog);

                await database.ChangelogRepository.Update(changelog);
            }

            return(changelog);
        }
Exemple #8
0
    public SemanticVersion Versionize(VersionizeOptions options)
    {
        var workingDirectory = _directory.FullName;

        using var repo = new Repository(workingDirectory);

        var isDirty = repo.RetrieveStatus(new StatusOptions()).IsDirty;

        if (!options.SkipDirty && isDirty)
        {
            Exit($"Repository {workingDirectory} is dirty. Please commit your changes.", 1);
        }

        var projects = Projects.Discover(workingDirectory);

        if (projects.IsEmpty())
        {
            Exit($"Could not find any projects files in {workingDirectory} that have a <Version> defined in their csproj file.", 1);
        }

        if (projects.HasInconsistentVersioning())
        {
            Exit($"Some projects in {workingDirectory} have an inconsistent <Version> defined in their csproj file. Please update all versions to be consistent or remove the <Version> elements from projects that should not be versioned", 1);
        }

        Information($"Discovered {projects.GetProjectFiles().Count()} versionable projects");
        foreach (var project in projects.GetProjectFiles())
        {
            Information($"  * {project}");
        }

        var versionTag       = repo.SelectVersionTag(projects.Version);
        var isInitialRelease = versionTag == null;
        var commitsInVersion = repo.GetCommitsSinceLastVersion(versionTag);

        var conventionalCommits = ConventionalCommitParser.Parse(commitsInVersion);

        var versionIncrement = new VersionIncrementStrategy(conventionalCommits);

        var nextVersion = isInitialRelease ? projects.Version : versionIncrement.NextVersion(projects.Version, options.Prerelease);

        // For non initial releases: for insignificant commits such as chore increment the patch version if IgnoreInsignificantCommits is not set
        if (!isInitialRelease && nextVersion == projects.Version)
        {
            if (options.IgnoreInsignificantCommits || options.ExitInsignificantCommits)
            {
                var exitCode = options.ExitInsignificantCommits ? 1 : 0;
                Exit($"Version was not affected by commits since last release ({projects.Version})", exitCode);
            }
            else
            {
                nextVersion = nextVersion.IncrementPatchVersion();
            }
        }

        if (!string.IsNullOrWhiteSpace(options.ReleaseAs))
        {
            try
            {
                nextVersion = SemanticVersion.Parse(options.ReleaseAs);
            }
            catch (Exception)
            {
                Exit($"Could not parse the specified release version {options.ReleaseAs} as valid version", 1);
            }
        }

        if (nextVersion < projects.Version)
        {
            Exit($"Semantic versioning conflict: the next version {nextVersion} would be lower than the current version {projects.Version}. This can be caused by using a wrong pre-release label or release as version", 1);
        }

        if (!options.DryRun && !options.SkipCommit && repo.VersionTagsExists(nextVersion))
        {
            Exit($"Version {nextVersion} already exists. Please use a different version.", 1);
        }

        var versionTime = DateTimeOffset.Now;

        // Commit changelog and version source
        if (!options.DryRun && (nextVersion != projects.Version))
        {
            projects.WriteVersion(nextVersion);

            foreach (var projectFile in projects.GetProjectFiles())
            {
                Commands.Stage(repo, projectFile);
            }
        }

        Step($"bumping version from {projects.Version} to {nextVersion} in projects");

        var changelog            = ChangelogBuilder.CreateForPath(workingDirectory);
        var changelogLinkBuilder = LinkBuilderFactory.CreateFor(repo);

        if (options.DryRun)
        {
            string markdown = ChangelogBuilder.GenerateMarkdown(nextVersion, versionTime, changelogLinkBuilder, conventionalCommits, options.Changelog);
            DryRun(markdown.TrimEnd('\n'));
        }
        else
        {
            changelog.Write(nextVersion, versionTime, changelogLinkBuilder, conventionalCommits, options.Changelog);
        }

        Step("updated CHANGELOG.md");

        if (!options.DryRun && !options.SkipCommit)
        {
            if (!repo.IsConfiguredForCommits())
            {
                Exit(@"Warning: Git configuration is missing. Please configure git before running versionize:
git config --global user.name ""John Doe""
$ git config --global user.email [email protected]", 1);
            }

            Commands.Stage(repo, changelog.FilePath);

            foreach (var projectFile in projects.GetProjectFiles())
            {
                Commands.Stage(repo, projectFile);
            }

            var author    = repo.Config.BuildSignature(versionTime);
            var committer = author;

            var releaseCommitMessage = $"chore(release): {nextVersion} {options.CommitSuffix}".TrimEnd();
            var versionCommit        = repo.Commit(releaseCommitMessage, author, committer);
            Step("committed changes in projects and CHANGELOG.md");

            repo.Tags.Add($"v{nextVersion}", versionCommit, author, $"{nextVersion}");
            Step($"tagged release as {nextVersion}");

            Information("");
            Information("i Run `git push --follow-tags origin master` to push all changes including tags");
        }
        else if (options.SkipCommit)
        {
            Information("");
            Information($"i Commit and tagging of release was skipped. Tag this release as `v{nextVersion}` to make versionize detect the release");
        }

        return(nextVersion);
    }