Пример #1
0
def current_version_option_validator(ctx, param, value):
    """If a version string is provided, validates it. Otherwise it tries
    to determine the current version from the last Git tag that matches
    ``tag_pattern`` option.

    Return a :class:`~braulio.version.Version` object or **None**.
    """

    current_version = None

    if value:
        try:
            current_version = Version(value)
        except ValueError:
            ctx.fail(f"{value} is not a valid version string")

    # Look for the last git tag for the curren version
    git = Git()
    tag_pattern = ctx.params["tag_pattern"]
    versions = tag_analyzer(git.tags, tag_pattern, Version)

    # User provided current version. Try to find a tag that match it.
    if current_version:
        for version in versions:
            if version == current_version:
                current_version = version
                break
    elif versions:
        current_version = versions[0]

    ctx.params[
        "current_tag"] = current_version.tag if current_version else None
    ctx.params["versions"] = versions

    return current_version
Пример #2
0
    def test_pass_files_to_commit(self, mocked_git_add, mocked_run_command):
        git = Git()
        git.commit("A good message", files=["file1.py", "file2.py"])

        # When autospec is used on a class method, the self parameter
        # must be passed to too.
        git.add.assert_called_with(git, "file1.py", "file2.py")

        command = ["git", "commit", "-m", '"A good message"']
        mocked_run_command.assert_called_with(command)
Пример #3
0
    def test_log_all_commits(self, mocked_run_command, fake_git_log_output):
        mocked_run_command.return_value = fake_git_log_output

        git = Git()
        commits = git.log()

        mocked_run_command.assert_called_with(["git", "log"])
        assert len(commits) == 12
        assert isinstance(commits[0], Commit)

        first = commits[0]
        assert first.header == "Fix lorem ipsum dolor sit amet"

        last = commits[-1]
        assert last.header == "Add additional information (#26)"
Пример #4
0
    def test_get_tags(self, mocked_run_command, command_output, expected):
        mocked_run_command.return_value = command_output

        git = Git()
        lst = git.tag()

        mocked_run_command.assert_called_with([
            "git",
            "tag",
            "-l",
            "--sort=creatordate",
            "--format=%(creatordate:short)%09%(refname:strip=2)",
        ])

        assert type(lst) == list
        assert len(lst) == expected

        if expected > 0:
            for _tag in lst:
                assert type(_tag) == Tag

            assert lst[0].name == "v0.0.6"
            assert lst[5].name == "v0.0.1"
Пример #5
0
def release(
    ctx,
    bump,
    bump_type,
    commit_flag,
    message,
    tag_flag,
    confirm_flag,
    changelog_file,
    files,
    label_pattern,
    label_position,
    tag_pattern,
    current_version,
    stage,
    merge_pre,
    current_tag=None,
    versions=None,
):
    """Release a new version.

    Determines the next version by inspecting commit messages, updates the
    changelog, commit the changes and tag the repository with the new version.
    """
    # If there isn't a current version, assume version 0.0.0
    current_version = current_version or Version()

    git = Git()
    from_tag = current_tag.name if current_tag else None

    # Delimiter of the block to be removed from the changelog file
    remove_pre_chglog = None

    # Look for the last final release version if the user want it
    if merge_pre and current_version.stage != "final":
        remove_pre_chglog = [current_version.string]

        for version in versions:
            if version.stage == "final":
                from_tag = version.tag.name
                remove_pre_chglog.append(version.string)
                break

    commit_list = git.log(_from=from_tag)

    msg(f'{label("Current version")} {current_version}')
    msg(f'{label("Commits found")} {len(commit_list)} since last release')

    if not commit_list:
        click.echo(" › Nothing to release.")
        ctx.exit()

    semantic_commits = commit_analyzer(commit_list, label_pattern,
                                       label_position)

    release_data = ReleaseDataTree(semantic_commits)

    bump_version_to = None

    # --bump, --major, --minor, --patch or commit message based version
    # are taken into account only if the current version is in final stage.
    if current_version.stage == "final":

        # --bump have precedence over any of --major, --minor or --patch
        bump_version_to = bump.string if bump else bump_type

        # Any manual bump have precedence over commit message based versions.
        bump_version_to = bump_version_to or release_data.bump_version_to

    try:
        new_version = get_next_version(current_version, bump_version_to, stage)
    except ValueError as e:
        ctx.fail(e)

    if not new_version:
        msg("The release of a lower versions is not supported for now.")
        ctx.abort()

    new_tag_name = tag_pattern.format(version=new_version.string)

    msg(f'{label("New version")} {new_version}')
    msg(f'{label("Changelog file")} {changelog_file.name}')

    # Messages about what tasks will be performed
    msg("Braulio will perform the next tasks :")
    msg(f"        Update {len(files) + 1} files.", prefix="")
    msg("        Add a release commit.", prefix="", silence=not commit_flag)
    msg(
        f"        Tag the repository with {new_tag_name}",
        prefix="",
        silence=not tag_flag,
    )

    msg("", prefix="")  # Print just a new line

    if confirm_flag or click.confirm(f"{prefix_mark}Continue?"):

        msg("Update changelog ", nl=False)

        update_chglog(
            changelog_file,
            new_version=new_version,
            current_version=current_version,
            release_data=release_data,
            remove=remove_pre_chglog,
        )

        msg(check_mark, prefix="")

        try:
            update_files(files, str(current_version), str(new_version))
        except ValueError as e:
            click.echo(e)
            ctx.abort()

        if commit_flag:
            message_args = {"new_version": new_version.string}

            if "{current_version}" in message:
                message_args["current_version"] = current_version.string

            commit_message = message.format(**message_args)

            msg(f"Add commit: {commit_message}", nl=False)

            files = [str(changelog_file)] + list(files)
            git.commit(commit_message, files=files)
            msg(f" {check_mark}", prefix="")

        if tag_flag:
            msg(f"Add tag {new_tag_name}", nl=False)
            git.tag(new_tag_name)
            msg(f" {check_mark}", prefix="")

        if "current_version" in ctx.obj.cfg_file_options:
            update_config_file("current_version", new_version.string)

        msg(f"Version {new_version} released successfully", suffix=" 🎉")
Пример #6
0
    def test_add_tag(self, mocked_run_command):
        git = Git()
        git.tag("tagname")

        mocked_run_command.assert_called_with(
            ["git", "tag", "-a", "tagname", "-m", '""'])
Пример #7
0
    def test_log_range(self, mocked_run_command, f, t, revision_range):

        git = Git()
        git.log(_from=f, to=t)

        mocked_run_command.assert_called_with(["git", "log"] + revision_range)
Пример #8
0
    def test_call_to_run_command(self, mocked_run_command):
        git = Git()
        git.commit("A message")

        command = ["git", "commit", "-m", '"A message"']
        mocked_run_command.assert_called_with(command)
Пример #9
0
    def test_when_provided_files_does_not_exits(self):
        git = Git()

        error = "No such file or directory: this_does_not_exist.py"
        with pytest.raises(FileNotFoundError, match=error):
            git.add("this_does_not_exist.py")
Пример #10
0
    def test_run_command_call(self, mocked_run_command, files, expected):
        git = Git()
        git.add(*files)

        command = ("git", "add")
        mocked_run_command.assert_called_with(command + expected)