def prepare_for_next_release():
    """Asks the release co-ordinator:
        1. To create a new chat group for the next release and send a message
        to make the release & QA co-ordinators aware.
        2. Send message to oppia-dev to inform about next release cut.
        3. Send message to oppia-dev as a reminder for job submissions.
    """
    common.open_new_tab_in_browser_if_possible(
        release_constants.RELEASE_ROTA_URL)
    common.ask_user_to_confirm(
        'Create a new chat group for the next release, '
        'and add the release coordinator, QA lead, Ankita '
        'and Nithesh to that group. You can find the release schedule '
        'and coordinators here: %s\n' % release_constants.RELEASE_ROTA_URL)
    common.ask_user_to_confirm(
        'Please send the following message to the newly created group:\n\n'
        'Hi all, This is the group chat for the next release. '
        '[Release co-ordinator\'s name] and [QA Lead\'s name] will be '
        'the release co-ordinator & QA Lead for next release. '
        'Please follow the release process doc: '
        '[Add link to release process doc] to ensure the release '
        'follows the schedule. Thanks!\n')
    common.open_new_tab_in_browser_if_possible(
        release_constants.OPPIA_DEV_GROUP_URL)
    common.ask_user_to_confirm(
        'Send the following message to oppia-dev:\n\n'
        'Hi all, This is an update for the next month\'s release. '
        'The next month release cut is [Add release cut date for next month]. '
        'Make sure you plan your tasks accordingly. Thanks!\n'
        'The subject for the message: Updates for next release\n')
    common.ask_user_to_confirm(
        'Send the following message to oppia-dev:\n\n'
        'Hi all, This is a reminder to fill in the job requests '
        'here: %s if you are planning to run your job in the next release. '
        'Please fill in the requests by [Add a deadline which is at least 7 '
        'days before the next release cut]. Thanks!\n'
        'The subject for the message: Deadline for job requests for '
        'the next release\n' % release_constants.JOBS_FORM_URL)
Ejemplo n.º 2
0
def update_and_check_indexes(app_name):
    """Updates indexes and checks if all indexes are serving.

    Args:
        app_name: str. The name of the app to deploy.

    Raises:
        Exception. All indexes are not serving on the indexes page.
    """
    # Update indexes, then prompt for a check that they are all serving
    # before continuing with the deployment.
    # NOTE: This assumes that the build process does not modify the
    # index.yaml file or create a different version of it to use in
    # production.
    indexes_page_url = ('https://console.cloud.google.com/datastore/indexes'
                        '?project=%s') % app_name
    gcloud_adapter.update_indexes(INDEX_YAML_PATH, app_name)
    if not gcloud_adapter.check_all_indexes_are_serving(app_name):
        common.open_new_tab_in_browser_if_possible(indexes_page_url)
        raise Exception(
            'Please wait for all indexes to serve, then run this '
            'script again to complete the deployment. For details, '
            'visit the indexes page. Exiting.')
Ejemplo n.º 3
0
def prompt_user_to_send_announcement_email():
    """Asks the user to send release announcement mail and check if
    it is in announcement category.
    """
    new_contributors_mail_ids = (', ').join(
        get_new_authors_and_contributors_mail_ids())
    release_version = common.get_current_release_version_number(
        common.get_current_branch_name())
    common.open_new_tab_in_browser_if_possible('https://www.gmail.com')
    common.ask_user_to_confirm(
        'Please draft an announcement message for the release and send it to:\n'
        '   TO: [email protected]\n'
        '   BCC: [email protected], '
        '[email protected], %s\n'
        'with the following subject: "Announcing release v%s of Oppia!"'
        'Please make sure to check that the mail ids of new authors '
        'and contributors are correct.\n' %
        (new_contributors_mail_ids, release_version))
    common.open_new_tab_in_browser_if_possible(
        'https://groups.google.com/forum/#!categories/oppia')
    common.ask_user_to_confirm('Add announcements label to the email sent.\n')
    common.ask_user_to_confirm(
        'Ensure the email sent to oppia@ is in the Announcements category')
Ejemplo n.º 4
0
def create_release_doc():
    """Asks the co-ordinator to create a doc for the current release."""
    common.open_new_tab_in_browser_if_possible(
        release_constants.RELEASE_DRIVE_URL)
    common.open_new_tab_in_browser_if_possible(
        release_constants.RELEASE_NOTES_TEMPLATE_URL)
    common.open_new_tab_in_browser_if_possible(
        release_constants.RELEASE_NOTES_EXAMPLE_URL)
    common.ask_user_to_confirm(
        'Please create a dedicated section for this release in the '
        'release tracking document created by the QA Lead.\n'
        'The three tabs in your browser point to: '
        'Release drive url, template for the release notes, example of release '
        'notes from previous release.')
Ejemplo n.º 5
0
def check_travis_and_circleci_tests(current_branch_name):
    """Checks if all travis and circleci tests are passing on release/test
    branch.

    Args:
        current_branch_name: str. The name of current branch.

    Raises:
        Exception. The latest commit on release/test branch locally does not
            match the latest commit on local fork or upstream.
        Exception. The travis or circleci tests are failing on release/test
            branch.
    """
    local_sha = subprocess.check_output(
        ['git', 'rev-parse', current_branch_name])
    origin_sha = subprocess.check_output(
        ['git', 'rev-parse',
         'origin/%s' % current_branch_name])
    upstream_sha = subprocess.check_output([
        'git', 'rev-parse',
        '%s/%s' % (common.get_remote_alias(
            release_constants.REMOTE_URL), current_branch_name)
    ])
    if local_sha != origin_sha:
        raise Exception('The latest commit on release branch locally does '
                        'not match the latest commit on your local fork.')
    if local_sha != upstream_sha:
        raise Exception('The latest commit on release branch locally does '
                        'not match the latest commit on Oppia repo.')

    python_utils.PRINT('\nEnter your GitHub username.\n')
    github_username = python_utils.INPUT().lower().strip()

    travis_url = 'https://travis-ci.org/%s/oppia/branches' % github_username
    circleci_url = 'https://circleci.com/gh/%s/workflows/oppia' % (
        github_username)

    try:
        python_utils.url_open(travis_url)
    except Exception:
        travis_url = 'https://travis-ci.com/oppia/oppia/branches'

    try:
        python_utils.url_open(circleci_url)
    except Exception:
        circleci_url = 'https://circleci.com/gh/oppia/workflows/oppia'

    common.open_new_tab_in_browser_if_possible(travis_url)
    python_utils.PRINT('Are all travis tests passing on branch %s?\n' %
                       current_branch_name)
    travis_tests_passing = python_utils.INPUT().lower()
    if travis_tests_passing not in release_constants.AFFIRMATIVE_CONFIRMATIONS:
        raise Exception('Please fix the travis tests before deploying.')

    common.open_new_tab_in_browser_if_possible(circleci_url)
    python_utils.PRINT('Are all circleci tests passing on branch %s?\n' %
                       current_branch_name)
    circleci_tests_passing = python_utils.INPUT().lower()
    if circleci_tests_passing not in (
            release_constants.AFFIRMATIVE_CONFIRMATIONS):
        raise Exception('Please fix the circleci tests before deploying.')
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))
Ejemplo n.º 7
0
def main():
    """Collects necessary info and dumps it to disk."""
    branch_name = common.get_current_branch_name()
    if not common.is_current_branch_a_release_branch():
        raise Exception(
            'This script should only be run from the latest release branch.')

    parsed_args = _PARSER.parse_args()
    if parsed_args.github_username is None:
        raise Exception('No GitHub username provided. Please re-run the '
                        'script specifying a username using '
                        '--github_username=<Your username>')
    github_username = parsed_args.github_username

    personal_access_token = common.get_personal_access_token()

    g = github.Github(personal_access_token)
    repo = g.get_organization('oppia').get_repo('oppia')
    repo_fork = g.get_repo('%s/oppia' % github_username)

    common.check_blocking_bug_issue_count(repo)
    common.check_prs_for_current_release_are_released(repo)

    if not os.path.exists(
            constants.release_constants.RELEASE_SUMMARY_FILEPATH):
        raise Exception('Release summary file %s is missing. Please re-run '
                        'this script.' %
                        (constants.release_constants.RELEASE_SUMMARY_FILEPATH))

    current_release_version_number = common.get_current_release_version_number(
        branch_name)
    target_branch = 'update-changelog-for-releasev%s' % (
        current_release_version_number)

    remove_updates_and_delete_branch(repo_fork, target_branch)

    # Opens Credit Form.
    python_utils.PRINT(
        'Note: Make following changes directly to %s and make sure to '
        'save the file after making these changes.' %
        (constants.release_constants.RELEASE_SUMMARY_FILEPATH))

    common.ask_user_to_confirm(
        'Check emails and names for new authors and new contributors in the '
        'file: %s and verify that the emails are '
        'correct through welcome emails sent from [email protected] '
        '(confirm with Sean in case of doubt). Please ensure that you correct '
        'the emails of the form: %s.' %
        (constants.release_constants.RELEASE_SUMMARY_FILEPATH,
         constants.release_constants.INVALID_EMAIL_SUFFIX))
    common.open_new_tab_in_browser_if_possible(
        constants.release_constants.CREDITS_FORM_URL)
    common.ask_user_to_confirm(
        'Check the credits form and add any additional contributors '
        'to the contributor list in the file: %s.' %
        (constants.release_constants.RELEASE_SUMMARY_FILEPATH))
    common.ask_user_to_confirm(
        'Categorize the PR titles in the Uncategorized section of the '
        'changelog in the file: %s, and arrange the changelog '
        'to have user-facing categories on top.' %
        (constants.release_constants.RELEASE_SUMMARY_FILEPATH))
    common.ask_user_to_confirm(
        'Verify each item is in the correct section in the '
        'file: %s and remove trivial changes like "Fix lint errors" '
        'from the changelog.' %
        (constants.release_constants.RELEASE_SUMMARY_FILEPATH))
    common.ask_user_to_confirm(
        'Ensure that all items in changelog in the file: %s '
        'start with a verb in simple present tense.' %
        (constants.release_constants.RELEASE_SUMMARY_FILEPATH))
    common.ask_user_to_confirm(
        'Please save the file: %s with all the changes that '
        'you have made.' %
        (constants.release_constants.RELEASE_SUMMARY_FILEPATH))

    release_summary_lines = get_release_summary_lines()

    update_changelog(branch_name, release_summary_lines,
                     current_release_version_number)
    update_authors(release_summary_lines)
    update_contributors(release_summary_lines)
    update_developer_names(release_summary_lines)
    update_version_in_config_files()

    list_of_numbered_files = []
    for i, filepath in enumerate(LIST_OF_FILEPATHS_TO_MODIFY, start=1):
        list_of_numbered_files.append('%s. %s' % (i, filepath))

    message = ('Please check the changes and make updates if required in the '
               'following files:\n%s\n' % '\n'.join(list_of_numbered_files))
    common.ask_user_to_confirm(message)

    create_branch(repo, repo_fork, target_branch, github_username,
                  current_release_version_number)
Ejemplo n.º 8
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 main():
    """Collects necessary info and dumps it to disk."""
    branch_name = common.get_current_branch_name()
    if not common.is_current_branch_a_release_branch():
        raise Exception(
            'This script should only be run from the latest release branch.')

    parsed_args = _PARSER.parse_args()
    if parsed_args.github_username is None:
        raise Exception(
            'No GitHub username provided. Please re-run the '
            'script specifying a username using '
            '--github_username=<Your username>')
    github_username = parsed_args.github_username

    personal_access_token = common.get_personal_access_token()

    python_utils.PRINT('Generating release summary...')
    generate_release_info.main(personal_access_token)

    if not os.path.exists(release_constants.RELEASE_SUMMARY_FILEPATH):
        raise Exception(
            'Release summary file %s is missing. Please re-run '
            'this script.' % release_constants.RELEASE_SUMMARY_FILEPATH)

    g = github.Github(personal_access_token)
    repo_fork = g.get_repo('%s/oppia' % github_username)

    current_release_version_number = common.get_current_release_version_number(
        branch_name)
    target_branch = 'update-changelog-for-releasev%s' % (
        current_release_version_number)

    remove_updates_and_delete_branch(repo_fork, target_branch)

    # Opens Credit Form.
    python_utils.PRINT(
        'Note: Make following changes directly to %s and make sure to '
        'save the file after making these changes.' % (
            release_constants.RELEASE_SUMMARY_FILEPATH))

    common.ask_user_to_confirm(
        'Check emails and names for authors and contributors in the release '
        'summary file and verify that the emails are '
        'correct through welcome emails sent from [email protected] '
        '(confirm with Sean in case of doubt).')
    common.open_new_tab_in_browser_if_possible(
        release_constants.CREDITS_FORM_URL)
    common.ask_user_to_confirm(
        'Check the credits form and add any additional contributors '
        'to the contributor list in the release summary file.')
    common.ask_user_to_confirm(
        'Categorize the PR titles in the Uncategorized section of the '
        'changelog in the release summary file, and arrange the changelog '
        'to have user-facing categories on top.')
    common.ask_user_to_confirm(
        'Verify each item is in the correct section in the release summary '
        'file and remove trivial changes like "Fix lint errors" '
        'from the changelog.')
    common.ask_user_to_confirm(
        'Ensure that all items in changelog in the release summary file '
        'start with a verb in simple present tense.')
    common.ask_user_to_confirm(
        'Please save the release summary file with all the changes that '
        'you have made.')

    release_summary_lines = []
    with python_utils.open_file(
        release_constants.RELEASE_SUMMARY_FILEPATH, 'r'
        ) as release_summary_file:
        release_summary_lines = release_summary_file.readlines()

    check_ordering_of_sections(release_summary_lines)

    update_changelog(
        branch_name, release_summary_lines, current_release_version_number)
    update_authors(release_summary_lines)
    update_contributors(release_summary_lines)
    update_developer_names(release_summary_lines)

    message = (
        'Please check the changes and make updates if required in the '
        'following files:\n1. %s\n2. %s\n3. %s\n4. %s\n' % (
            CHANGELOG_FILEPATH, AUTHORS_FILEPATH, CONTRIBUTORS_FILEPATH,
            ABOUT_PAGE_FILEPATH))
    common.ask_user_to_confirm(message)

    create_branch(
        repo_fork, target_branch, github_username,
        current_release_version_number)
Ejemplo n.º 10
0
def main():
    """Performs task to initiate the release."""
    common.require_cwd_to_be_oppia()
    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))
    try:
        # The file here is opened and closed just to create an empty
        # file where the release co-ordinator can enter the credentials.
        f = python_utils.open_file(RELEASE_CREDENTIALS_FILEPATH, 'w')
        f.close()
        common.ask_user_to_confirm(
            'Copy the release json credentials from the release '
            'doc and paste them in the file %s. Make sure to save the '
            'file once you are done.' % (RELEASE_CREDENTIALS_FILEPATH))
        client = pygsheets.authorize(
            client_secret=RELEASE_CREDENTIALS_FILEPATH)

        repeatable_jobs_sheet = client.open(
            'Oppia release team: Submitting an existing job for '
            'testing on the Oppia test server (Responses)').sheet1
        repeatable_job_details = get_job_details_for_current_release(
            repeatable_jobs_sheet.get_all_records(),
            'Select the job you want to test',
            'Which upcoming release are you targeting this job for? ',
            'Email Address', 'What is your name? ',
            'Please give a clear description of why you want to '
            'run this job on the test server')
        repeatable_job_names = [
            job_detail['job_name'] for job_detail in repeatable_job_details
        ]

        one_time_jobs_sheet = client.open(
            'Oppia release team: Submitting a job for testing (Responses)'
        ).sheet1
        one_time_job_details = get_job_details_for_current_release(
            one_time_jobs_sheet.get_all_records(),
            'What is the name of the job to be run?',
            'Which upcoming release are you targeting this job for?',
            'Email Address', 'What is your name?',
            'URL of a Google Doc with clear instructions on what the tester '
            'needs to do:')
        one_time_job_names = [
            job_detail['job_name'] for job_detail in one_time_job_details
        ]

        if repeatable_job_names:
            python_utils.PRINT('Repeatable jobs to run:\n%s\n' %
                               ('\n').join(repeatable_job_names))
        if one_time_job_names:
            python_utils.PRINT('One time jobs to run:\n%s\n' %
                               ('\n').join(one_time_job_names))
        if repeatable_job_names or one_time_job_names:
            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.')
            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)
            python_utils.PRINT(
                get_mail_message_template(repeatable_job_details +
                                          one_time_job_details))
            author_mail_ids = [
                job_details['author_email']
                for job_details in (repeatable_job_details +
                                    one_time_job_details)
            ]
            common.ask_user_to_confirm(
                'Note: Send the mail only after deploying to backup server.\n\n'
                'Note: Add author email ids: %s to the cc list when you send '
                'the mail.\n\n'
                'Note: Please check manually if the details in the above mail '
                'are correct and add anything extra if required.\n\n'
                'Copy and save the above template for sending a mail to Sean '
                'to run these jobs on backup server.\n\n'
                'If the jobs are successful on backup server, run them on test '
                'and prod server.' % list(set(author_mail_ids)))
        else:
            python_utils.PRINT('No jobs to run for the release.')
            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 check manually if there are no jobs to run.')
    finally:
        if os.path.isfile(RELEASE_CREDENTIALS_FILEPATH):
            os.remove(RELEASE_CREDENTIALS_FILEPATH)
        if os.path.isfile(AUTH_FILEPATH):
            os.remove(AUTH_FILEPATH)
Ejemplo n.º 11
0
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!')
Ejemplo n.º 12
0
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.')
    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.')
    python_utils.PRINT(get_mail_message_template())
    common.ask_user_to_confirm(
        'Update the mail message template by adding job names, '
        'instruction doc url and author names '
        'Note: Send the mail only after deploying to backup server.\n\n'
        'Note: Add author email ids to the cc list when you send '
        'the mail.\n\n'
        'Note: Please check manually if the details in the above mail '
        'are correct and add anything extra if required.\n\n'
        'Copy and save the above template for sending a mail to Sean '
        'to run these jobs on backup server.\n\n'
        'If the jobs are successful on backup server, run them on test '
        'and prod server.')

    cut_release_branch()