コード例 #1
0
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']))
コード例 #2
0
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
コード例 #3
0
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!')
コード例 #4
0
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))
コード例 #5
0
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)
コード例 #6
0
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))
コード例 #7
0
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!')
コード例 #8
0
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
コード例 #9
0
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)
コード例 #10
0
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)
コード例 #11
0
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)
コード例 #12
0
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)
コード例 #13
0
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
コード例 #14
0
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))
コード例 #15
0
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
コード例 #16
0
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))
コード例 #17
0
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))
コード例 #18
0
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))
コード例 #19
0
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
コード例 #20
0
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
コード例 #21
0
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")
コード例 #22
0
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?')
コード例 #23
0
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!')
コード例 #24
0
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!')
コード例 #25
0
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"
    )
コード例 #26
0
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!')
コード例 #27
0
    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
コード例 #28
0
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!')