async def test_release_notes(doof, test_repo, test_repo_directory, mocker): """Doof should show release notes""" old_version = "0.1.2" update_version_mock = mocker.patch('bot.update_version', autospec=True, return_value=old_version) mocker.patch( 'bot.init_working_dir', side_effect=async_context_manager_yielder(test_repo_directory) ) notes = "some notes" create_release_notes_mock = mocker.async_patch('bot.create_release_notes', return_value=notes) any_new_commits_mock = mocker.async_patch('bot.any_new_commits', return_value=True) org, repo = get_org_and_repo(test_repo.repo_url) release_pr = ReleasePR('version', f'https://github.com/{org}/{repo}/pulls/123456', 'body') get_release_pr_mock = mocker.async_patch('bot.get_release_pr', return_value=release_pr) await doof.run_command( manager='mitodl_user', channel_id=test_repo.channel_id, words=['release', 'notes'], ) update_version_mock.assert_called_once_with("9.9.9", working_dir=test_repo_directory) create_release_notes_mock.assert_called_once_with( old_version, with_checkboxes=False, base_branch="master", root=test_repo_directory ) any_new_commits_mock.assert_called_once_with(old_version, base_branch="master", root=test_repo_directory) get_release_pr_mock.assert_called_once_with(github_access_token=GITHUB_ACCESS, org=org, repo=repo) assert doof.said("Release notes since {}".format(old_version)) assert doof.said(notes) assert doof.said(f"And also! There is a release already in progress: {release_pr.url}")
async def test_startup(doof, mocker, repo_info, has_release_pr, has_expected): """ Test that doof will show help text """ doof.repos_info = [repo_info] release_pr = ReleasePR( version="version", url=repo_info.repo_url, body='Release PR body', ) mocker.async_patch('bot.get_release_pr', return_value=( release_pr if has_release_pr else None )) wait_for_checkboxes_mock = mocker.async_patch('bot.Bot.wait_for_checkboxes') wait_for_deploy_mock = mocker.async_patch('bot.Bot.wait_for_deploy') await doof.startup() # iterate once through event loop await asyncio.sleep(0) assert not doof.said("isn't evil enough until all the checkboxes are checked") if has_expected: wait_for_checkboxes_mock.assert_called_once_with(doof, manager=None, repo_info=repo_info, speak_initial=False) wait_for_deploy_mock.assert_called_once_with(doof, repo_info=repo_info) else: assert wait_for_checkboxes_mock.call_count == 0 assert wait_for_deploy_mock.call_count == 0
async def test_wait_for_deploy_rc(doof, test_repo, mocker): """Bot._wait_for_deploy_prod should wait until repo has been deployed to RC""" wait_for_deploy_mock = mocker.async_patch('bot.wait_for_deploy') get_unchecked_patch = mocker.async_patch( 'bot.get_unchecked_authors', return_value={'author1', 'author2', 'author3'} ) org, repo = get_org_and_repo(test_repo.repo_url) release_pr = ReleasePR('version', f'https://github.com/{org}/{repo}/pulls/123456', 'body') get_release_pr_mock = mocker.async_patch('bot.get_release_pr', return_value=release_pr) await doof._wait_for_deploy_rc(repo_info=test_repo) # pylint: disable=protected-access assert doof.said('These people have commits in this release') wait_for_deploy_mock.assert_called_once_with( github_access_token=GITHUB_ACCESS, repo_url=test_repo.repo_url, hash_url=test_repo.rc_hash_url, watch_branch='release-candidate' ) get_unchecked_patch.assert_called_once_with( github_access_token=GITHUB_ACCESS, org=org, repo=repo, ) get_release_pr_mock.assert_called_once_with( github_access_token=GITHUB_ACCESS, org=org, repo=repo, )
async def test_get_unchecked_authors(mocker): """ get_unchecked_authors should download the PR body, parse it, filter out checked authors and leave only unchecked ones """ org = "org" repo = "repo" access_token = "all-access" get_release_pr_mock = mocker.async_patch( "lib.get_release_pr", return_value=ReleasePR( body=FAKE_RELEASE_PR_BODY, version="1.2.3", url="http://url", number=234, open=False, ), ) unchecked = await get_unchecked_authors( github_access_token=access_token, org=org, repo=repo, ) assert unchecked == {"Alice Pote"} get_release_pr_mock.assert_called_once_with( github_access_token=access_token, org=org, repo=repo, )
async def test_status_for_repo_last_pr( mocker, test_repo, library_test_repo, has_release_pr, is_library_project, is_open, labels, expected, ): # pylint: disable=too-many-arguments """status_for_repo_last_pr should get the status for the most recent PR for a project""" release_pr = ( ReleasePR("1.2.3", "http://example.com", "body", 12, is_open) if has_release_pr else None ) get_labels_mock = mocker.async_patch("status.get_labels", return_value=labels) repo_info = library_test_repo if is_library_project else test_repo assert ( await status_for_repo_last_pr( github_access_token=GITHUB_TOKEN, repo_info=repo_info, release_pr=release_pr ) == expected ) if not is_library_project and has_release_pr: get_labels_mock.assert_called_once_with( github_access_token=GITHUB_TOKEN, repo_url=repo_info.repo_url, pr_number=release_pr.number, ) else: assert get_labels_mock.called is False
async def test_release(doof, repo_info, event_loop, mocker, command): """ Doof should do a release when asked """ version = '1.2.3' pr = ReleasePR( version=version, url='http://new.url', body='Release PR body', ) get_release_pr_mock = mocker.patch('bot.get_release_pr', autospec=True, side_effect=[None, pr, pr]) release_mock = mocker.patch('bot.release', autospec=True) wait_for_deploy_sync_mock = mocker.Mock() async def wait_for_deploy_fake(*args, **kwargs): """await cannot be used with mock objects""" wait_for_deploy_sync_mock(*args, **kwargs) mocker.patch('bot.wait_for_deploy', wait_for_deploy_fake) authors = ['author1', 'author2'] mocker.patch('bot.get_unchecked_authors', return_value=authors) wait_for_checkboxes_sync_mock = mocker.Mock() async def wait_for_checkboxes_fake(*args, **kwargs): """await cannot be used with mock objects""" wait_for_checkboxes_sync_mock(*args, **kwargs) mocker.patch('bot.wait_for_checkboxes', wait_for_checkboxes_fake) command_words = command.split() + [version] me = 'mitodl_user' await doof.run_command( manager=me, channel_id=repo_info.channel_id, words=command_words, loop=event_loop, ) org, repo = get_org_and_repo(repo_info.repo_url) get_release_pr_mock.assert_any_call(GITHUB_ACCESS, org, repo) release_mock.assert_called_once_with( github_access_token=GITHUB_ACCESS, repo_url=repo_info.repo_url, new_version=pr.version, ) wait_for_deploy_sync_mock.assert_called_once_with( github_access_token=GITHUB_ACCESS, repo_url=repo_info.repo_url, hash_url=repo_info.rc_hash_url, watch_branch='release-candidate', ) assert doof.said("Now deploying to RC...") assert doof.said("These people have commits in this release: {}".format(', '.join(authors))) wait_for_checkboxes_sync_mock.assert_called_once_with(GITHUB_ACCESS, org, repo) assert doof.said( "Release {version} is ready for the Merginator {name}".format( version=pr.version, name=format_user_id(me), ) )
async def test_release_in_progress(doof, test_repo, event_loop, mocker, command): """ If a release is already in progress doof should fail """ version = '1.2.3' url = 'http://fake.release.pr' mocker.patch('bot.get_release_pr', autospec=True, return_value=ReleasePR( version=version, url=url, body='Release PR body', )) command_words = command.split() + [version] with pytest.raises(ReleaseException) as ex: await doof.run_command( manager='mitodl_user', channel_id=test_repo.channel_id, words=command_words, loop=event_loop, ) assert ex.value.args[0] == "A release is already in progress: {}".format( url)
async def test_webhook_finish_release(doof, event_loop, mocker): """ Finish the release """ wait_for_deploy_sync_mock = Mock() async def wait_for_deploy_fake(*args, **kwargs): """await cannot be used with mock objects""" wait_for_deploy_sync_mock(*args, **kwargs) pr_body = ReleasePR( version='version', url='url', body='body', ) get_release_pr_mock = mocker.patch('bot.get_release_pr', autospec=True, return_value=pr_body) finish_release_mock = mocker.patch('bot.finish_release', autospec=True) mocker.patch('bot.wait_for_deploy', wait_for_deploy_fake) await doof.handle_webhook( loop=event_loop, webhook_dict={ "token": "token", "callback_id": FINISH_RELEASE_ID, "channel": { "id": "doof" }, "user": { "id": "doofenshmirtz" }, "message_ts": "123.45", "original_message": { "text": "Doof's original text", } }, ) repo_url = WEB_TEST_REPO_INFO.repo_url hash_url = WEB_TEST_REPO_INFO.prod_hash_url org, repo = get_org_and_repo(repo_url) wait_for_deploy_sync_mock.assert_any_call( github_access_token=doof.github_access_token, hash_url=hash_url, repo_url=repo_url, watch_branch='release', ) get_release_pr_mock.assert_any_call( github_access_token=doof.github_access_token, org=org, repo=repo, ) finish_release_mock.assert_any_call( github_access_token=doof.github_access_token, repo_url=repo_url, version=pr_body.version, timezone=doof.timezone) assert doof.said("Merging...") assert not doof.said("Error")
def test_get_unchecked_authors(): """ get_unchecked_authors should download the PR body, parse it, filter out checked authors and leave only unchecked ones """ org = 'org' repo = 'repo' access_token = 'all-access' with patch('lib.get_release_pr', autospec=True, return_value=ReleasePR( body=FAKE_RELEASE_PR_BODY, version='1.2.3', url='http://url' )) as get_release_pr_mock: unchecked = get_unchecked_authors( github_access_token=access_token, org=org, repo=repo, ) assert unchecked == {"Alice Pote"} get_release_pr_mock.assert_called_once_with( github_access_token=access_token, org=org, repo=repo, )
async def test_release_library(doof, library_test_repo, event_loop, mocker): """Do a library release""" version = '1.2.3' pr = ReleasePR( version=version, url='http://new.url', body='Release PR body', ) get_release_pr_mock = mocker.patch('bot.get_release_pr', autospec=True, side_effect=[None, pr, pr]) release_mock = mocker.patch('bot.release', autospec=True) finish_release_mock = mocker.patch('bot.finish_release', autospec=True) wait_for_travis_sync_mock = mocker.Mock() wait_for_travis_sync_mock.return_value = TRAVIS_SUCCESS async def wait_for_travis_fake(*args, **kwargs): """await cannot be used with mock objects""" return wait_for_travis_sync_mock(*args, **kwargs) mocker.patch('bot.wait_for_travis', wait_for_travis_fake) command_words = ['release', version] me = 'mitodl_user' await doof.run_command( manager=me, channel_id=library_test_repo.channel_id, words=command_words, loop=event_loop, ) org, repo = get_org_and_repo(library_test_repo.repo_url) release_mock.assert_called_once_with( github_access_token=GITHUB_ACCESS, repo_url=library_test_repo.repo_url, new_version=pr.version, ) wait_for_travis_sync_mock.assert_called_once_with( github_access_token=GITHUB_ACCESS, org=org, repo=repo, branch='release-candidate', ) get_release_pr_mock.assert_called_once_with( github_access_token=GITHUB_ACCESS, org=org, repo=repo, ) finish_release_mock.assert_called_once_with( github_access_token=GITHUB_ACCESS, repo_url=library_test_repo.repo_url, version=version, timezone=doof.timezone) assert doof.said( "My evil scheme {version} for {project} has been merged!".format( version=pr.version, project=library_test_repo.name, ))
async def test_release_library(doof, library_test_repo, mocker): """Do a library release""" version = '1.2.3' pr = ReleasePR( version=version, url='http://new.url', body='Release PR body', ) get_release_pr_mock = mocker.async_patch('bot.get_release_pr', side_effect=[None, pr, pr]) release_mock = mocker.async_patch('bot.release') finish_release_mock = mocker.async_patch('bot.finish_release') wait_for_travis_sync_mock = mocker.async_patch('bot.wait_for_travis', return_value=TRAVIS_SUCCESS) command_words = ['release', version] me = 'mitodl_user' await doof.run_command( manager=me, channel_id=library_test_repo.channel_id, words=command_words, ) org, repo = get_org_and_repo(library_test_repo.repo_url) release_mock.assert_called_once_with( github_access_token=GITHUB_ACCESS, repo_url=library_test_repo.repo_url, new_version=pr.version, ) wait_for_travis_sync_mock.assert_called_once_with( github_access_token=GITHUB_ACCESS, org=org, repo=repo, branch='release-candidate', ) get_release_pr_mock.assert_called_once_with( github_access_token=GITHUB_ACCESS, org=org, repo=repo, ) finish_release_mock.assert_called_once_with( github_access_token=GITHUB_ACCESS, repo_url=library_test_repo.repo_url, version=version, timezone=doof.timezone ) assert doof.said( f"Merging evil scheme {pr.version} for {library_test_repo.name}..." ) assert doof.said( f"My evil scheme {pr.version} for {library_test_repo.name} has been released! Waiting for Travis..." ) assert doof.said( "My evil scheme {version} for {project} has been merged!".format( version=pr.version, project=library_test_repo.name, ) )
async def test_release(doof, test_repo, mocker, command): """ Doof should do a release when asked """ version = '1.2.3' pr = ReleasePR( version=version, url='http://new.url', body='Release PR body', ) get_release_pr_mock = mocker.async_patch('bot.get_release_pr', side_effect=[None, pr, pr]) release_mock = mocker.async_patch('bot.release') wait_for_deploy_sync_mock = mocker.async_patch('bot.wait_for_deploy') authors = {'author1', 'author2'} mocker.async_patch('bot.get_unchecked_authors', return_value=authors) wait_for_checkboxes_sync_mock = mocker.async_patch( 'bot.Bot.wait_for_checkboxes') command_words = command.split() + [version] me = 'mitodl_user' await doof.run_command( manager=me, channel_id=test_repo.channel_id, words=command_words, ) org, repo = get_org_and_repo(test_repo.repo_url) get_release_pr_mock.assert_any_call( github_access_token=GITHUB_ACCESS, org=org, repo=repo, ) release_mock.assert_called_once_with( github_access_token=GITHUB_ACCESS, repo_url=test_repo.repo_url, new_version=pr.version, ) wait_for_deploy_sync_mock.assert_called_once_with( github_access_token=GITHUB_ACCESS, repo_url=test_repo.repo_url, hash_url=test_repo.rc_hash_url, watch_branch='release-candidate', ) assert doof.said("Now deploying to RC...") for channel_id in [test_repo.channel_id, ANNOUNCEMENTS_CHANNEL.channel_id]: assert doof.said( "These people have commits in this release", channel_id=channel_id, ) for author in authors: assert doof.said(author, channel_id=channel_id) assert wait_for_checkboxes_sync_mock.called is True
async def test_webhook_finish_release(doof, mocker): """ Finish the release """ pr_body = ReleasePR( version='version', url='url', body='body', ) get_release_pr_mock = mocker.async_patch('bot.get_release_pr', return_value=pr_body) finish_release_mock = mocker.async_patch('bot.finish_release') wait_for_deploy_prod_mock = mocker.async_patch('bot.Bot._wait_for_deploy_prod') await doof.handle_webhook( webhook_dict={ "token": "token", "callback_id": FINISH_RELEASE_ID, "channel": { "id": "doof" }, "user": { "id": "doofenshmirtz" }, "message_ts": "123.45", "original_message": { "text": "Doof's original text", } }, ) repo_url = WEB_TEST_REPO_INFO.repo_url org, repo = get_org_and_repo(repo_url) wait_for_deploy_prod_mock.assert_any_call( doof, repo_info=WEB_TEST_REPO_INFO, ) get_release_pr_mock.assert_any_call( github_access_token=doof.github_access_token, org=org, repo=repo, ) finish_release_mock.assert_any_call( github_access_token=doof.github_access_token, repo_url=repo_url, version=pr_body.version, timezone=doof.timezone ) assert doof.said("Merging...") assert not doof.said("Error")
async def test_finish_release(doof, test_repo, event_loop, mocker): """ Doof should finish a release when asked """ version = '1.2.3' pr = ReleasePR( version=version, url='http://new.url', body='Release PR body', ) get_release_pr_mock = mocker.patch('bot.get_release_pr', autospec=True, return_value=pr) finish_release_mock = mocker.patch('bot.finish_release', autospec=True) wait_for_deploy_sync_mock = mocker.Mock() async def wait_for_deploy_fake(*args, **kwargs): """await cannot be used with mock objects""" wait_for_deploy_sync_mock(*args, **kwargs) mocker.patch('bot.wait_for_deploy', wait_for_deploy_fake) await doof.run_command( manager='mitodl_user', channel_id=test_repo.channel_id, words=['finish', 'release'], loop=event_loop, ) org, repo = get_org_and_repo(test_repo.repo_url) get_release_pr_mock.assert_called_once_with( github_access_token=GITHUB_ACCESS, org=org, repo=repo, ) finish_release_mock.assert_called_once_with( github_access_token=GITHUB_ACCESS, repo_url=test_repo.repo_url, version=version, timezone=doof.timezone) assert doof.said('deploying to production...') wait_for_deploy_sync_mock.assert_called_once_with( github_access_token=GITHUB_ACCESS, repo_url=test_repo.repo_url, hash_url=test_repo.prod_hash_url, watch_branch='release', ) assert doof.said('has been released to production')
async def test_release_library_failure(doof, library_test_repo, event_loop, mocker): """If a library release fails we shouldn't merge it""" version = '1.2.3' pr = ReleasePR( version=version, url='http://new.url', body='Release PR body', ) mocker.patch('bot.get_release_pr', autospec=True, side_effect=[None, pr, pr]) release_mock = mocker.patch('bot.release', autospec=True) finish_release_mock = mocker.patch('bot.finish_release', autospec=True) wait_for_travis_sync_mock = mocker.Mock() wait_for_travis_sync_mock.return_value = TRAVIS_FAILURE async def wait_for_travis_fake(*args, **kwargs): """await cannot be used with mock objects""" return wait_for_travis_sync_mock(*args, **kwargs) mocker.patch('bot.wait_for_travis', wait_for_travis_fake) command_words = ['release', version] me = 'mitodl_user' await doof.run_command( manager=me, channel_id=library_test_repo.channel_id, words=command_words, loop=event_loop, ) org, repo = get_org_and_repo(library_test_repo.repo_url) release_mock.assert_called_once_with( github_access_token=GITHUB_ACCESS, repo_url=library_test_repo.repo_url, new_version=pr.version, ) wait_for_travis_sync_mock.assert_called_once_with( github_access_token=GITHUB_ACCESS, org=org, repo=repo, branch='release-candidate', ) assert finish_release_mock.call_count == 0 assert doof.said( "Uh-oh, it looks like, uh, coffee break's over. During the release Travis had a failure." )
async def test_release_library_failure(doof, library_test_repo, mocker): """If a library release fails we shouldn't merge it""" version = '1.2.3' pr = ReleasePR( version=version, url='http://new.url', body='Release PR body', ) mocker.async_patch('bot.get_release_pr', side_effect=[None, pr, pr]) release_mock = mocker.async_patch('bot.release') finish_release_mock = mocker.async_patch('bot.finish_release') wait_for_travis_sync_mock = mocker.async_patch('bot.wait_for_travis', return_value=TRAVIS_FAILURE) command_words = ['release', version] me = 'mitodl_user' await doof.run_command( manager=me, channel_id=library_test_repo.channel_id, words=command_words, ) org, repo = get_org_and_repo(library_test_repo.repo_url) release_mock.assert_called_once_with( github_access_token=GITHUB_ACCESS, repo_url=library_test_repo.repo_url, new_version=pr.version, ) wait_for_travis_sync_mock.assert_called_once_with( github_access_token=GITHUB_ACCESS, org=org, repo=repo, branch='release-candidate', ) assert finish_release_mock.call_count == 0 assert doof.said( f"Merging evil scheme {pr.version} for {library_test_repo.name}..." ) assert doof.said( "Uh-oh, it looks like, uh, coffee break's over. During the release Travis had a failure." )
async def test_finish_release(doof, mocker, project_type): """ Doof should finish a release when asked """ version = '1.2.3' pr = ReleasePR( version=version, url='http://new.url', body='Release PR body', ) get_release_pr_mock = mocker.async_patch('bot.get_release_pr', return_value=pr) finish_release_mock = mocker.async_patch('bot.finish_release') wait_for_deploy_prod_mock = mocker.async_patch( 'bot.Bot._wait_for_deploy_prod') test_repo = LIBRARY_TEST_REPO_INFO if project_type == LIBRARY_TYPE else WEB_TEST_REPO_INFO await doof.run_command( manager='mitodl_user', channel_id=test_repo.channel_id, words=['finish', 'release'], ) org, repo = get_org_and_repo(test_repo.repo_url) get_release_pr_mock.assert_called_once_with( github_access_token=GITHUB_ACCESS, org=org, repo=repo, ) finish_release_mock.assert_called_once_with( github_access_token=GITHUB_ACCESS, repo_url=test_repo.repo_url, version=version, timezone=doof.timezone) assert doof.said(f"Merged evil scheme {version} for {test_repo.name}!") if project_type == WEB_APPLICATION_TYPE: assert doof.said('deploying to production...') wait_for_deploy_prod_mock.assert_called_once_with(doof, repo_info=test_repo)
async def test_status_for_repo_new_commits( # pylint: disable=too-many-arguments mocker, test_repo, test_repo_directory, has_commits, has_release_pr, is_open ): """status_for_repo_new_commits should check if there are new commits""" release_pr = ( ReleasePR("1.2.3", "http://example.com", "body", 12, is_open) if has_release_pr else None ) init_mock = mocker.patch( "status.init_working_dir", side_effect=async_context_manager_yielder(test_repo_directory), ) get_project_version_mock = mocker.async_patch("status.get_project_version") get_default_branch_mock = mocker.async_patch("status.get_default_branch") any_commits_mock = mocker.async_patch( "status.any_commits_between_branches", return_value=has_commits ) assert ( await status_for_repo_new_commits( github_access_token=GITHUB_TOKEN, repo_info=test_repo, release_pr=release_pr, ) == has_commits ) init_mock.assert_called_once_with(GITHUB_TOKEN, test_repo.repo_url) get_project_version_mock.assert_called_once_with( repo_info=test_repo, working_dir=test_repo_directory ) get_default_branch_mock.assert_called_once_with(test_repo_directory) any_commits_mock.assert_called_once_with( branch1="origin/release-candidate" if has_release_pr and is_open else f"v{get_project_version_mock.return_value}", branch2=get_default_branch_mock.return_value, root=test_repo_directory, )
async def test_finish_release(doof, test_repo, mocker): """ Doof should finish a release when asked """ version = '1.2.3' pr = ReleasePR( version=version, url='http://new.url', body='Release PR body', ) get_release_pr_mock = mocker.async_patch('bot.get_release_pr', return_value=pr) finish_release_mock = mocker.async_patch('bot.finish_release') wait_for_deploy_prod_mock = mocker.async_patch('bot.Bot._wait_for_deploy_prod') await doof.run_command( manager='mitodl_user', channel_id=test_repo.channel_id, words=['finish', 'release'], ) org, repo = get_org_and_repo(test_repo.repo_url) get_release_pr_mock.assert_called_once_with( github_access_token=GITHUB_ACCESS, org=org, repo=repo, ) finish_release_mock.assert_called_once_with( github_access_token=GITHUB_ACCESS, repo_url=test_repo.repo_url, version=version, timezone=doof.timezone ) assert doof.said('deploying to production...') wait_for_deploy_prod_mock.assert_called_once_with( doof, repo_info=test_repo )
async def test_wait_for_checkboxes( mocker, doof, test_repo, speak_initial, has_checkboxes ): """wait_for_checkboxes should poll github, parse checkboxes and see if all are checked""" org, repo = get_org_and_repo(test_repo.repo_url) pr = ReleasePR('version', f'https://github.com/{org}/{repo}/pulls/123456', 'body') get_release_pr_mock = mocker.async_patch('bot.get_release_pr', return_value=pr) get_unchecked_patch = mocker.async_patch('bot.get_unchecked_authors', side_effect=[ {'author1', 'author2', 'author3'}, {'author2'}, set(), ] if has_checkboxes else [set()]) doof.slack_users = [ {"profile": {"real_name": name}, "id": username} for (name, username) in [ ("Author 1", "author1"), ("Author 2", "author2"), ("Author 3", "author3"), ] ] sleep_sync_mock = mocker.async_patch('asyncio.sleep') me = 'mitodl_user' await doof.wait_for_checkboxes( manager=me, repo_info=test_repo, speak_initial=speak_initial, ) if speak_initial: assert doof.said("isn't evil enough until all the checkboxes are checked") get_unchecked_patch.assert_any_call( github_access_token=GITHUB_ACCESS, org=org, repo=repo, ) assert get_unchecked_patch.call_count == (3 if has_checkboxes else 1) assert sleep_sync_mock.call_count == (2 if has_checkboxes else 0) get_release_pr_mock.assert_called_once_with(github_access_token=GITHUB_ACCESS, org=org, repo=repo) if speak_initial or has_checkboxes: assert doof.said( "All checkboxes checked off. Release {version} is ready for the Merginator {name}".format( version=pr.version, name=format_user_id(me), ), attachments=[ { 'actions': [ { 'name': 'finish_release', 'text': 'Finish the release', 'type': 'button', "confirm": { "title": "Are you sure?", "ok_text": "Finish the release", "dismiss_text": "Cancel", } }, ], 'callback_id': 'finish_release', 'fallback': 'Finish the release' } ] ) if speak_initial: assert doof.said(f"PR is up at {pr.url}. These people have commits in this release") if has_checkboxes: assert not doof.said( "Thanks for checking off your boxes <@author1>, <@author2>, <@author3>!" ) assert doof.said( "Thanks for checking off your boxes <@author1>, <@author3>!" ) assert doof.said( "Thanks for checking off your boxes <@author2>!" )
async def test_hotfix_release(doof, test_repo, test_repo_directory, mocker): """ Doof should do a hotfix when asked """ mocker.patch( 'bot.init_working_dir', side_effect=async_context_manager_yielder(test_repo_directory) ) commit_hash = 'uthhg983u4thg9h5' version = '0.1.2' pr = ReleasePR( version=version, url='http://new.url', body='Release PR body', ) get_release_pr_mock = mocker.async_patch('bot.get_release_pr', side_effect=[None, pr, pr]) release_mock = mocker.async_patch('bot.release') wait_for_deploy_sync_mock = mocker.async_patch('bot.wait_for_deploy') authors = {'author1', 'author2'} mocker.async_patch('bot.get_unchecked_authors', return_value=authors) wait_for_checkboxes_sync_mock = mocker.async_patch('bot.Bot.wait_for_checkboxes') old_version = "0.1.1" update_version_mock = mocker.patch('bot.update_version', autospec=True, return_value=old_version) command_words = ['hotfix', commit_hash] me = 'mitodl_user' await doof.run_command( manager=me, channel_id=test_repo.channel_id, words=command_words, ) org, repo = get_org_and_repo(test_repo.repo_url) get_release_pr_mock.assert_any_call( github_access_token=GITHUB_ACCESS, org=org, repo=repo, ) update_version_mock.assert_called_once_with("9.9.9", working_dir=test_repo_directory) release_mock.assert_called_once_with( github_access_token=GITHUB_ACCESS, repo_url=test_repo.repo_url, new_version=pr.version, branch='release', commit_hash=commit_hash, ) wait_for_deploy_sync_mock.assert_called_once_with( github_access_token=GITHUB_ACCESS, repo_url=test_repo.repo_url, hash_url=test_repo.rc_hash_url, watch_branch='release-candidate', ) assert doof.said("Now deploying to RC...") for channel_id in [test_repo.channel_id, ANNOUNCEMENTS_CHANNEL.channel_id]: assert doof.said( "These people have commits in this release: {}".format(', '.join(authors)), channel_id=channel_id, ) assert wait_for_checkboxes_sync_mock.called is True