Beispiel #1
0
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}")
Beispiel #2
0
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
Beispiel #3
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,
    )
Beispiel #4
0
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,
    )
Beispiel #5
0
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),
        )
    )
Beispiel #7
0
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)
Beispiel #8
0
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,
    )
Beispiel #10
0
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,
        ))
Beispiel #11
0
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,
        )
    )
Beispiel #12
0
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
Beispiel #13
0
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")
Beispiel #14
0
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')
Beispiel #15
0
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."
    )
Beispiel #16
0
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."
    )
Beispiel #17
0
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)
Beispiel #18
0
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,
    )
Beispiel #19
0
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
    )
Beispiel #20
0
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>!"
        )
Beispiel #21
0
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