def main():
    """Performs task to initiate the release."""
    common.require_cwd_to_be_oppia()
    common.verify_current_branch_name('develop')
    common.open_new_tab_in_browser_if_possible(
        release_constants.RELEASE_NOTES_URL)
    common.ask_user_to_confirm(
        'Please check if anything extra is required for the release. '
        'If so, keep track of this and do it at the appropriate point.')

    common.open_new_tab_in_browser_if_possible(
        release_constants.RELEASE_DRIVE_URL)
    python_utils.PRINT(
        'Has the QA lead created a document for the current release?\n'
        'Confirm by entering y/ye/yes.\n')
    doc_for_release_created = python_utils.INPUT().lower()
    if doc_for_release_created not in (
            release_constants.AFFIRMATIVE_CONFIRMATIONS):
        raise Exception('Please ensure a new doc is created for the '
                        'release before starting with the release process.')

    remote_alias = common.get_remote_alias(release_constants.REMOTE_URL)
    python_utils.PRINT('Enter version of previous release.')
    previous_release_version = python_utils.INPUT()
    assert re.match(r'^\d+\.\d+\.\d+$', previous_release_version)

    extra_jobs_to_run = get_extra_jobs_due_to_schema_changes(
        remote_alias, previous_release_version)
    if did_supported_audio_languages_change(remote_alias,
                                            previous_release_version):
        # This job is run so that an opportunity is created for
        # contributors to translate and voiceover an exploration
        # whenever a new audio language is added.
        # Refer: https://github.com/oppia/oppia/issues/8027.
        extra_jobs_to_run.append(
            'ExplorationOpportunitySummaryModelRegenerationJob')
    if extra_jobs_to_run:
        common.ask_user_to_confirm(
            'Please add the following jobs to release journal and '
            'run them after deployment:\n%s' % '\n'.join(extra_jobs_to_run))

    common.open_new_tab_in_browser_if_possible(
        release_constants.REPEATABLE_JOBS_SPREADSHEETS_URL)
    common.open_new_tab_in_browser_if_possible(
        release_constants.ONE_TIME_JOBS_SPREADSHEET_URL)
    common.ask_user_to_confirm(
        'Please copy the names of the jobs to be run for this release along '
        'with author names, author mail ids & instruction docs.\n'
        'Note: Copy only those jobs that have been successfully run '
        'on backup server.')
    common.open_new_tab_in_browser_if_possible(
        release_constants.RELEASE_DRIVE_URL)
    common.ask_user_to_confirm(
        'Please enter the above job names to release journal.')

    cut_release_branch()
def execute_branch_cut(target_version, hotfix_number):
    """Creates & pushes the new release branch to Github.

    Args:
        target_version: str. The release version.
        hotfix_number: int. The number for the hotfix branch.

    Raises:
        Exception: Travis tests are failing on the branch from which
            the new branch is cut.
    """

    # Construct the new branch name.
    if not hotfix_number:
        new_branch_type, new_branch_name = _get_release_branch_type_and_name(
            target_version)
    else:
        new_branch_type, new_branch_name = _get_hotfix_branch_type_and_name(
            target_version, hotfix_number)

    # Do prerequisite checks.
    common.require_cwd_to_be_oppia()
    common.verify_local_repo_is_clean()
    common.verify_current_branch_name('develop')

    # Update the local repo.
    remote_alias = common.get_remote_alias(release_constants.REMOTE_URL)
    subprocess.check_call(['git', 'pull', remote_alias, 'develop'])

    verify_target_branch_does_not_already_exist(remote_alias, new_branch_name)

    # The release coordinator should verify that tests are passing on the parent
    # branch before checking out the new branch.
    common.open_new_tab_in_browser_if_possible(
        'https://travis-ci.org/oppia/oppia/branches')
    while True:
        if not hotfix_number:
            branch_to_check = 'develop'
        elif hotfix_number == 1:
            branch_to_check = 'release-%s' % target_version
        else:
            branch_to_check = 'release-%s-hotfix-%s' % (target_version,
                                                        hotfix_number - 1)
        python_utils.PRINT(
            'Please confirm: are Travis checks passing on %s? (y/n) ' %
            (branch_to_check))
        answer = python_utils.INPUT().lower()
        if answer in release_constants.AFFIRMATIVE_CONFIRMATIONS:
            break
        elif answer:
            raise Exception(
                'Tests should pass on %s before this script is run.' %
                (branch_to_check))

    # Cut a new release or hotfix branch.
    if new_branch_type == release_constants.BRANCH_TYPE_HOTFIX:
        verify_hotfix_number_is_one_ahead_of_previous_hotfix_number(
            remote_alias, target_version, hotfix_number)
        if hotfix_number == 1:
            branch_to_cut_from = 'release-%s' % target_version
        else:
            branch_to_cut_from = 'release-%s-hotfix-%s' % (target_version,
                                                           hotfix_number - 1)
        python_utils.PRINT('Cutting a new hotfix branch: %s' % new_branch_name)
        subprocess.check_call(
            ['git', 'checkout', '-b', new_branch_name, branch_to_cut_from])
    else:
        verify_target_version_compatible_with_latest_release(target_version)
        python_utils.PRINT('Cutting a new release branch: %s' %
                           new_branch_name)
        subprocess.check_call(['git', 'checkout', '-b', new_branch_name])

    # Push the new release branch to GitHub.
    python_utils.PRINT('Pushing new %s branch to GitHub.' % new_branch_type)
    subprocess.check_call(['git', 'push', remote_alias, new_branch_name])

    python_utils.PRINT('')
    python_utils.PRINT(
        'New %s branch successfully cut. You are now on branch %s' %
        (new_branch_type, new_branch_name))
    python_utils.PRINT('Done!')

    common.ask_user_to_confirm(
        'Ask Sean (or Ben, if Sean isn\'t available) to create '
        'a new branch protection rule by:\n'
        '1. Going to this page: https://github.com/oppia/oppia/'
        'settings/branch_protection_rules/new.\n'
        '2. Typing in the full branch name %s.\n'
        '3. Checking the box: Restrict who can push to matching '
        'branches (then add the oppia/release-coordinators team)\n' %
        (new_branch_name))
Exemple #3
0
def execute_branch_cut(target_version, hotfix_number):
    """Creates & pushes the new release branch to Github.

    Args:
        target_version: str. The release version.
        hotfix_number: int. The number for the hotfix branch.

    Raises:
        Exception. Actions tests are failing on the branch from which
            the new branch is cut.
    """

    # Construct the new branch name.
    if not hotfix_number:
        new_branch_type, new_branch_name = _get_release_branch_type_and_name(
            target_version)
    else:
        new_branch_type, new_branch_name = _get_hotfix_branch_type_and_name(
            target_version, hotfix_number)

    # Do prerequisite checks.
    common.require_cwd_to_be_oppia()
    common.verify_local_repo_is_clean()
    common.verify_current_branch_name('develop')

    # Update the local repo.
    remote_alias = common.get_remote_alias(
        constants.release_constants.REMOTE_URLS)
    subprocess.check_call(['git', 'pull', remote_alias, 'develop'])

    verify_target_branch_does_not_already_exist(remote_alias, new_branch_name)

    if not hotfix_number:
        branch_to_check = 'develop'
    elif hotfix_number == 1:
        branch_to_check = 'release-%s' % target_version
    else:
        branch_to_check = 'release-%s-hotfix-%s' % (target_version,
                                                    hotfix_number - 1)
    # The release coordinator should verify that tests are passing on
    # the parent branch before checking out the new branch.
    common.open_new_tab_in_browser_if_possible(
        'https://github.com/oppia/oppia/actions?query=branch:%s' %
        branch_to_check)
    print('Please confirm: are Actions checks passing on %s? (y/n) ' %
          (branch_to_check))
    answer = input().lower()
    if answer not in common.AFFIRMATIVE_CONFIRMATIONS:
        raise Exception('Tests should pass on %s before this script is run.' %
                        (branch_to_check))

    # Cut a new release or hotfix branch.
    if new_branch_type == constants.release_constants.BRANCH_TYPE_HOTFIX:
        verify_hotfix_number_is_one_ahead_of_previous_hotfix_number(
            remote_alias, target_version, hotfix_number)
        if hotfix_number == 1:
            branch_to_cut_from = 'release-%s' % target_version
        else:
            branch_to_cut_from = 'release-%s-hotfix-%s' % (target_version,
                                                           hotfix_number - 1)
        print('Cutting a new hotfix branch: %s' % new_branch_name)
        subprocess.check_call(['git', 'checkout', branch_to_cut_from])
        common.update_branch_with_upstream()
        subprocess.check_call(
            ['git', 'checkout', '-b', new_branch_name, branch_to_cut_from])
    else:
        verify_target_version_compatible_with_latest_release(target_version)
        print('Cutting a new release branch: %s' % new_branch_name)
        subprocess.check_call(['git', 'checkout', '-b', new_branch_name])

    # Push the new release branch to GitHub.
    if new_branch_type == constants.release_constants.BRANCH_TYPE_RELEASE:
        print('Pushing new %s branch to GitHub.' % new_branch_type)
        subprocess.check_call(['git', 'push', remote_alias, new_branch_name])
    else:
        print('Please cherrypick the required PRs and push the branch '
              'to Github once this script is done.\n'
              'Note: It is fine to push the branch only after creating the '
              'branch protection rule and doing all the cherrypicks.')

    print('')
    print('New %s branch successfully cut. You are now on branch %s' %
          (new_branch_type, new_branch_name))
    print('Done!')
def execute_branch_cut():
    """Pushes the new release branch to Github."""

    parsed_args = _PARSER.parse_args()
    if parsed_args.new_version:
        target_version = parsed_args.new_version
    else:
        raise Exception('ERROR: A "new_version" arg must be specified.')

    # Construct the new branch name.
    hotfix_number = int(parsed_args.hotfix_number)
    if not hotfix_number:
        new_branch_type, new_branch_name = _get_release_branch_type_and_name(
            target_version)
    else:
        new_branch_type, new_branch_name = _get_hotfix_branch_type_and_name(
            target_version, hotfix_number)

    # Do prerequisite checks.
    common.require_cwd_to_be_oppia()
    common.verify_local_repo_is_clean()
    common.verify_current_branch_name('develop')

    # Update the local repo.
    remote_alias = common.get_remote_alias(release_constants.REMOTE_URL)
    subprocess.check_call(['git', 'pull', remote_alias, 'develop'])

    verify_target_branch_does_not_already_exist(remote_alias, new_branch_name)

    # The release coordinator should verify that tests are passing on develop
    # before checking out the release branch.
    common.open_new_tab_in_browser_if_possible(
        'https://github.com/oppia/oppia#oppia---')
    while True:
        if not hotfix_number:
            branch_to_check = 'develop'
        elif hotfix_number == 1:
            branch_to_check = 'release-%s' % target_version
        else:
            branch_to_check = 'release-%s-hotfix-%s' % (
                target_version, hotfix_number - 1)
        python_utils.PRINT(
            'Please confirm: are Travis checks passing on %s? (y/n) ' % (
                branch_to_check))
        answer = python_utils.INPUT().lower()
        if answer in release_constants.AFFIRMATIVE_CONFIRMATIONS:
            break
        elif answer:
            python_utils.PRINT(
                'Tests should pass on %s before this script is run. '
                'Exiting.' % branch_to_check)
            sys.exit()

    # Cut a new release or hotfix branch.
    if new_branch_type == release_constants.BRANCH_TYPE_HOTFIX:
        verify_hotfix_number_is_one_ahead_of_previous_hotfix_number(
            remote_alias, target_version, hotfix_number)
        if hotfix_number == 1:
            branch_to_cut_from = 'release-%s' % target_version
        else:
            branch_to_cut_from = 'release-%s-hotfix-%s' % (
                target_version, hotfix_number - 1)
        python_utils.PRINT('Cutting a new hotfix branch: %s' % new_branch_name)
        subprocess.check_call([
            'git', 'checkout', '-b', new_branch_name, branch_to_cut_from])
    else:
        verify_target_version_compatible_with_latest_release(
            target_version)
        python_utils.PRINT('Cutting a new release branch: %s' % new_branch_name)
        subprocess.check_call(['git', 'checkout', '-b', new_branch_name])

    # Push the new release branch to GitHub.
    python_utils.PRINT('Pushing new %s branch to GitHub.' % new_branch_type)
    subprocess.check_call(['git', 'push', remote_alias, new_branch_name])

    python_utils.PRINT('')
    python_utils.PRINT(
        'New %s branch successfully cut. You are now on branch %s' % (
            new_branch_type, new_branch_name))
    python_utils.PRINT('Done!')