Esempio n. 1
0
def install_shell_profile(ctx):
    config.CONFIG_DIR.mkdir(parents=True, exist_ok=True)
    profile = config.CONFIG_DIR / 'profile'
    with open(profile, 'w') as fh:
        fh.write(shell_profile_template)

    todo = actionable('TODO:')
    get_logger().info(f'{todo} Please add the following line to your shell config file, if you haven\'t already ')
    get_logger().info('      done so. The default shell config file is ~/.profile. If you\'re using a')
    get_logger().info('      different shell, e.g. zsh, you may have a different config file, e.g. ~/.zshrc')
    get_logger().info('')
    get_logger().info(actionable('      source %s'), str(profile))
Esempio n. 2
0
def ssh_keys(ctx):
    ssh_dir = config.HOME / '.ssh'
    ssh_dir.mkdir(exist_ok=True)

    if config.SSH_KEY_FILE.is_file():
        get_logger().info(
            'Found existing key ~/.ssh/id_rsa, skipping setting up ssh keys')
        get_logger().info(
            'Please ensure your keys are added to your GitHub account')
        return
    else:
        get_logger().info('Did not find existing ssh key in ~/.ssh/id_rsa')

    with open(ssh_dir / 'config', 'w') as fh:
        get_logger().info('Disabling host key checking for github.com in %s',
                          str(ssh_dir / 'config'))
        fh.write('Host github.com\n\tStrictHostKeyChecking no\n')

    res = req_input(
        'Opening browser for instructions to setting up ssh keys in GitHub, '
        'press any key to continue, enter "skip" to skip: ')

    if res != 'skip':
        webbrowser.open(config.GITHUB_SSH_HELP_URL)
        get_logger().info(
            actionable(
                'Once you\'ve generated SSH keys and added them to GitHub, '
                'please rerun `workflow setup.macos`'))
        sys.exit(0)

    else:
        get_logger().info('Skipping adding SSH Keys to GitHub')
Esempio n. 3
0
def install_githooks(ctx):
    hooks_dir = config.HOME / '.githooks'

    # Dupe of path defined in REQUIRED_REPO.
    kernel_tools_dir = config.REPO_ROOT / 'kernel-tools'
    mongo_dir = config.REPO_ROOT / 'mongo'

    hooks_dir.mkdir(exist_ok=True, parents=True)

    if not (hooks_dir / 'mongo').exists():
        ctx.run(
            f'ln -s {str(kernel_tools_dir / "githooks")} {str(hooks_dir / "mongo")}'
        )

    with ctx.cd(str(mongo_dir)):
        ctx.run(f'source buildscripts/install-hooks -f')

        todo = actionable('TODO:')
        get_logger().info(
            f'{todo} Please consult with your mentor on which githooks are needed. Some hooks may be'
        )
        get_logger().info(
            '      unnecessarily cumbersome for your project. You can delete any unneeded hooks in '
        )
        get_logger().info(f'     `%s` and rerun `workflow macos.setup`',
                          str(kernel_tools_dir / "githooks" / "pre-push"))
Esempio n. 4
0
 def username(self):
     if not self._username:
         self._username = input(
             actionable(
                 'Please enter your Evergreen username (firstname.lastname): '
             ))
     return self._username
Esempio n. 5
0
def zzz(ctx, force=False):
    """
    Step 6: Cleanup. Remove local branches and close Jira ticket

    :param force: Force delete the local branch even if it's not fully merged
    """
    helpers.check_mongo_repo_root()
    ticket_conf = helpers.get_ticket_conf(ctx)
    feature_branch = git.cur_branch_name(ctx)
    base_branch = ticket_conf.base_branch

    get_logger().info(f'🍦 Congrats on completing {feature_branch.upper()}! 🍦')
    input(actionable(f'Press any key to remove local branches and close the Jira ticket'))

    config.Config().in_progress_tickets.pop(feature_branch)

    ctx.run(f'git checkout {base_branch}')

    try:
        if force:
            ctx.run(f'git branch -D {feature_branch}')
        else:
            ctx.run(f'git branch --delete {feature_branch}')
    except UnexpectedExit as e:
        get_logger().error(e)
        get_logger().error(f'Failed to delete branch, please manually delete your local branch {feature_branch}')

    jira.transition_ticket(
        feature_branch.upper(),
        'In Code Review',
        'Close Issue'
    )
Esempio n. 6
0
def evergreen_yaml(conf):
    if config.EVG_CONFIG_FILE.exists():
        get_logger().info(
            'Found existing ~/.evergreen.yml, skipping adding Evergreen configuration')
        get_logger().info(
            'Please ensure your ~/.evergreen.yml was generated by this tool. If not, '
            'make sure you know what\'s in there')
    else:
        settings_url = 'https://evergreen.mongodb.com/login/key'
        while True:
            pwd = getpass.getpass(prompt=actionable('Please enter your Evergreen password: '******'username': conf.username, 'password': pwd})
            if res.status_code != 200:
                get_logger().error('Failed to fetch API key from evergreen. Error: %s', str(res))
                req_input('Press any key to retry...')
                continue
            res_json = res.json()

            evg_config = evergreen_yaml_template.format(res_json['user'], res_json['api_key'])

            with open(config.EVG_CONFIG_FILE, 'w') as fh:
                fh.write(evg_config)
            break

    return True
Esempio n. 7
0
 def jira_pwd(self):
     if not self._jira_pwd:
         jira_pwd = keyring.get_password(JIRA_URL, self.username)
         if not jira_pwd:
             jira_pwd = getpass.getpass(
                 prompt=actionable('Please enter your Jira password: '))
         keyring.set_password(JIRA_URL, self.username, jira_pwd)
         self._jira_pwd = jira_pwd
     return self._jira_pwd
Esempio n. 8
0
    def get_sudo_pwd(self, ctx):
        if not self._sudo_pwd:
            while True:
                sudo_pwd = getpass.getpass(
                    prompt=actionable('Please enter your sudo password: '******'ls', warn=False, hide='both', password=sudo_pwd)
                except invoke.exceptions.AuthFailure as e:
                    get_logger().error(str(e))
                    continue

                self._sudo_pwd = sudo_pwd
                break

        return self._sudo_pwd
Esempio n. 9
0
def post_task_instructions():
    lines = [
        actionable('Note on Using "compiledb":'),
        '    A Clang JSON Compilation Database (compiledb) can be generated for the mongo repository by running',
        '', '    `ninja compiledb` (from the mongo repo at ~/mongodb/mongo)',
        '',
        '    It enables features like jump to definition and semantic code completion in code editors. Please refer',
        '    to the following web page on how to integrate compiledb with your favorite editor',
        '',
        '    https://sarcasm.github.io/notes/dev/compilation-database.html#text-editors-and-ides',
        '',
        '    When you switch branches or add/remove files, compiledb needs to be updated by running `ninja compiledb`',
        '',
        '    If you\'d like to use an editor that "just works", The CLion IDE is a good option. You just need',
        '    to install it and open the "mongo" directory. Code completion and jumping to definitions will',
        '    automatically work', '',
        '    To install CLion, run: `brew cask install clion`'
    ]

    log_multiline(get_logger().info, lines)
Esempio n. 10
0
def ship(ctx):
    """
    Step 5: Provide instructions on pushing your changes to master

    Also add the URL of the latest patch build to the Jira ticket.
    """
    helpers.check_mongo_repo_root()
    ticket_conf = helpers.get_ticket_conf(ctx)
    cur_branch = git.cur_branch_name(ctx)

    if ticket_conf.patch_ids:
        jira.add_comment(
            cur_branch.upper(),
            f'Patch Build: {urllib.parse.urljoin(config.EVG_PATCH_URL_BASE, ticket_conf.patch_ids[-1])}',
            visibility={'type': 'role', 'value': 'Developers'}
        )
    else:
        get_logger().warning('No patch builds were created for this ticket, not adding patch build URL to Jira')

    # This will implicitly check for uncommitted changes on the feature branch
    git.refresh_repos(ctx, ticket_conf.base_branch)

    lines = [
        actionable('Please run the following commands to push your changes to the upstream MongoDB repository:'),
        '',
        f'    git rebase --interactive {ticket_conf.base_branch}',
        f'    git checkout {ticket_conf.base_branch}',
        f'    git merge --ff-only {cur_branch}',
        f'    git push origin {ticket_conf.base_branch} --dry-run',
        f'    git push origin {ticket_conf.base_branch}',
        '',
        'As part of `git rebase --interactive`, you should squash your local commits into one commit. Please refer to',
        'this guide for an intro to interactive rebase: https://git-scm.com/docs/git-rebase#_interactive_mode',
        '',
        'If you encounter errors during any of the above steps, please ask your mentor for advice.',
        '',
        'Finally, when you\'ve pushed your changes, run `workflow zzz` to delete your local branches'
    ]
    log.log_multiline(get_logger().info, lines)
Esempio n. 11
0
def review(ctx):
    """
    Step 4: Open a new code review (CR) or put up a new patch to an existing code review
    """
    helpers.check_mongo_repo_root()

    ticket_conf = helpers.get_ticket_conf(ctx)

    if not ticket_conf.commits:
        get_logger().warning('Did not find any commits on this branch. Please make sure you run `commit` '
                             'before `review`')

    with ctx.prefix(helpers.virtualenv):
        def upload(existing_cr, repo_name):
            has_changes = ctx.run(f'git diff {ticket_conf.base_branch}').stdout.strip()
            if has_changes:
                get_logger().info(f'Submitting code review for the {repo_name} repo')
            else:
                get_logger().info(f'There are no changes in the {repo_name} repository, skipping code review')
                return

            cmd = f'python {str(config.UPLOAD_PY)} --rev {ticket_conf.base_branch}...'  # Yes three dots.
            cmd += ' --nojira -y --git_similarity 90 --check-clang-format --check-eslint'

            if existing_cr is not None:
                # Continue an existing CR.
                cmd += f' -i {existing_cr}'
            else:
                # Start a new CR.
                commit_msg = ctx.run('git log -1 --pretty=%B').stdout.strip()
                cr_title = input(f'Please enter the title for this code review (without the ticket number). '
                                 f'Default: {commit_msg}')
                if not cr_title:
                    cr_title = commit_msg
                else:
                    # Add the ticket number to the description.
                    cr_title = f'{git.cur_branch_name(ctx).upper()} {commit_msg}'

                cmd += f' -t "{cr_title}"'

            get_logger().info('Opening browser to authenticate with OAuth2... ')
            # Simulate some newline inputs to get the browser to open.
            sim_stdin = io.StringIO(initial_value='\n\n')
            res = ctx.run(cmd, in_stream=sim_stdin)

            if existing_cr is None:
                cr_url = re.search('Issue created. URL: (.*)', res.stdout.strip()).group(1)
                cr_issue_number = cr_url.split('/')[-1]
                get_logger().info(f'Code review created: {cr_url}')

                ticket_number = git.cur_branch_name(ctx).upper()
                jira.transition_ticket(ticket_number, 'In Progress', 'Start Code Review')

                jira.add_comment(
                    ticket_number,
                    f'Code Review: {cr_url}',
                    visibility={'type': 'role', 'value': 'Developers'}
                )

                return cr_issue_number
            else:
                get_logger().info(f'Code review updated')
                return existing_cr

        ticket_conf.cr_info.community = upload(ticket_conf.cr_info.community, 'community')
        with ctx.cd(git.ent_repo_rel_path):
            ticket_conf.cr_info.enterprise = upload(ticket_conf.cr_info.enterprise, 'enterprise')

        note = actionable('Note:')
        get_logger().info('')
        get_logger().info(f'{note} Step 3 (patch build) and Step 4 (code review) may need to be repeated to address')
        get_logger().info('      CR feedback or to validate new changes. Please consult with your mentor on the exact')
        get_logger().info('      workflow for your team.')
        get_logger().info('')
        req_input('Press any key to open the code review app...')
        webbrowser.open('https://mongodbcr.appspot.com')