def create_pull_request(repo_name, from_branch, target_branch, token): r = post_content( '{}/repos/{}/{}/pulls'.format(consts.GH_API_URL, consts.ORGANIZATION, repo_name), token, { 'title': '[release] merging {} into {}'.format(from_branch, target_branch), 'body': 'cc @GuillaumeGomez @EPashkin @sdroege', 'base': target_branch, 'head': from_branch, 'maintainer_can_modify': True }) if r is None: write_error( "Pull request from {repo}/{from_b} to {repo}/{target} couldn't be created. You " "need to do it yourself... (url provided at the end)".format( repo=repo_name, from_b=from_branch, target=target_branch)) input("Press ENTER once done to continue...") PULL_REQUESTS.append('|=> "{}/{}/{}/compare/{}...{}?expand=1"'.format( consts.GITHUB_URL, consts.ORGANIZATION, repo_name, target_branch, from_branch)) else: write_msg("===> Pull request created: {}".format(r['html_url'])) PULL_REQUESTS.append('> {}'.format(r['html_url']))
def update_crate_version(repo_name, crate_name, crate_dir_path, temp_dir, specified_crate): file_path = join(join(join(temp_dir, repo_name), crate_dir_path), "Cargo.toml") output = file_path.replace(temp_dir, "") if output.startswith('/'): output = output[1:] write_msg('=> Updating crate versions for {}'.format(file_path)) content = get_file_content(file_path) if content is None: return False toml = TomlHandler(content) for section in toml.sections: if section.name == 'package': section.set('version', CRATES_VERSION[crate_name]) elif specified_crate is not None: continue elif section.name.startswith('dependencies.') and find_crate( section.name[13:]): if specified_crate is None and section.name[ 13:] not in CRATES_VERSION: input( '"{}" dependency not found in versions for crate "{}"...'. format(section.name[13:], crate_name)) continue section.set('version', CRATES_VERSION[section.name[13:]]) elif section.name == 'dependencies': for entry in section.entries: if find_crate(entry['key']): section.set(entry['key'], CRATES_VERSION[entry['key']]) result = write_into_file(file_path, str(toml)) write_msg('=> {}: {}'.format( output.split(os_sep)[-2], 'Failure' if result is False else 'Success')) return result
def generate_tags_and_version_branches(args, temp_dir, repositories): if args.no_push is True or args.doc_only is True or args.badges_only is True: return write_msg("=> Generating tags and branches...") for repo in repositories: generate_new_tag(repo, temp_dir, args.specified_crate, args) generate_new_branches(repo, temp_dir, args.specified_crate, args) write_msg('Done!')
def get_answer(text): while True: text = input('{} [Y/n] '.format(text)).strip().lower() if len(text) == 0 or text == 'y': return True if text == 'n': return False write_msg('-> Invalid answer "{}": only "Y" and "n" are expected'.format(text))
def main(argv): args = Arguments.parse_arguments(argv) if args is None: sys.exit(1) if check_rustdoc_is_nightly() is False: return if check_if_up_to_date() is False: return write_msg('=> Creating temporary directory...') with temporary_directory() as temp_dir: write_msg('Temporary directory created in "{}"'.format(temp_dir)) start(args, temp_dir)
def publish_crate(repository, crate_dir_path, temp_dir, crate_name): write_msg('=> publishing crate {}'.format(crate_name)) path = join(join(temp_dir, repository), crate_dir_path) # In case we needed to fix bugs, we checkout to crate branch before publishing crate. command = [ 'bash', '-c', 'cd {} && git checkout crate && cargo publish'.format(path) ] if not exec_command_and_print_error(command): input( "Something bad happened! Try to fix it and then press ENTER to continue..." ) write_msg('> crate {} has been published'.format(crate_name))
def update_gtk_rs_blog(args, temp_dir): if args.doc_only is True or args.tags_only is True: return write_msg('=> Updating blog...') if update_badges(consts.BLOG_REPO, temp_dir, args.specified_crate) is False: write_error("Error when trying to update badges...") elif args.no_push is False: commit_and_push(consts.BLOG_REPO, temp_dir, "Update versions", consts.MASTER_TMP_BRANCH) create_pull_request(consts.BLOG_REPO, consts.MASTER_TMP_BRANCH, "master", args.token) write_msg('Done!')
def update_repo_version(repo_name, crate_name, crate_dir_path, temp_dir, update_type, badges_only): file_path = join(join(join(temp_dir, repo_name), crate_dir_path), "Cargo.toml") output = file_path.replace(temp_dir, "") if output.startswith('/'): output = output[1:] write_msg('=> Updating versions for {}'.format(file_path)) content = get_file_content(file_path) if content is None: return False toml = TomlHandler(content) versions_update = [] for section in toml.sections: if (section.name == 'package' or (section.name.startswith('dependencies.') and find_crate(section.name[13:]))): version = section.get('version', None) if version is None: continue new_version = None if badges_only is False: new_version = update_version(version, update_type, section.name) else: new_version = version if new_version is None: return False # Print the status directly if it's the crate's version. if section.name == 'package': write_msg('\t{}: {} => {}'.format( output.split(os_sep)[-2], version, new_version)) CRATES_VERSION[crate_name] = new_version else: # Otherwise add it to the list to print later. versions_update.append({ 'dependency_name': section.name[13:], 'old_version': version, 'new_version': new_version }) section.set('version', new_version) elif section.name == 'dependencies': for entry in section.entries: if find_crate(entry): new_version = check_and_update_version( section.entries[entry], update_type, entry) section.set(entry, new_version) for up in versions_update: write_msg('\t{}: {} => {}'.format(up['dependency_name'], up['old_version'], up['new_version'])) out = str(toml) if not out.endswith("\n"): out += '\n' result = True if badges_only is False: # We only write into the file if we're not just getting the crates version. result = write_into_file(file_path, out) write_msg('=> {}: {}'.format( output.split(os_sep)[-2], 'Failure' if result is False else 'Success')) return result
def generate_new_tag(repository, temp_dir, specified_crate): versions = {} version = None # In some repositories (like sys), there are more than one crates. In such case, we try to # get the most common version number and then we create the tag from there. # # First, we get all versions. for crate in consts.CRATE_LIST: if crate['repository'] == repository: versions[crate['crate']] = CRATES_VERSION[crate['crate']] if crate['crate'].endswith('-sys') or crate['crate'].endswith( '-sys-rs'): version = CRATES_VERSION[crate['crate']] if (specified_crate is not None and (specified_crate.endswith('-sys') or specified_crate.endswith('-sys-rs'))): write_msg( 'Seems like "{}" is part of a repository with multiple crates so no \ tag generation this time...'.format(specified_crate)) return if version is None: most_common = {} # Now we get how many crates have this version. for version in versions: if versions[version] in most_common: most_common[versions[version]] += 1 else: most_common[versions[version]] = 1 # Now we get the "lowest" version that will be used as default tag name. for common in most_common: if version is None or compare_versions(common, version) < 0: version = common # And now we get the most common tag name. for common in most_common: if version is None or most_common[version] < most_common[common]: version = common if version is None: write_error( 'Something impossible happened for "{}": no version can be tagged...' .format(repository)) input( 'If you think you can do better, go ahead! (In "{}") Then press ENTER to continue' .format(join(temp_dir, repository))) return write_msg('==> Creating new tag "{}" for repository "{}"...'.format( version, repository)) create_tag_and_push(version, repository, temp_dir)
def main(argv): try: opts, args = getopt.getopt(argv, "ht:m:c:", [ "help", "token=", "mode=", "no-push", "doc-only", "crate", "badges-only" ]) except getopt.GetoptError: write_help() sys.exit(2) token = None mode = None no_push = False doc_only = False specified_crate = None badges_only = False for opt, arg in opts: if opt in ('-h', '--help'): write_help() sys.exit(0) elif opt in ("-t", "--token"): token = arg elif opt in ("-m", "--mode"): mode = UpdateType.create_from_string(arg) if mode is None: write_error( '{}: Invalid update type received. Accepted values: ' '(MINOR|MEDIUM|MAJOR)'.format(opt)) sys.exit(3) elif opt in ("--no-push"): no_push = True elif opt in ("--doc-only"): doc_only = True elif opt in ("--badges-only"): badges_only = True elif opt in ('-c', '--crate'): specified_crate = arg else: write_msg('"{}": unknown option'.format(opt)) write_msg('Use "-h" or "--help" to see help') sys.exit(0) if token is None and no_push is False: write_error('Missing token argument.') sys.exit(4) if mode is None and doc_only is False and badges_only is False: write_error('Missing update type argument.') sys.exit(5) start(mode, token, no_push, doc_only, specified_crate, badges_only)
def generate_new_tag(repository, temp_dir, specified_crate, args): # We make a new tag for every crate: # # * If it is a "sys" crate, then we add its name to the tag # * If not, then we just keep its version number for crate in args.crates: crate = crate['crate'] if crate['repository'] == repository: if specified_crate is not None and crate[ 'crate'] != specified_crate: continue tag_name = CRATES_VERSION[crate['crate']] if crate['crate'].endswith('-sys') or crate['crate'].endswith( '-sys-rs'): tag_name = '{}-{}'.format(crate['crate'], tag_name) write_msg( '==> Creating new tag "{}" for repository "{}"...'.format( tag_name, repository)) create_tag_and_push(tag_name, repository, temp_dir)
def generate_new_branches(repository, temp_dir, specified_crate, args): # We make a new branch for every crate based on the current "crate" branch: # # * If it is a "sys" crate, then we ignore it. # * If not, then we create a new branch for crate in args.crates: crate = crate['crate'] if crate['repository'] == repository: if specified_crate is not None and crate[ 'crate'] != specified_crate: continue if crate['crate'].endswith('-sys') or crate['crate'].endswith( '-sys-rs'): continue branch_name = CRATES_VERSION[crate['crate']] write_msg( '==> Creating new branch "{}" for repository "{}"...'.format( branch_name, repository)) push(repository, temp_dir, branch_name)
def clone_repositories(args, temp_dir): write_msg('=> Cloning the repositories...') repositories = [] for crate in args.crates: crate = crate['crate'] if args.specified_crate is not None and crate[ 'crate'] != args.specified_crate: continue if crate["repository"] not in repositories: repositories.append(crate["repository"]) if clone_repo(crate["repository"], temp_dir) is False: write_error('Cannot clone the "{}" repository...'.format( crate["repository"])) return [] if len(repositories) < 1: write_msg('No crate "{}" found. Aborting...'.format( args.specified_crate)) return [] if args.doc_only is False: if clone_repo(consts.BLOG_REPO, temp_dir, depth=1) is False: write_error('Cannot clone the "{}" repository...'.format( consts.BLOG_REPO)) return [] if clone_repo(consts.DOC_REPO, temp_dir, depth=1) is False: write_error('Cannot clone the "{}" repository...'.format( consts.DOC_REPO)) return [] write_msg('Done!') return repositories
def start(args, temp_dir): repositories = clone_repositories(args, temp_dir) if len(repositories) < 1: return if args.doc_only is False: if (args.blog_only is False and update_crates_versions(args, temp_dir, repositories) is False): return if args.badges_only is False and args.tags_only is False: build_blog_post(repositories, temp_dir, args.token) if args.blog_only: input( "Blog post generated, press ENTER to quit (it'll remove the tmp folder and " "its content!)") return checkout_crate_branches(temp_dir, repositories) if args.doc_only is False and args.badges_only is False and args.tags_only is False: if update_crate_repositories_branches(args, temp_dir, repositories) is False: return if args.no_push is False: publish_crates(args, temp_dir) create_example_repository_pull_request(args) generate_tags_and_version_branches(args, temp_dir, repositories) regenerate_documentation(args, temp_dir, repositories) update_gtk_rs_blog(args, temp_dir) write_msg('Seems like most things are done! Now remains:') write_msg( " * Check generated docs for all crates (don't forget to enable features!)." ) input( 'Press ENTER to leave (once done, the temporary directory "{}" will be destroyed)' .format(temp_dir))
def get_up_type(crate, mode, pick_update_type_for_crates, default_updates): if mode is None and pick_update_type_for_crates is False: return None if is_sys_crate(crate) and default_updates['sys'] is not None: return default_updates['sys'] if not is_sys_crate(crate) and default_updates['non-sys'] is not None: return default_updates['non-sys'] while pick_update_type_for_crates is True: text = input('Which kind of update do you want for "{}"? [MINOR/MEDIUM/MAJOR] ' .format(crate)) text = text.strip().lower() mode = UpdateType.create_from_string(text) if mode is not None: if (is_sys_crate(crate) and get_answer('Do you want to use this release for all other sys crates?')): default_updates['sys'] = mode elif (not is_sys_crate(crate) and get_answer('Do you want to use this release for all other non-sys crates?')): default_updates['non-sys'] = mode break write_msg('Invalid update type received: "{}". Accepted values: (MINOR|MEDIUM|MAJOR)' .format(text)) return mode
def start(update_type, token, no_push, doc_only, specified_crate, badges_only): write_msg('=> Creating temporary directory...') with TemporaryDirectory() as temp_dir: write_msg('Temporary directory created in "{}"'.format(temp_dir)) write_msg('=> Cloning the repositories...') repositories = [] for crate in consts.CRATE_LIST: if specified_crate is not None and crate[ 'crate'] != specified_crate: continue if crate["repository"] not in repositories: repositories.append(crate["repository"]) if clone_repo(crate["repository"], temp_dir) is False: write_error('Cannot clone the "{}" repository...'.format( crate["repository"])) return if len(repositories) < 1: write_msg( 'No crate "{}" found. Aborting...'.format(specified_crate)) return if doc_only is False: if clone_repo(consts.BLOG_REPO, temp_dir, depth=1) is False: write_error('Cannot clone the "{}" repository...'.format( consts.BLOG_REPO)) return if clone_repo(consts.DOC_REPO, temp_dir, depth=1) is False: write_error('Cannot clone the "{}" repository...'.format( consts.DOC_REPO)) return write_msg('Done!') if doc_only is False: write_msg('=> Updating [master] crates version...') for crate in consts.CRATE_LIST: if specified_crate is not None and crate[ 'crate'] != specified_crate: continue if update_repo_version(crate["repository"], crate["crate"], crate["path"], temp_dir, update_type, badges_only) is False: write_error( 'The update for the "{}" crate failed...'.format( crate["crate"])) return write_msg('Done!') if badges_only is False: write_msg('=> Committing{} to the "{}" branch...'.format( " and pushing" if no_push is False else "", consts.MASTER_TMP_BRANCH)) for repo in repositories: commit(repo, temp_dir, "Update versions [ci skip]") if no_push is False: push(repo, temp_dir, consts.MASTER_TMP_BRANCH) write_msg('Done!') if no_push is False: write_msg('=> Creating PRs on master branch...') for repo in repositories: create_pull_request(repo, consts.MASTER_TMP_BRANCH, "master", token) write_msg('Done!') write_msg('=> Building blog post...') build_blog_post(repositories, temp_dir, token) write_msg('Done!') write_msg('=> Checking out "crate" branches') for repo in repositories: checkout_target_branch(repo, temp_dir, "crate") write_msg('Done!') if doc_only is False and badges_only is False: write_msg('=> Merging "master" branches into "crate" branches...') for repo in repositories: merging_branches(repo, temp_dir, "master") write_msg('Done!') write_msg('=> Updating [crate] crates version...') for crate in consts.CRATE_LIST: if specified_crate is not None and crate[ 'crate'] != specified_crate: continue if update_crate_version(crate["repository"], crate["crate"], crate["path"], temp_dir, specified_crate) is False: write_error( 'The update for the "{}" crate failed...'.format( crate["crate"])) return write_msg('Done!') write_msg('=> Committing{} to the "{}" branch...'.format( " and pushing" if no_push is False else "", consts.CRATE_TMP_BRANCH)) for repo in repositories: commit(repo, temp_dir, "Update versions [ci skip]") if no_push is False: push(repo, temp_dir, consts.CRATE_TMP_BRANCH) write_msg('Done!') if no_push is False: write_msg('=> Creating PRs on crate branch...') for repo in repositories: create_pull_request(repo, consts.CRATE_TMP_BRANCH, "crate", token) write_msg('Done!') write_msg('+++++++++++++++') write_msg('++ IMPORTANT ++') write_msg('+++++++++++++++') write_msg( 'Almost everything has been done. Take a deep breath, check for opened ' 'pull requests and once done, we can move forward!') write_msg("\n{}\n".format('\n'.join(PULL_REQUESTS))) PULL_REQUESTS.append('=============') input('Press ENTER to continue...') write_msg('=> Publishing crates...') for crate in consts.CRATE_LIST: if specified_crate is not None and crate[ 'crate'] != specified_crate: continue publish_crate(crate["repository"], crate["path"], temp_dir, crate['crate']) write_msg('Done!') write_msg('=> Creating PR for examples repository') create_pull_request("examples", "pending", "master", token) write_msg('Done!') write_msg("=> Generating tags...") for repo in repositories: generate_new_tag(repo, temp_dir, specified_crate) write_msg('Done!') if badges_only is False: write_msg( '=> Preparing doc repo (too much dark magic in here urg)...') cleanup_doc_repo(temp_dir) write_msg('Done!') write_msg('=> Building docs...') for repo in repositories: if repo != "sys": # Maybe we should generate docs for sys crates as well? write_msg('-> Building docs for {}...'.format(repo)) build_docs(repo, temp_dir) end_docs_build(temp_dir) write_msg('Done!') write_msg('=> Committing{} docs to the "{}" branch...'.format( " and pushing" if no_push is False else "", consts.CRATE_TMP_BRANCH)) commit(consts.DOC_REPO, temp_dir, "Regen docs") if no_push is False: push(consts.DOC_REPO, temp_dir, consts.CRATE_TMP_BRANCH) create_pull_request(consts.DOC_REPO, consts.CRATE_TMP_BRANCH, "gh-pages", token) write_msg("New pull request(s):\n\n{}\n".format( '\n'.join(PULL_REQUESTS))) write_msg('Done!') if doc_only is False: write_msg('=> Updating blog...') if update_badges(consts.BLOG_REPO, temp_dir, specified_crate) is False: write_error("Error when trying to update badges...") elif no_push is False: commit_and_push(consts.BLOG_REPO, temp_dir, "Update versions", consts.MASTER_TMP_BRANCH) create_pull_request(consts.BLOG_REPO, consts.MASTER_TMP_BRANCH, "master", token) write_msg('Done!') write_msg('Seems like most things are done! Now remains:') write_msg( " * Check generated docs for all crates (don't forget to enable features!)." ) input( 'Press ENTER to leave (once done, the temporary directory "{}" will be destroyed)' .format(temp_dir))
def update_doc_content_repository(repositories, temp_dir, token, no_push, args): if clone_repo(consts.DOC_CONTENT_REPO, temp_dir) is False: input('Try to fix the problem then press ENTER to continue...') write_msg("Done!") repo_path = join(temp_dir, consts.DOC_CONTENT_REPO) write_msg("=> Generating documentation for crates...") for repo in repositories: current = None for crate in args.crates: crate = crate['crate'] if crate['repository'] == repo: current = crate break if current is None: input( 'No repository matches "{}", something is weird. (Press ENTER TO CONTINUE)' ) continue if current.get("doc", True) is False: continue write_msg('==> Generating documentation for "{}"'.format(current)) path = join(temp_dir, current['repository']) command = [ 'bash', '-c', 'cd {} && make doc && mv vendor.md {}'.format( path, join(repo_path, current['crate'])) ] if not exec_command_and_print_error(command): input("Fix the error and then press ENTER") write_msg('Done!') write_msg('Committing "{}" changes...'.format(consts.DOC_CONTENT_REPO)) commit(consts.DOC_CONTENT_REPO, temp_dir, "Update vendor files") if no_push is False: push(consts.DOC_CONTENT_REPO, temp_dir, consts.MASTER_TMP_BRANCH) # We always make minor releases in here, no need for a more important one considering we don't # change the API. if update_repo_version(consts.DOC_CONTENT_REPO, consts.DOC_CONTENT_REPO, "", temp_dir, UpdateType.MINOR, False) is False: write_error('The update for the "{}" crate failed...'.format( consts.DOC_CONTENT_REPO)) input('Fix the error and then press ENTER') commit(consts.DOC_CONTENT_REPO, temp_dir, "Update version") if no_push is False: push(consts.DOC_CONTENT_REPO, temp_dir, consts.MASTER_TMP_BRANCH) create_pull_request(consts.DOC_CONTENT_REPO, consts.MASTER_TMP_BRANCH, "master", token, False) input(( 'All done with the "{}" update: please merge the PR then press ENTER so the ' 'publication can performed...').format(consts.DOC_CONTENT_REPO)) publish_crate(consts.DOC_CONTENT_REPO, "", temp_dir, consts.DOC_CONTENT_REPO, checkout_branch='master') write_msg('Ok all done! We can move forward now!') else: write_msg(( 'All with "{}", you still need to publish a new version if you want the changes ' 'to be taken into account').format(consts.DOC_CONTENT_REPO))
def build_blog_post(repositories, temp_dir, token): content = '''--- layout: post author: {} title: {} categories: [front, crates] date: {} --- * Write intro here * ### Changes For the interested ones, here is the list of the (major) changes: '''.format(input('Enter author name: '), input('Enter title: '), time.strftime("%Y-%m-%d %H:00:00 +0000")) contributors = [] git = Github(token) oldest_date = None for repo in repositories: checkout_target_branch(repo, temp_dir, "crate") success, out, err = get_last_commit_date(repo, temp_dir) if not success: write_msg("Couldn't get PRs for '{}': {}".format(repo, err)) continue max_date = datetime.date.fromtimestamp(int(out)) if oldest_date is None or max_date < oldest_date: oldest_date = max_date write_msg("Gettings merged PRs from {}...".format(repo)) merged_prs = git.get_pulls(repo, consts.ORGANIZATION, 'closed', max_date, only_merged=True) write_msg("=> Got {} merged PRs".format(len(merged_prs))) if len(merged_prs) < 1: continue repo_url = '{}/{}/{}'.format(consts.GITHUB_URL, consts.ORGANIZATION, repo) content += '[{}]({}):\n\n'.format(repo, repo_url) content += write_merged_prs(merged_prs, contributors, repo_url) write_msg("Gettings merged PRs from gir...") merged_prs = git.get_pulls('gir', consts.ORGANIZATION, 'closed', oldest_date, only_merged=True) write_msg("=> Got {} merged PRs".format(len(merged_prs))) if len(merged_prs) > 0: repo_url = '{}/{}/{}'.format(consts.GITHUB_URL, consts.ORGANIZATION, 'gir') content += ( 'All this was possible thanks to the [gtk-rs/gir]({}) project as well:\n\n' .format(repo_url)) content += write_merged_prs(merged_prs, contributors, repo_url) content += 'Thanks to all of our contributors for their (awesome!) work for this release:\n\n' content += '\n'.join([ ' * [@{}]({}/{})'.format(contributor, consts.GITHUB_URL, contributor) for contributor in contributors ]) content += '\n' file_name = join( join(temp_dir, consts.BLOG_REPO), '_posts/{}-new-release.md'.format(time.strftime("%Y-%m-%d"))) try: with open(file_name, 'w') as outfile: outfile.write(content) write_msg('New blog post written into "{}".'.format(file_name)) add_to_commit(consts.BLOG_REPO, temp_dir, [file_name]) commit(consts.BLOG_REPO, temp_dir, "Add new blog post") except Exception as e: write_error('build_blog_post failed: {}'.format(e)) write_msg( '\n=> Here is the blog post content:\n{}\n<='.format(content))
def update_crates_versions(args, temp_dir, repositories): write_msg('=> Updating [master] crates version...') for crate in args.crates: update_type = crate['up-type'] crate = crate['crate'] if args.specified_crate is not None and crate[ 'crate'] != args.specified_crate: continue if update_repo_version(crate["repository"], crate["crate"], crate["path"], temp_dir, update_type, args.badges_only or args.tags_only) is False: write_error('The update for the "{}" crate failed...'.format( crate["crate"])) return False write_msg('Done!') if args.badges_only is False and args.tags_only is False: write_msg('=> Committing{} to the "{}" branch...'.format( " and pushing" if args.no_push is False else "", consts.MASTER_TMP_BRANCH)) for repo in repositories: commit(repo, temp_dir, "Update versions [ci skip]") if args.no_push is False: push(repo, temp_dir, consts.MASTER_TMP_BRANCH) write_msg('Done!') if args.no_push is False: write_msg('=> Creating PRs on master branch...') for repo in repositories: create_pull_request(repo, consts.MASTER_TMP_BRANCH, "master", args.token) write_msg('Done!') return True
def update_crate_repositories_branches(args, temp_dir, repositories): write_msg('=> Merging "master" branches into "crate" branches...') for repo in repositories: merging_branches(repo, temp_dir, "master") write_msg('Done!') write_msg('=> Updating [crate] crates version...') for crate in args.crates: crate = crate['crate'] if args.specified_crate is not None and crate[ 'crate'] != args.specified_crate: continue if update_crate_version(crate["repository"], crate["crate"], crate["path"], temp_dir, args.specified_crate) is False: write_error('The update for the "{}" crate failed...'.format( crate["crate"])) return False write_msg('Done!') write_msg('=> Committing{} to the "{}" branch...'.format( " and pushing" if args.no_push is False else "", consts.CRATE_TMP_BRANCH)) for repo in repositories: commit(repo, temp_dir, "Update versions [ci skip]") if args.no_push is False: push(repo, temp_dir, consts.CRATE_TMP_BRANCH) write_msg('Done!') if args.no_push is False: write_msg('=> Creating PRs on crate branch...') for repo in repositories: create_pull_request(repo, consts.CRATE_TMP_BRANCH, "crate", args.token) write_msg('Done!') return True
def write_help(): write_msg("release.py accepts the following options:") write_msg("") write_msg(" * -h | --help : display this message") write_msg(" * -t <token> | --token=<token> : give the github token") write_msg(" * -m <mode> | --mode=<mode> : give the update type (MINOR|MEDIUM|MAJOR)") write_msg(" * --no-push : performs all operations but doesn't push anything") write_msg(" * --doc-only : only builds documentation") write_msg(" * -c <crate> | --crate=<crate> : only update the given crate (for test purpose" " mainly)") write_msg(" * --badges-only : only update the badges on the website") write_msg(" * --tags-only : only create new tags") write_msg(" * --blog-only : only create blog post") write_msg(" * --pick-crates : add an interactive way to pick crates") write_msg(" * --pick-update-type-for-crates: pick an update type for each crate")
def ask_updates_confirmation(crates): write_msg("Recap' of picked updates:") for crate in crates: write_msg("[{}] => {}".format(crate['crate']['crate'], UpdateType.to_str(crate['up-type']))) return get_answer('Do you agree with this?')
def create_example_repository_pull_request(args): write_msg('=> Creating PR for examples repository') create_pull_request("examples", "pending", "master", args.token) write_msg('Done!')
def regenerate_documentation(args, temp_dir, repositories): if args.badges_only is True or args.tags_only is True: return input( "About to regenerate documentation. Are you sure you want to continue? " + "(Press ENTER to continue)") update_doc_content_repository(repositories, temp_dir, args.token, args.no_push, args) write_msg('=> Preparing doc repo (too much dark magic in here urg)...') cleanup_doc_repo(temp_dir) write_msg('Done!') write_msg('=> Building docs...') for crate in args.crates: crate = crate['crate'] if crate['crate'] == 'gtk-test': continue write_msg('-> Building docs for {}...'.format(crate['crate'])) build_docs(crate['repository'], temp_dir, crate['path'], crate.get('doc_name', crate['crate'])) end_docs_build(temp_dir) write_msg('Done!') write_msg('=> Committing{} docs to the "{}" branch...'.format( " and pushing" if args.no_push is False else "", consts.CRATE_TMP_BRANCH)) commit(consts.DOC_REPO, temp_dir, "Regen docs") if args.no_push is False: push(consts.DOC_REPO, temp_dir, consts.CRATE_TMP_BRANCH) create_pull_request(consts.DOC_REPO, consts.CRATE_TMP_BRANCH, "gh-pages", args.token) write_msg("New pull request(s):\n\n{}\n".format( '\n'.join(PULL_REQUESTS))) write_msg('Done!')
def write_help(): write_msg("release.py accepts the following options:") write_msg("") write_msg(" * -h | --help : display this message") write_msg(" * -t <token> | --token=<token> : give the github token") write_msg( " * -m <mode> | --mode=<mode> : give the update type (MINOR|MEDIUM|MAJOR)" ) write_msg( " * --no-push : performs all operations but doesn't push anything" ) write_msg(" * --doc-only : only builds documentation") write_msg( " * -c <crate> | --crate=<crate> : only update the given crate (for test purpose \ mainly)") write_msg( " * --badges-only : only update the badges on the website" )
def publish_crates(args, temp_dir): write_msg('+++++++++++++++') write_msg('++ IMPORTANT ++') write_msg('+++++++++++++++') write_msg( 'Almost everything has been done. Take a deep breath, check for opened ' 'pull requests and once done, we can move forward!') write_msg("\n{}\n".format('\n'.join(PULL_REQUESTS))) PULL_REQUESTS.append('=============') input('Press ENTER to continue...') write_msg('=> Publishing crates...') for crate in args.crates: crate = crate['crate'] if args.specified_crate is not None and crate[ 'crate'] != args.specified_crate: continue publish_crate(crate["repository"], crate["path"], temp_dir, crate['crate']) write_msg('Done!')
def parse_arguments(argv): # pylint: disable=too-many-branches,too-many-return-statements try: opts = getopt.getopt(argv, "ht:m:c:", ["help", "token=", "mode=", "no-push", "doc-only", "crate", "badges-only", "tags-only", "pick-update-type-for-crates", "pick-crates", "blog-only"])[0] # second argument is "args" except getopt.GetoptError: write_help() return None instance = Arguments() pick_update_type_for_crates = False for opt, arg in opts: if opt in ('-h', '--help'): write_help() return None if opt in ("-t", "--token"): instance.token = arg elif opt in ("-m", "--mode"): instance.mode = UpdateType.create_from_string(arg) if instance.mode is None: write_error('{}: Invalid update type received. Accepted values: ' '(MINOR|MEDIUM|MAJOR)'.format(opt)) return None elif opt == "--no-push": instance.no_push = True elif opt == "--doc-only": instance.doc_only = True elif opt == "--badges-only": instance.badges_only = True elif opt in ('-c', '--crate'): instance.specified_crate = arg elif opt == '--tags-only': instance.tags_only = True elif opt == '--blog-only': instance.blog_only = True elif opt == '--pick-crates': instance.crates = [] elif opt == '--pick-update-type-for-crates': pick_update_type_for_crates = True else: write_msg('"{}": unknown option'.format(opt)) write_msg('Use "-h" or "--help" to see help') return None if instance.token is None and instance.no_push is False and instance.blog_only is False: # In this case, I guess it's not an issue to not have a github token... write_error('Missing token argument.') return None # To make pylint happy. only_checks = (instance.doc_only is False or instance.badges_only is False or instance.tags_only is False or instance.blog_only is False) if (instance.mode is None and only_checks is False and pick_update_type_for_crates is False): write_error('Missing update type argument.') return None default_updates = {"sys": None, "non-sys": None} if len(instance.crates) == 0: for crate in consts.CRATE_LIST: if get_answer('Do you want to include "{}" in this release?') is True: instance.crates.append( { 'up-type': get_up_type(crate['crate'], instance.mode, pick_update_type_for_crates, default_updates), 'crate': crate, }) if ask_updates_confirmation(instance.crates) is False: write_msg('OK! Aborting then!') return None else: instance.crates = [ { 'up-type': get_up_type(crate['crate'], instance.mode, pick_update_type_for_crates, default_updates), 'crate': crate, } for crate in instance.crates] if (pick_update_type_for_crates is True and ask_updates_confirmation(instance.crates) is False): write_msg('OK! Aborting then!') return None return instance
def checkout_crate_branches(temp_dir, repositories): write_msg('=> Checking out "crate" branches') for repo in repositories: checkout_target_branch(repo, temp_dir, "crate") write_msg('Done!')