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)
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))
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))
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)
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)
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)
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 )