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)
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.')
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')
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.')
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))
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)
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)
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)
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!')
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()