Esempio n. 1
0
    def test_checkout_and_pull(self):
        """
        _test_checkout_and_pull_
        """
        mock_remote = mock.Mock()
        mock_remote.name = 'origin'
        mock_remote.pull = mock.Mock()

        class Remotes(list):
            def __init__(self, m):
                self.append(m)

            def __getattr__(self, name):
                return self[0]

        self.mock_repo.remotes = Remotes(mock_remote)
        checkout_and_pull(None, 'master')
        self.failUnless(self.mock_git.Repo.called)
Esempio n. 2
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 = os.getcwd()
    checkout_and_pull(repo_dir, config.gitflow_branch_name())
    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 opts.push:
        push(repo_dir)
        LOGGER.info("Branch {0} pushed to remote".format(branch_name))
Esempio n. 3
0
    def test_checkout_and_pull_no_remote(self):
        """
        _test_checkout_and_pull_
        """
        mock_remote = mock.Mock()
        mock_remote.name = 'origin'
        mock_remote.pull = mock.Mock()

        class Remotes(list):
            def __init__(self, m):
                self.append(m)

            def __getattr__(self, name):
                return self[0]

        self.mock_repo.remotes = Remotes(mock_remote)
        self.mock_repo.git = mock.Mock()
        self.mock_repo.git.branch = mock.Mock(
            return_value="develop master remotes/origin/develop")
        checkout_and_pull(None, 'master')
        self.failUnless(self.mock_git.Repo.called)
        self.failUnless(not mock_remote.pull.called)
Esempio n. 4
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))
Esempio n. 5
0
    def test_checkout_and_pull_no_remote(self):
        """
        _test_checkout_and_pull_
        """
        mock_remote = mock.Mock()
        mock_remote.name = 'origin'
        mock_remote.pull = mock.Mock()

        class Remotes(list):
            def __init__(self, m):
                self.append(m)

            def __getattr__(self, name):
                return self[0]

        self.mock_repo.remotes = Remotes(mock_remote)
        self.mock_repo.git = mock.Mock()
        self.mock_repo.git.branch = mock.Mock(
            return_value="develop master remotes/origin/develop"
        )
        checkout_and_pull(None, 'master')
        self.failUnless(self.mock_git.Repo.called)
        self.failUnless(not mock_remote.pull.called)
Esempio n. 6
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))
Esempio n. 7
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))
Esempio n. 8
0
def init_container(opts):
    """
    Initialise a basic container-template setup
    for this package
    """
    cirrus_conf = os.path.join(opts.repo, 'cirrus.conf')
    if not os.path.exists(cirrus_conf):
        msg = "No cirrus.conf found, need to init repo first?"
        LOGGER.error(msg)
        sys.exit(1)

    config = load_configuration(opts.repo)
    print "cirrus_conf=", cirrus_conf
    template_dir = os.path.join(opts.repo, opts.template_dir)
    if not os.path.exists(template_dir):
        LOGGER.info("Creating Template in {}".format(template_dir))
        os.makedirs(template_dir)

    docker_file = os.path.join(template_dir, 'Dockerfile.mustache')
    dotfile = os.path.join(template_dir, '.dockerstache')
    pre_script = os.path.join(template_dir, 'pre_script.sh')
    post_script = os.path.join(template_dir, 'post_script.sh')
    context = os.path.join(template_dir, 'context.json')
    local_install = os.path.join(template_dir, 'local_pip_install.sh.mustache')
    pypi_install = os.path.join(template_dir, 'pypi_pip_install.sh.mustache')
    opts.context_file = os.path.join(opts.template_dir, 'context.json')

    # make sure repo is clean
    if has_unstaged_changes(opts.repo):
        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()
    LOGGER.info("checking out latest {} branch...".format(main_branch))
    checkout_and_pull(opts.repo, main_branch, not opts.no_remote)

    venv_option = ""
    if opts.virtualenv:
        venv_option = ". {}/bin/activate".format(opts.virtualenv)

    with working_dir(template_dir):
        write_basic_dockerfile(opts, config, docker_file)
        write_json_file(dotfile, {
            "post_script": "post_script.sh",
            "pre_script": "pre_script.sh"
        })
        write_json_file(context, {})
        write_script(pre_script, DOCKER_PRE_SCRIPT)
        write_script(local_install,
                     LOCAL_INSTALL_SCRIPT,
                     virtualenv=venv_option)
        write_script(
            pypi_install,
            PYPI_INSTALL_SCRIPT,
            virtualenv=venv_option,
            pip_options=config.pip_options() if config.pip_options() else "")
        if opts.local_install:
            write_script(post_script,
                         DOCKER_POST_SCRIPT,
                         copy_dist=LOCAL_INSTALL_COMMAND.format(
                             package=config.package_name()))
        else:
            write_script(post_script, DOCKER_POST_SCRIPT, copy_dist="")
        edit_cirrus_conf(opts, config)

        modified = [
            cirrus_conf, docker_file, dotfile, pre_script, post_script,
            local_install, pypi_install, context
        ]
        LOGGER.info("commiting changes...")
        commit_files_optional_push(opts.repo,
                                   "git cirrus package container-init",
                                   not opts.no_remote, *modified)
Esempio n. 9
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)
Esempio n. 10
0
 def test_checkout_and_pull(self):
     """
     _test_checkout_and_pull_
     """
     checkout_and_pull(None, 'master')
     self.failUnless(self.mock_git.Repo.called)
Esempio n. 11
0
def init_container(opts):
    """
    Initialise a basic container-template setup
    for this package
    """
    cirrus_conf = os.path.join(opts.repo, 'cirrus.conf')
    if not os.path.exists(cirrus_conf):
        msg = "No cirrus.conf found, need to init repo first?"
        LOGGER.error(msg)
        sys.exit(1)

    config = load_configuration(opts.repo)
    template_dir = os.path.join(opts.repo, opts.template_dir)
    if not os.path.exists(template_dir):
        LOGGER.info("Creating Template in {}".format(template_dir))
        os.makedirs(template_dir)

    docker_file = os.path.join(template_dir, 'Dockerfile.mustache')
    dotfile = os.path.join(template_dir, '.dockerstache')
    pre_script = os.path.join(template_dir, 'pre_script.sh')
    post_script = os.path.join(template_dir, 'post_script.sh')
    context = os.path.join(template_dir, 'context.json')
    installer_script = os.path.join(template_dir, 'install_script.sh.mustache')
    opts.context_file = os.path.join(opts.template_dir, 'context.json')

    # make sure repo is clean
    if has_unstaged_changes(opts.repo):
        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()
    LOGGER.info("checking out latest {} branch...".format(main_branch))
    checkout_and_pull(opts.repo, main_branch, not opts.no_remote)

    venv_option = ""
    if opts.virtualenv:
        venv_option = ". {}/bin/activate".format(opts.virtualenv)

    with working_dir(template_dir):
        write_basic_dockerfile(opts, config, docker_file)
        write_json_file(
            dotfile, {
                "post_script": "post_script.sh",
                "pre_script": "pre_script.sh",
                "inclusive": True,
                "excludes":
                ["post_script.sh", "post_script.sh", ".dockerstache"]
            })
        write_json_file(context, {})

        # render templates for container scripts
        template_context = {
            'open_brace': '{{',
            'close_brace': '}}',
            'package': config.package_name(),
            'virtualenv': venv_option,
            'pip_options': config.pip_options() if config.pip_options() else ""
        }

        install_template = find_template('install_script.sh.mustache')
        pre_template = find_template('pre_script.sh.mustache')
        post_template = find_template('post_script.sh.mustache')

        renderer = pystache.Renderer()
        install_result = renderer.render_path(install_template,
                                              template_context)

        with open(installer_script, 'w') as handle:
            handle.write(install_result)

        post_result = renderer.render_path(post_template, template_context)
        with open(post_script, 'w') as handle:
            handle.write(post_result)

        pre_result = renderer.render_path(pre_template, template_context)
        with open(pre_script, 'w') as handle:
            handle.write(pre_result)

        make_executable(pre_script, opts.repo)
        make_executable(post_script, opts.repo)
        make_executable(installer_script, opts.repo)

        edit_cirrus_conf(opts, config)

        modified = [
            cirrus_conf, docker_file, dotfile, pre_script, post_script,
            installer_script, context
        ]
        LOGGER.info("commiting changes...")
        commit_files_optional_push(opts.repo,
                                   "git cirrus package container-init",
                                   not opts.no_remote, *modified)
Esempio n. 12
0
def init_container(opts):
    """
    Initialise a basic container-template setup
    for this package
    """
    cirrus_conf = os.path.join(opts.repo, 'cirrus.conf')
    if not os.path.exists(cirrus_conf):
        msg = "No cirrus.conf found, need to init repo first?"
        LOGGER.error(msg)
        sys.exit(1)

    config = load_configuration(opts.repo)
    template_dir = os.path.join(opts.repo, opts.template_dir)
    if not os.path.exists(template_dir):
        LOGGER.info("Creating Template in {}".format(template_dir))
        os.makedirs(template_dir)

    docker_file = os.path.join(template_dir, 'Dockerfile.mustache')
    dotfile = os.path.join(template_dir, '.dockerstache')
    pre_script = os.path.join(template_dir, 'pre_script.sh')
    post_script = os.path.join(template_dir, 'post_script.sh')
    context = os.path.join(template_dir, 'context.json')
    installer_script = os.path.join(template_dir, 'install_script.sh.mustache')
    opts.context_file = os.path.join(opts.template_dir, 'context.json')

     # make sure repo is clean
    if has_unstaged_changes(opts.repo):
        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()
    LOGGER.info("checking out latest {} branch...".format(main_branch))
    checkout_and_pull(opts.repo,  main_branch, not opts.no_remote)

    venv_option = ""
    if opts.virtualenv:
        venv_option = ". {}/bin/activate".format(opts.virtualenv)

    with working_dir(template_dir):
        write_basic_dockerfile(opts, config, docker_file)
        write_json_file(dotfile, {
            "post_script": "post_script.sh",
            "pre_script": "pre_script.sh",
            "inclusive": True,
            "excludes": ["post_script.sh", "post_script.sh", ".dockerstache"]
        })
        write_json_file(context, {})

        # render templates for container scripts
        template_context = {
            'open_brace': '{{',
            'close_brace': '}}',
            'package': config.package_name(),
            'virtualenv': venv_option,
            'pip_options': config.pip_options() if config.pip_options() else ""
        }

        install_template = find_template('install_script.sh.mustache')
        pre_template = find_template('pre_script.sh.mustache')
        post_template = find_template('post_script.sh.mustache')

        renderer = pystache.Renderer()
        install_result = renderer.render_path(install_template, template_context)

        with open(installer_script, 'w') as handle:
            handle.write(install_result)

        post_result = renderer.render_path(post_template, template_context)
        with open(post_script, 'w') as handle:
            handle.write(post_result)

        pre_result = renderer.render_path(pre_template, template_context)
        with open(pre_script, 'w') as handle:
            handle.write(pre_result)

        make_executable(pre_script, opts.repo)
        make_executable(post_script, opts.repo)
        make_executable(installer_script, opts.repo)

        edit_cirrus_conf(opts, config)

        modified = [
            cirrus_conf,
            docker_file,
            dotfile,
            pre_script,
            post_script,
            installer_script,
            context
        ]
        LOGGER.info("commiting changes...")
        commit_files_optional_push(
            opts.repo,
            "git cirrus package container-init",
            not opts.no_remote,
            *modified
        )