Ejemplo n.º 1
0
def setup_sdist(opts):
    LOGGER.info("Running setup.py sdist...")
    local('cd {} && python setup.py sdist'.format(repo_directory()))
    dist_dir = os.path.join(repo_directory(), 'dist')
    pkg = opts.package
    if opts.pypi_package_name:
        pkg = opts.pypi_package_name
    package = "{}-{}.tar.gz".format(pkg, opts.version)
    return os.path.join(dist_dir, package)
Ejemplo n.º 2
0
def load_configuration(package_dir=None, gitconfig_file=None):
    """
    _load_configuration_

    Load the cirrus.conf file and parse it into a nested dictionary
    like Configuration instance.

    :param package_dir: Location of cirrus managed package if not pwd
    :param gitconfig_file: Path to gitconfig if not ~/.gitconfig
    :returns: Configuration instance

    """
    dirname = os.getcwd()
    if package_dir is not None:
        dirname = package_dir

    config_path = os.path.join(dirname, 'cirrus.conf')
    if not os.path.exists(config_path):
        repo_dir = repo_directory()
        if repo_dir is not None:
            config_path = os.path.join(repo_dir, 'cirrus.conf')

    if not os.path.exists(config_path):
        msg = "Couldnt find ./cirrus.conf, are you in a package directory?"
        raise RuntimeError(msg)

    config_instance = Configuration(config_path, gitconfig_file=gitconfig_file)
    config_instance.load()
    return config_instance
Ejemplo n.º 3
0
def load_configuration(package_dir=None, gitconfig_file=None):
    """
    _load_configuration_

    Load the cirrus.conf file and parse it into a nested dictionary
    like Configuration instance.

    :param package_dir: Location of cirrus managed package if not pwd
    :param gitconfig_file: Path to gitconfig if not ~/.gitconfig
    :returns: Configuration instance

    """
    dirname = os.getcwd()
    if package_dir is not None:
        dirname = package_dir

    config_path = os.path.join(dirname, 'cirrus.conf')
    if not os.path.exists(config_path):
        repo_dir = repo_directory()
        if repo_dir is not None:
            config_path = os.path.join(repo_dir, 'cirrus.conf')

    if not os.path.exists(config_path):
        msg = "Couldnt find ./cirrus.conf, are you in a package directory?"
        raise RuntimeError(msg)

    config_instance = Configuration(config_path, gitconfig_file=gitconfig_file)
    config_instance.load()
    return config_instance
Ejemplo n.º 4
0
def list_feature_branches(opts):
    """
    list unmerged feature branches
    """
    repo_dir = repo_directory()
    print("unmerged feature branches:")
    with GitHubContext(repo_dir) as ghc:
        for x in ghc.iter_git_feature_branches(merged=False):
            print(x)
Ejemplo n.º 5
0
def show_release_status(opts):
    """check release status"""
    release = opts.release
    if release is None:
        release = current_branch(repo_directory())
    result = release_status(release)
    if not result:
        # unmerged/tagged release => exit as error status
        sys.exit(1)
Ejemplo n.º 6
0
 def __init__(self):
     super(Linter, self).__init__()
     self.config = load_configuration()
     self.linter_config = self.config.get(
         'qc/{}'.format(type(self).__name__, {}), {})
     self.working_dir = repo_directory()
     self.pass_threshold = 0
     self.test_mode = False
     self.errors = {}
Ejemplo n.º 7
0
def list_feature_branches(opts):
    """
    list unmerged feature branches
    """
    repo_dir = repo_directory()
    print("unmerged feature branches:")
    with GitHubContext(repo_dir) as ghc:
        for x in ghc.iter_git_feature_branches(merged=False):
            print(x)
Ejemplo n.º 8
0
def make_new_version(opts):
    LOGGER.info("Updating package version...")
    if not highlander([opts.major, opts.minor, opts.micro]):
        msg = "Can only specify one of --major, --minor or --micro"
        LOGGER.error(msg)
        raise RuntimeError(msg)

    fields = ['major', 'minor', 'micro']
    mask = [opts.major, opts.minor, opts.micro]
    field = [x for x in itertools.compress(fields, mask)][0]

    config = load_configuration()
    current_version = config.package_version()

    # need to be on the latest develop
    repo_dir = repo_directory()
    curr_branch = current_branch(repo_dir)
    # make sure repo is clean
    if has_unstaged_changes(repo_dir):
        msg = ("Error: Unstaged changes are present on the branch {}"
               "Please commit them or clean up before proceeding"
               ).format(curr_branch)
        LOGGER.error(msg)
        raise RuntimeError(msg)

    # update cirrus conf
    new_version = bump_version_field(current_version, field)

    msg = "Bumping version from {prev} to {new} on branch {branch}".format(
        prev=current_version, new=new_version, branch=curr_branch)
    LOGGER.info(msg)

    config.update_package_version(new_version)
    changes = ['cirrus.conf']

    if opts.bump:
        reqs_file = os.path.join(repo_dir, 'requirements.txt')
        for pkg, version in opts.bump:
            LOGGER.info("Bumping dependency {} to {}".format(pkg, version))
            bump_package(reqs_file, pkg, version)
        changes.append(reqs_file)

    # update __version__ or equivalent
    version_file, version_attr = config.version_file()
    if version_file is not None:
        LOGGER.info('Updating {0} attribute in {1}'.format(
            version_file, version_attr))
        update_version(version_file, new_version, version_attr)
        changes.append(version_file)

    # update files changed
    msg = "cirrus release: version bumped for {0}".format(curr_branch)
    LOGGER.info('Committing files: {0}'.format(','.join(changes)))
    LOGGER.info(msg)
    commit_files_optional_push(repo_dir, msg, not opts.no_remote, *changes)
Ejemplo n.º 9
0
 def __init__(self):
     super(Builder, self).__init__()
     self.plugin_parser = argparse.ArgumentParser()
     self.config = load_configuration()
     self.build_config = self.config.get('build', {})
     self.working_dir = repo_directory()
     self.venv_name = self.build_config.get('virtualenv_name', 'venv')
     self.reqs_name = self.build_config.get('requirements_file', 'requirements.txt')
     self.extra_reqs = self.build_config.get('extra_requirements', [])
     self.python_bin = self.build_config.get('python', None)
     self.extra_reqs = self.str_to_list(self.extra_reqs)
     self.venv_path = os.path.join(self.working_dir, self.venv_name)
Ejemplo n.º 10
0
 def __init__(self):
     super(Builder, self).__init__()
     self.plugin_parser = argparse.ArgumentParser()
     self.config = load_configuration()
     self.build_config = self.config.get('build', {})
     self.working_dir = repo_directory()
     self.venv_name = self.build_config.get('virtualenv_name', 'venv')
     self.reqs_name = self.build_config.get('requirements_file', 'requirements.txt')
     self.extra_reqs = self.build_config.get('extra_requirements', [])
     self.python_bin = self.build_config.get('python', None)
     self.extra_reqs = self.str_to_list(self.extra_reqs)
     self.venv_path = os.path.join(self.working_dir, self.venv_name)
Ejemplo n.º 11
0
def nose_run(config, opts):
    """
    _nose_test_

    Locally activate vitrualenv and run tests via nose
    """
    where = config.test_where(opts.suite)
    suite_conf = config.test_suite(opts.suite)
    test_opts = suite_conf.get('test_options')
    venv_path = os.path.join(repo_directory(), config.venv_name())
    if opts.options:
        # command line overrides
        test_opts = opts.options
    activate = activate_command(venv_path)

    local('{0} && nosetests -w {1} {2}'.format(activate, where,
                                               test_opts if test_opts else ""))
Ejemplo n.º 12
0
def new_pr(opts):
    """
    _new_pr_

    Creates a pull request
    """
    repo_dir = repo_directory()
    #parse notify adding '@' if necessary
    notifiees = []
    if opts.notify is not None:
        notify = opts.notify.split(',')
        for user in notify:
            if not user.startswith('@'):
                tmp = '@{0}'.format(user)
                notifiees.append(tmp)

    pr_body = '{0} \n{1}'.format(' '.join(notifiees), opts.body)
    pr_info = {'title': opts.title, 'body': pr_body}
    pr_url = create_pull_request(repo_dir, pr_info)
    LOGGER.info("Created PR {0}".format(pr_url))
Ejemplo n.º 13
0
def new_feature_branch(opts):
    """
    _new_feature_branch_

    Checks out branch, creates new branch 'name', optionally
    pushes new branch to remote
    """
    config = load_configuration()
    repo_dir = repo_directory()
    checkout_and_pull(repo_dir,
                      config.gitflow_branch_name(),
                      pull=not opts.no_remote)
    LOGGER.info("Checked out and pulled {0}".format(
        config.gitflow_branch_name()))
    branch_name = ''.join((config.gitflow_feature_prefix(), opts.name[0]))
    branch(repo_dir, branch_name, config.gitflow_branch_name())
    LOGGER.info("Created branch {0}".format(branch_name))
    if not opts.no_remote:
        push(repo_dir)
        LOGGER.info("Branch {0} pushed to remote".format(branch_name))
Ejemplo n.º 14
0
def tox_run(config, opts):
    """
    tox test

    activate venv and run tox test suite

    """
    suite_conf = config.test_suite(opts.suite)
    tox_ini = suite_conf.get('tox_ini')
    test_opts = suite_conf.get('test_options')
    venv_path = os.path.join(repo_directory(), config.venv_name())
    if opts.options:
        # command line overrides
        test_opts = opts.options
    tox_command = "tox"
    if tox_ini:
        tox_command += " -c {}".format(tox_ini)
    if test_opts:
        tox_command += " {}".format(test_opts)
    activate = activate_command(venv_path)
    local('{0} && {1}'.format(activate, tox_command))
Ejemplo n.º 15
0
def new_pr(opts):
    """
    _new_pr_

    Creates a pull request
    """
    repo_dir = repo_directory()
    #parse notify adding '@' if necessary
    notifiees = []
    if opts.notify is not None:
        notify = opts.notify.split(',')
        for user in notify:
            if not user.startswith('@'):
                tmp = '@{0}'.format(user)
                notifiees.append(tmp)

    pr_body = '{0} \n{1}'.format(' '.join(notifiees), opts.body)
    pr_info = {
        'title': opts.title,
        'body': pr_body}
    pr_url = create_pull_request(repo_dir, pr_info)
    LOGGER.info("Created PR {0}".format(pr_url))
Ejemplo n.º 16
0
def merge_feature_branch(opts):
    """
    merge current feature branch into develop
    """
    config = load_configuration()
    main_branch = config.gitflow_branch_name()
    repo_dir = repo_directory()
    curr_branch = current_branch(repo_dir)
    LOGGER.info("Merging {} into {}".format(curr_branch, main_branch))
    # make sure repo is clean
    if has_unstaged_changes(repo_dir):
        msg = ("Error: Unstaged changes are present on the feature branch {}"
               "Please commit them or clean up before proceeding"
               ).format(curr_branch)
        LOGGER.error(msg)
        raise RuntimeError(msg)

    checkout_and_pull(repo_dir, main_branch, pull=not opts.no_remote)
    with GitHubContext(repo_dir) as ghc:
        ghc.merge_branch(curr_branch)
        if not opts.no_remote:
            ghc.push_branch(main_branch)
            LOGGER.info("Branch {0} pushed to remote".format(main_branch))
Ejemplo n.º 17
0
def merge_feature_branch(opts):
    """
    merge current feature branch into develop
    """
    config = load_configuration()
    main_branch = config.gitflow_branch_name()
    repo_dir = repo_directory()
    curr_branch = current_branch(repo_dir)
    LOGGER.info("Merging {} into {}".format(curr_branch, main_branch))
    # make sure repo is clean
    if has_unstaged_changes(repo_dir):
        msg = (
            "Error: Unstaged changes are present on the feature branch {}"
            "Please commit them or clean up before proceeding"
        ).format(curr_branch)
        LOGGER.error(msg)
        raise RuntimeError(msg)

    checkout_and_pull(repo_dir,  main_branch, pull=not opts.no_remote)
    with GitHubContext(repo_dir) as ghc:
        ghc.merge_branch(curr_branch)
        if not opts.no_remote:
            ghc.push_branch(main_branch)
            LOGGER.info("Branch {0} pushed to remote".format(main_branch))
Ejemplo n.º 18
0
def new_feature_branch(opts):
    """
    _new_feature_branch_

    Checks out branch, creates new branch 'name', optionally
    pushes new branch to remote
    """
    config = load_configuration()
    repo_dir = repo_directory()
    checkout_and_pull(
        repo_dir,
        config.gitflow_branch_name(),
        pull=not opts.no_remote
    )
    LOGGER.info("Checked out and pulled {0}".format(
        config.gitflow_branch_name()))
    branch_name = ''.join((config.gitflow_feature_prefix(), opts.name[0]))
    branch(repo_dir,
           branch_name,
           config.gitflow_branch_name())
    LOGGER.info("Created branch {0}".format(branch_name))
    if not opts.no_remote:
        push(repo_dir)
        LOGGER.info("Branch {0} pushed to remote".format(branch_name))
Ejemplo n.º 19
0
def execute_build(opts):
    """
    _execute_build_

    Execute the build in the current package context.

    - reads the config to check for custom build parameters
      - defaults to ./venv for virtualenv
      - defaults to ./requirements.txt for reqs
    - removes existing virtualenv if clean flag is set
    - builds the virtualenv
    - pip installs the requirements into it

    : param argparse.Namspace opts: A Namespace of build options
    """
    working_dir = repo_directory()
    config = load_configuration()
    build_params = config.get('build', {})

    # we have custom build controls in the cirrus.conf
    venv_name = build_params.get('virtualenv_name', 'venv')
    reqs_name = build_params.get('requirements_file', 'requirements.txt')
    extra_reqs = build_params.get('extra_requirements', '')
    python_bin = build_params.get('python', None)
    if opts.python:
        python_bin = opts.python
    extra_reqs = [x.strip() for x in extra_reqs.split(',') if x.strip()]
    if opts.extras:
        extra_reqs.extend(opts.extras)
        extra_reqs = set(extra_reqs)  # dedupe

    venv_path = os.path.join(working_dir, venv_name)
    if is_anaconda():
        conda_venv(venv_path, opts, python_bin)
    else:
        virtualenv_venv(venv_path, opts, python_bin)

    # custom pypi server
    pypi_server = config.pypi_url()
    pip_options = config.pip_options()
    pip_command_base = None
    if pypi_server is not None:

        pypirc = PypircFile()
        if pypi_server in pypirc.index_servers:
            pypi_url = pypirc.get_pypi_url(pypi_server)
        else:
            pypi_conf = get_pypi_auth()
            pypi_url = (
                "https://{pypi_username}:{pypi_token}@{pypi_server}/simple"
            ).format(pypi_token=pypi_conf['token'],
                     pypi_username=pypi_conf['username'],
                     pypi_server=pypi_server)

        pip_command_base = ('{0}/bin/pip install -i {1}').format(
            venv_path, pypi_url)

        if opts.upgrade:
            cmd = ('{0} --upgrade '
                   '-r {1}').format(pip_command_base, reqs_name)
        else:
            cmd = ('{0} ' '-r {1}').format(pip_command_base, reqs_name)

    else:
        pip_command_base = '{0}/bin/pip install'.format(venv_path)
        # no pypi server
        if opts.upgrade:
            cmd = '{0} --upgrade -r {1}'.format(pip_command_base, reqs_name)
        else:
            cmd = '{0} -r {1}'.format(pip_command_base, reqs_name)

    if pip_options:
        cmd += " {} ".format(pip_options)

    try:
        local(cmd)
    except OSError as ex:
        msg = ("Error running pip install command during build\n"
               "Error was {0}\n"
               "Running command: {1}\n"
               "Working Dir: {2}\n"
               "Virtualenv: {3}\n"
               "Requirements: {4}\n").format(ex, cmd, working_dir, venv_path,
                                             reqs_name)
        LOGGER.error(msg)
        sys.exit(1)

    if extra_reqs:
        if opts.upgrade:
            commands = [
                "{0} --upgrade -r {1}".format(pip_command_base, reqfile)
                for reqfile in extra_reqs
            ]
        else:
            commands = [
                "{0} -r {1}".format(pip_command_base, reqfile)
                for reqfile in extra_reqs
            ]

        for cmd in commands:
            LOGGER.info("Installing extra requirements... {}".format(cmd))
            try:
                local(cmd)
            except OSError as ex:
                msg = ("Error running pip install command extra "
                       "requirements install: {}\n{}").format(reqfile, ex)
                LOGGER.error(msg)
                sys.exit(1)

    # setup for development
    if opts.nosetupdevelop:
        msg = "skipping python setup.py develop..."
        LOGGER.info(msg)
    else:
        LOGGER.info('running python setup.py develop...')
        activate = activate_command(venv_path)
        local('{} && python setup.py develop'.format(activate))
Ejemplo n.º 20
0
def new_release(opts):
    """
    _new_release_

    - Create a new release branch in the local repo
    - Edit the conf to bump the version
    - Edit the history file with release notes

    """
    LOGGER.info("Creating new release...")
    if not highlander([opts.major, opts.minor, opts.micro]):
        msg = "Can only specify one of --major, --minor or --micro"
        LOGGER.error(msg)
        raise RuntimeError(msg)

    fields = ['major', 'minor', 'micro']
    mask = [opts.major, opts.minor, opts.micro]
    field = [x for x in itertools.compress(fields, mask)][0]

    config = load_configuration()

    # version bump:
    current_version = config.package_version()
    new_version = bump_version_field(current_version, field)

    # release branch
    branch_name = "{0}{1}".format(config.gitflow_release_prefix(), new_version)
    LOGGER.info('release branch is {0}'.format(branch_name))

    # need to be on the latest develop
    repo_dir = repo_directory()
    # make sure the branch doesnt already exist on remote
    if remote_branch_exists(repo_dir, branch_name):
        msg = ("Error: branch {branch_name} already exists on the remote repo "
               "Please clean up that branch before proceeding\n"
               "git branch -d {branch_name}\n"
               "git push origin --delete {branch_name}\n").format(
                   branch_name=branch_name)
        LOGGER.error(msg)
        raise RuntimeError(msg)

    # make sure repo is clean
    if has_unstaged_changes(repo_dir):
        msg = ("Error: Unstaged changes are present on the branch "
               "Please commit them or clean up before proceeding")
        LOGGER.error(msg)
        raise RuntimeError(msg)

    main_branch = config.gitflow_branch_name()
    checkout_and_pull(repo_dir, main_branch, pull=not opts.no_remote)

    # create release branch
    branch(repo_dir, branch_name, main_branch)

    # update cirrus conf
    config.update_package_version(new_version)
    changes = ['cirrus.conf']

    if opts.bump:
        reqs_file = os.path.join(repo_dir, 'requirements.txt')
        for pkg, version in opts.bump:
            LOGGER.info("Bumping dependency {} to {}".format(pkg, version))
            bump_package(reqs_file, pkg, version)
        changes.append(reqs_file)

    # update release notes file
    relnotes_file, relnotes_sentinel = config.release_notes()
    if (relnotes_file is not None) and (relnotes_sentinel is not None):
        LOGGER.info('Updating release notes in {0}'.format(relnotes_file))
        relnotes = "Release: {0} Created: {1}\n".format(
            new_version,
            datetime.datetime.utcnow().isoformat())
        relnotes += build_release_notes(repo_dir, current_version,
                                        config.release_notes_format())
        update_file(relnotes_file, relnotes_sentinel, relnotes)
        changes.append(relnotes_file)

    # update __version__ or equivalent
    version_file, version_attr = config.version_file()
    if version_file is not None:
        LOGGER.info('Updating {0} attribute in {1}'.format(
            version_file, version_attr))
        update_version(version_file, new_version, version_attr)
        changes.append(version_file)

    # update files changed
    msg = "cirrus release: new release created for {0}".format(branch_name)
    LOGGER.info('Committing files: {0}'.format(','.join(changes)))
    LOGGER.info(msg)
    commit_files_optional_push(repo_dir, msg, not opts.no_remote, *changes)
    return (new_version, field)
Ejemplo n.º 21
0
def release_status(release):
    """
    given a release branch name or tag, look at the status
    of that release based on git history and attempt to
    check wether it has been fully merged or tagged.

    returns True if the release looks to be successfully merged and tagged

    """
    result = False
    with GitHubContext(repo_directory()) as ghc:
        LOGGER.info("Checking release status for {}".format(release))
        # work out the branch and tag for the release

        rel_pfix = ghc.config.gitflow_release_prefix()
        develop_branch = ghc.config.gitflow_branch_name()
        master_branch = ghc.config.gitflow_master_name()
        origin_name = ghc.config.gitflow_origin_name()

        if release in (develop_branch, master_branch):
            unmerged = ghc.unmerged_releases()
            msg = (
                "On Develop or Master Branch {}, "
                "checking for unmerged releases...\n"
            ).format(release)
            if unmerged:
                msg += (
                    "Found the following unmerged "
                    "releases:\n{}\n"
                ).format('\n '.join(unmerged))
            else:
                msg += "No unmerged releases found.\n"
            msg += (
                "Please checkout a release branch and re run this command"
                " for more details about a specific release"
            )
            LOGGER.info(msg)
            return False

        if not release.startswith(rel_pfix):
            msg = (
                "Branch {release} doesnt look like a release branch\n"
                "Please checkout the release branch you want to check status of"
            ).format(release=release)
            LOGGER.error(msg)
            return False

        if rel_pfix in release:
            release_tag = release.split(rel_pfix)[1]
            release_branch = release
        else:
            release_branch = "{}{}".format(rel_pfix, release)
            release_tag = release

        LOGGER.info("Checking: branch={} tag={}".format(release_branch, release_tag))
        branch_commit = ghc.find_release_commit(release_branch)
        tag_commit = ghc.find_release_commit(release_tag)
        LOGGER.info("Resolved Commits: branch={} tag={}".format(branch_commit, tag_commit))

        # handles caser where tag or release is not present, eg typo
        if (not tag_commit) and (not branch_commit):
            msg = (
                "Unable to find any branch or tag commits "
                "for release \'{}\'\n"
                "Are you sure this is a valid release?"
            ).format(release)
            LOGGER.error(msg)
            return False

        # check the tag commit is present on master and remote master
        tag_present = False
        if tag_commit:
            branches = ghc.commit_on_branches(tag_commit)
            remote_master = "remotes/{}/{}".format(origin_name, master_branch)
            on_master = master_branch in branches
            on_origin = remote_master in branches
            if on_master:
                LOGGER.info("Tag is present on local master {}...".format(master_branch))
                tag_present = True
            if on_origin:
                LOGGER.info("Tag is present on remote master {}...".format(remote_master))
                tag_present = True

        # look for common merge base containing the release name for master
        # and develop
        develop_merge = ghc.merge_base(release_tag, develop_branch)
        master_merge = ghc.merge_base(release_tag, master_branch)
        merge_on_develop = False
        merge_on_master = False
        if develop_merge:
            merge_on_develop = release_branch in ghc.git_show_commit(develop_merge)
        if master_merge:
            merge_on_master = release_branch in ghc.git_show_commit(master_merge)

        if merge_on_develop:
            LOGGER.info("Merge of {} is on {}".format(release_branch, develop_branch))
        else:
            LOGGER.info("Merge of {} not found on {}".format(release_branch, develop_branch))
        if merge_on_master:
            LOGGER.info("Merge of {} is on {}".format(release_branch, master_branch))
        else:
            LOGGER.info("Merge of {} not found on {}".format(release_branch, master_branch))

        if not all([tag_present, merge_on_develop, merge_on_master]):
            msg = (
                "\nRelease branch {} was not found either as a tag or merge "
                "commit on develop branch: {} or master branch: {} branches\n"
                "This may mean that the release is still running on a CI platform or "
                "has errored out. \n"
                " => Tag Present: {}\n"
                " => Merged to develop: {}\n"
                " => Merged to master: {}\n"
                "\nFor troubleshooting please see: "
                "https://github.com/evansde77/cirrus/wiki/Troubleshooting#release\n"
            ).format(
                release_branch,
                develop_branch,
                master_branch,
                tag_present,
                merge_on_develop,
                merge_on_master
            )
            LOGGER.error(msg)
            result = False
        else:
            msg = "Release {} looks to be successfully merged and tagged\n".format(release_branch)
            LOGGER.info(msg)
            result = True
    return result
Ejemplo n.º 22
0
def release_status(release):
    """
    given a release branch name or tag, look at the status
    of that release based on git history and attempt to
    check wether it has been fully merged or tagged.

    returns True if the release looks to be successfully merged and tagged

    """
    result = False
    with GitHubContext(repo_directory()) as ghc:
        LOGGER.info("Checking release status for {}".format(release))
        # work out the branch and tag for the release

        rel_pfix = ghc.config.gitflow_release_prefix()
        develop_branch = ghc.config.gitflow_branch_name()
        master_branch = ghc.config.gitflow_master_name()
        origin_name = ghc.config.gitflow_origin_name()
        if rel_pfix in release:
            release_tag = release.split(rel_pfix)[1]
            release_branch = release
        else:
            release_branch = "{}{}".format(rel_pfix, release)
            release_tag = release

        LOGGER.info("Checking: branch={} tag={}".format(
            release_branch, release_tag))
        branch_commit = ghc.find_release_commit(release_branch)
        tag_commit = ghc.find_release_commit(release_tag)
        LOGGER.info("Resolved Commits: branch={} tag={}".format(
            branch_commit, tag_commit))

        # handles caser where tag or release is not present, eg typo
        if (not tag_commit) and (not branch_commit):
            msg = ("Unable to find any branch or tag commits "
                   "for release \'{}\'\n"
                   "Are you sure this is a valid release?").format(release)
            LOGGER.error(msg)
            return False

        # check the tag commit is present on master and remote master
        tag_present = False
        if tag_commit:
            branches = ghc.commit_on_branches(tag_commit)
            remote_master = "remotes/{}/{}".format(origin_name, master_branch)
            on_master = master_branch in branches
            on_origin = remote_master in branches
            if on_master:
                LOGGER.info("Tag is present on local master {}...".format(
                    master_branch))
                tag_present = True
            if on_origin:
                LOGGER.info("Tag is present on remote master {}...".format(
                    remote_master))
                tag_present = True

        # look for common merge base containing the release name for master
        # and develop
        develop_merge = ghc.merge_base(release_tag, develop_branch)
        master_merge = ghc.merge_base(release_tag, master_branch)
        merge_on_develop = False
        merge_on_master = False
        if develop_merge:
            merge_on_develop = release_branch in ghc.git_show_commit(
                develop_merge)
        if master_merge:
            merge_on_master = release_branch in ghc.git_show_commit(
                master_merge)

        if merge_on_develop:
            LOGGER.info("Merge of {} is on {}".format(release_branch,
                                                      develop_branch))
        else:
            LOGGER.info("Merge of {} not found on {}".format(
                release_branch, develop_branch))
        if merge_on_master:
            LOGGER.info("Merge of {} is on {}".format(release_branch,
                                                      master_branch))
        else:
            LOGGER.info("Merge of {} not found on {}".format(
                release_branch, master_branch))

        if not all([tag_present, merge_on_develop, merge_on_master]):
            msg = (
                "\nRelease branch {} was not found either as a tag or merge "
                "commit on develop branch: {} or master branch: {} branches\n"
                "This may mean that the release is still running on a CI platform or "
                "has errored out. \n"
                " => Tag Present: {}\n"
                " => Merged to develop: {}\n"
                " => Merged to master: {}\n"
                "\nFor troubleshooting please see: "
                "https://github.com/evansde77/cirrus/wiki/Troubleshooting#release\n"
            ).format(release_branch, develop_branch, master_branch,
                     tag_present, merge_on_develop, merge_on_master)
            LOGGER.error(msg)
            result = False
        else:
            msg = "Release {} looks to be successfully merged and tagged\n".format(
                release_branch)
            LOGGER.info(msg)
            result = True
    return result