Beispiel #1
0
def test_get_release_pr_no_pulls():
    """If there is no release PR, an exception should be raised"""
    with pytest.raises(Exception) as ex, patch(
            'lib.requests.get',
            return_value=Mock(json=Mock(return_value=FAKE_PULLS))):
        get_release_pr('org', 'repo', 'version')

    assert ex.value.args[0] == "No release pull request on server"
Beispiel #2
0
def test_too_many_releases():
    """If there is no release PR, an exception should be raised"""
    pulls = [RELEASE_PR, RELEASE_PR]
    with pytest.raises(Exception) as ex, patch(
            'lib.requests.get',
            return_value=Mock(json=Mock(return_value=pulls))):
        get_release_pr('org', 'repo', '0.53.3')

    assert ex.value.args[0] == "Too many release pull requests"
Beispiel #3
0
def test_no_release_wrong_repo():
    """If there is no repo accessible, an exception should be raised"""
    response_404 = Response()
    response_404.status_code = 404
    with pytest.raises(HTTPError) as ex, patch('github.requests.get',
                                               return_value=response_404):
        get_release_pr('access_token', 'org', 'repo')

    assert ex.value.response.status_code == 404
Beispiel #4
0
def test_too_many_releases():
    """If there is no release PR, an exception should be raised"""
    pulls = [RELEASE_PR, RELEASE_PR]
    with pytest.raises(Exception) as ex, patch(
            'github.requests.get',
            return_value=Mock(json=Mock(return_value=pulls))):
        get_release_pr('access_token', 'org', 'repo')

    assert ex.value.args[
        0] == "More than one pull request for the branch release-candidate"
Beispiel #5
0
    async def release_command(self, command_args):
        """
        Start a new release and wait for deployment

        Args:
            command_args (CommandArgs): The arguments for this command
        """
        repo_info = command_args.repo_info
        version = command_args.args[0]
        repo_url = repo_info.repo_url
        channel_id = repo_info.channel_id
        org, repo = get_org_and_repo(repo_url)
        pr = get_release_pr(self.github_access_token, org, repo)
        if pr:
            raise ReleaseException(
                "A release is already in progress: {}".format(pr.url))
        release(
            github_access_token=self.github_access_token,
            repo_url=repo_url,
            new_version=version,
        )

        await self.say(
            channel_id=channel_id,
            text=
            "Behold, my new evil scheme - release {version} for {project}! Now deploying to RC..."
            .format(
                version=version,
                project=repo_info.name,
            ),
        )

        await wait_for_deploy(
            github_access_token=self.github_access_token,
            repo_url=repo_url,
            hash_url=repo_info.rc_hash_url,
            watch_branch="release-candidate",
        )
        unchecked_authors = get_unchecked_authors(self.github_access_token,
                                                  org, repo)
        slack_usernames = self.translate_slack_usernames(unchecked_authors)
        pr = get_release_pr(self.github_access_token, org, repo)
        await self.say(
            channel_id=channel_id,
            text=
            "Release {version} for {project} was deployed! PR is up at {pr_url}."
            " These people have commits in this release: {authors}".format(
                version=version,
                authors=", ".join(slack_usernames),
                pr_url=pr.url,
                project=repo_info.name,
            ))

        await self.wait_for_checkboxes(repo_info, command_args.manager)
        command_args.loop.create_task(self.delay_message(repo_info))
Beispiel #6
0
    async def wait_for_checkboxes(self, repo_info, manager):
        """
        Poll the Release PR and wait until all checkboxes are checked off

        Args:
            repo_info (RepoInfo): Information for a repo
            manager (str): User id for the release manager
        """
        channel_id = repo_info.channel_id
        await self.say(
            channel_id=channel_id,
            text=
            "Wait, wait. Time out. My evil plan for {project} isn't evil enough "
            "until all the checkboxes are checked...".format(
                project=repo_info.name, ))
        org, repo = get_org_and_repo(repo_info.repo_url)
        await wait_for_checkboxes(self.github_access_token, org, repo)
        pr = get_release_pr(self.github_access_token, org, repo)
        await self.say(
            channel_id=channel_id,
            text=
            "All checkboxes checked off. Release {version} is ready for the Merginator {name}!"
            .format(name=format_user_id(manager), version=pr.version),
            attachments=[{
                "fallback":
                "Finish the release",
                "callback_id":
                FINISH_RELEASE_ID,
                "actions": [{
                    "name": "finish_release",
                    "text": "Finish the release",
                    "type": "button",
                }]
            }])
Beispiel #7
0
    async def do_release(self, repo_info, version):
        """
        Start a new release and wait for deployment

        Args:
            repo_info (RepoInfo): Information for a repo
            version (str): The version
        """
        repo_url = repo_info.repo_url
        channel_id = repo_info.channel_id
        release(repo_url, version)

        await self.say(
            channel_id,
            "Behold, my new evil scheme - release {}! Now deploying to RC...".
            format(version))

        await wait_for_deploy(repo_url, repo_info.rc_hash_url,
                              "release-candidate")
        org, repo = get_org_and_repo(repo_url)
        unchecked_authors = get_unchecked_authors(org, repo, version)
        slack_usernames = self.translate_slack_usernames(unchecked_authors)
        await self.say(
            channel_id,
            "Release {version} was deployed! PR is up at <{pr_url}|Release {version}>."
            " These people have commits in this release: {authors}".format(
                version=version,
                authors=", ".join(slack_usernames),
                pr_url=get_release_pr(org, repo, version)['html_url'],
            ))
def test_get_release_pr_no_pulls():
    """If there is no release PR it should return None"""
    with patch(
            'github.requests.get', return_value=Mock(json=Mock(return_value=[OTHER_PR]))
    ):
        assert get_release_pr(
            github_access_token='access_token',
            org='org',
            repo='repo-missing',
        ) is None
Beispiel #9
0
    async def _web_application_release(self, command_args):
        """Do a web application release"""
        repo_info = command_args.repo_info
        version = command_args.args[0]
        repo_url = repo_info.repo_url
        channel_id = repo_info.channel_id
        org, repo = get_org_and_repo(repo_url)

        release(
            github_access_token=self.github_access_token,
            repo_url=repo_url,
            new_version=version,
        )
        await self.say(
            channel_id=channel_id,
            text="Behold, my new evil scheme - release {version} for {project}! Now deploying to RC...".format(
                version=version,
                project=repo_info.name,
            ),
        )

        await wait_for_deploy(
            github_access_token=self.github_access_token,
            repo_url=repo_url,
            hash_url=repo_info.rc_hash_url,
            watch_branch="release-candidate",
        )
        unchecked_authors = get_unchecked_authors(
            github_access_token=self.github_access_token,
            org=org,
            repo=repo,
        )
        slack_usernames = self.translate_slack_usernames(unchecked_authors)
        pr = get_release_pr(
            github_access_token=self.github_access_token,
            org=org,
            repo=repo,
        )
        await self.say(
            channel_id=channel_id,
            text="Release {version} for {project} was deployed! PR is up at {pr_url}."
            " These people have commits in this release: {authors}".format(
                version=version,
                authors=", ".join(slack_usernames),
                pr_url=pr.url,
                project=repo_info.name,
            )
        )

        await self.wait_for_checkboxes(repo_info, command_args.manager)
        command_args.loop.create_task(self.delay_message(repo_info))
Beispiel #10
0
    async def finish_release(self, command_args):
        """
        Merge the release candidate into the release branch, tag it, merge to master, and wait for deployment

        Args:
            command_args (CommandArgs): The arguments for this command
        """
        repo_info = command_args.repo_info
        channel_id = repo_info.channel_id
        repo_url = repo_info.repo_url
        org, repo = get_org_and_repo(repo_url)
        pr = get_release_pr(
            github_access_token=self.github_access_token,
            org=org,
            repo=repo,
        )
        if not pr:
            raise ReleaseException("No release currently in progress for {project}".format(project=repo_info.name))
        version = pr.version

        finish_release(
            github_access_token=self.github_access_token,
            repo_url=repo_url,
            version=version,
            timezone=self.timezone
        )

        await self.say(
            channel_id=channel_id,
            text="Merged evil scheme {version} for {project}! Now deploying to production...".format(
                version=version,
                project=repo_info.name,
            ),
        )
        await wait_for_deploy(
            github_access_token=self.github_access_token,
            repo_url=repo_url,
            hash_url=repo_info.prod_hash_url,
            watch_branch="release",
        )
        await self.say(
            channel_id=channel_id,
            text="My evil scheme {version} for {project} has been released to production. "
            "And by 'released', I mean completely...um...leased.".format(
                version=version,
                project=repo_info.name,
            )
        )
Beispiel #11
0
def test_get_release_pr():
    """get_release_pr should grab a release from GitHub's API"""
    org = 'org'
    repo = 'repo'
    version = '0.53.3'

    with patch(
            'lib.requests.get',
            return_value=Mock(json=Mock(return_value=FAKE_PULLS))) as get_mock:
        pulls = get_release_pr(org, repo, version)
    get_mock.assert_called_once_with(
        "https://api.github.com/repos/{org}/{repo}/pulls".format(
            org=org,
            repo=repo,
        ))
    assert pulls == RELEASE_PR
def test_get_release_pr():
    """get_release_pr should grab a release from GitHub's API"""
    org = 'org'
    repo = 'repo'
    access_token = 'access'

    with patch('github.requests.get', return_value=Mock(json=Mock(return_value=FAKE_PULLS))) as get_mock:
        pr = get_release_pr(
            github_access_token=access_token,
            org=org,
            repo=repo,
        )
    get_mock.assert_called_once_with("https://api.github.com/repos/{org}/{repo}/pulls".format(
        org=org,
        repo=repo,
    ), headers=github_auth_headers(access_token))
    assert pr.body == RELEASE_PR['body']
    assert pr.url == RELEASE_PR['html_url']
    assert pr.version == '0.53.3'
Beispiel #13
0
    async def release_command(self, command_args):
        """
        Start a new release and wait for deployment

        Args:
            command_args (CommandArgs): The arguments for this command
        """
        repo_info = command_args.repo_info
        repo_url = repo_info.repo_url
        org, repo = get_org_and_repo(repo_url)
        pr = get_release_pr(
            github_access_token=self.github_access_token,
            org=org,
            repo=repo,
        )
        if pr:
            raise ReleaseException("A release is already in progress: {}".format(pr.url))

        if repo_info.project_type == LIBRARY_TYPE:
            await self._library_release(command_args)
        elif repo_info.project_type == WEB_APPLICATION_TYPE:
            await self._web_application_release(command_args)
        else:
            raise Exception("Configuration error: unknown project type {}".format(repo_info.project_type))