def prepare_release(release_type):
    """Bump the version, update the changelog and open a PR."""
    remote = 'origin'

    if any_uncommitted_changes():
        raise CommandError(
            'There are uncommitted changes. Please commit, stash or delete them and try again.',
        )

    subprocess.run(['git', 'fetch'], check=True)
    subprocess.run(['git', 'checkout', f'{remote}/develop'],
                   check=True,
                   capture_output=True)

    new_version = get_next_version(release_type)

    branch = f'changelog/{new_version}'
    pr_title = f'Prepare for release {new_version}'
    pr_body = f'This bumps the version and adds the changelog for version {new_version}.'
    commit_message = f"""{pr_title}\n\n{pr_body}"""

    if local_branch_exists(branch):
        raise CommandError(
            f'Branch {branch} already exists locally. Please delete it and try again.',
        )

    if remote_branch_exists(branch):
        raise CommandError(
            f'Branch {branch} already exists remotely. Please delete it on GitHub and try again.',
        )

    if not list_news_fragments():
        raise CommandError('There are no news fragments.')

    subprocess.run(['git', 'checkout', '-b', branch, f'{remote}/develop'],
                   check=True)
    subprocess.run(['towncrier', '--version',
                    str(new_version), '--yes'],
                   check=True)

    remaining_news_fragment_paths = list_news_fragments()
    if remaining_news_fragment_paths:
        joined_paths = '\n'.join(
            str(path) for path in remaining_news_fragment_paths)

        raise CommandError(
            'These news fragments were left behind:\n\n'
            f'{joined_paths}\n\n'
            'They may be misnamed. Please investigate.', )

    set_current_version(new_version)

    subprocess.run(['git', 'add', VERSION_FILE_PATH], check=True)
    subprocess.run(['git', 'commit', '-m', commit_message], check=True)
    subprocess.run(['git', 'push', '--set-upstream', remote, branch],
                   check=True)

    escaped_branch_name = quote(branch)
    params = {
        'expand': '1',
        'title': pr_title,
        'body': pr_body,
    }
    webbrowser.open(
        f'{BASE_GITHUB_REPO_URL}/compare/{escaped_branch_name}?{urlencode(params)}'
    )

    return branch
Esempio n. 2
0
def create_release_branch():
    """Create and push a release branch."""
    remote = 'origin'

    if any_uncommitted_changes():
        raise CommandError(
            'There are uncommitted changes. Please commit, stash or delete them and try again.',
        )

    subprocess.run(['git', 'fetch'], check=True)
    subprocess.run(['git', 'checkout', f'{remote}/develop'],
                   check=True,
                   capture_output=True)

    version = get_current_version()

    branch = f'release/{version}'
    tag = f'v{version}'

    if remote_tag_exists(tag):
        raise CommandError(
            f'A remote tag {tag} currently exists. It looks like version {version} has '
            f'already been released.', )

    news_fragment_paths = list_news_fragments()
    if news_fragment_paths:
        joined_paths = '\n'.join(str(path) for path in news_fragment_paths)

        raise CommandError(
            'These are news fragments on origin/develop:\n\n'
            f'{joined_paths}\n\n'
            'Is the changelog up to date?', )

    if local_branch_exists(branch):
        raise CommandError(
            f'Branch {branch} already exists locally. Please delete it and try again.',
        )

    if remote_branch_exists(branch):
        raise CommandError(
            f'Branch {branch} already exists remotely. Please delete it on GitHub and try again.',
        )

    subprocess.run(['git', 'checkout', '-b', branch, f'{remote}/develop'],
                   check=True)
    subprocess.run(['git', 'push', '--set-upstream', remote, branch],
                   check=True)

    params = {
        'expand':
        '1',
        'title':
        f'Release {version}',
        'body':
        PR_BODY_TEMPLATE.format(version=version,
                                release_guide_url=RELEASE_GUIDE_URL),
    }
    encoded_params = urlencode(params)
    escaped_branch_name = quote(branch)
    webbrowser.open(
        f'{GITHUB_BASE_REPO_URL}/compare/master...{escaped_branch_name}?{encoded_params}',
    )

    return branch
Esempio n. 3
0
def test_remote_branch_exists(side_effect, expected_result,
                              mock_subprocess_run):
    """Test that remote_branch_exists() returns the expected value in various scenarios."""
    mock_subprocess_run.side_effect = side_effect

    assert remote_branch_exists('test-branch') == expected_result