Exemple #1
0
async def redis_stream() -> typing.AsyncGenerator[utils.RedisStream, None]:
    with utils.aredis_for_stream() as client:
        await client.flushdb()
        try:
            yield client
        finally:
            await client.flushdb()
            client.connection_pool.disconnect()
            await utils.stop_pending_aredis_tasks()
Exemple #2
0
 async def run(self, ctxt: context.Context,
               rule: rules.EvaluatedRule) -> check_api.Result:
     with utils.aredis_for_stream() as redis_stream:
         await github_events.send_refresh(
             ctxt.redis,
             redis_stream,
             ctxt.pull["base"]["repo"],
             pull_request_number=ctxt.pull["number"],
         )
     return check_api.Result(check_api.Conclusion.SUCCESS,
                             title="Pull request refreshed",
                             summary="")
Exemple #3
0
    async def _refresh_pulls(
        self,
        repository: github_types.GitHubRepository,
        except_pull_request: typing.Optional[
            github_types.GitHubPullRequestNumber] = None,
    ) -> None:

        with utils.aredis_for_stream() as redis_stream:
            for pull_number in await self.get_pulls():
                if (except_pull_request is not None
                        and except_pull_request == pull_number):
                    continue
                await utils.send_refresh(
                    self.repository.installation.redis,
                    redis_stream,
                    repository,
                    pull_request_number=pull_number,
                    action="internal",
                )
    async def _report_failure(
        self,
        details: str,
        operation: typing.Literal["created", "update"] = "created",
    ) -> None:
        title = "This pull request cannot be embarked for merge"

        if self.queue_pull_request_number is None:
            summary = f"The merge-queue pull request can't be {operation}"
        else:
            summary = f"The merge-queue pull request (#{self.queue_pull_request_number}) can't be prepared"

        summary += f"\nDetails: `{details}`"

        # Update the original Pull Request
        original_ctxt = await self.train.repository.get_pull_request_context(
            self.user_pull_request_number)
        original_ctxt.log.info(
            "pull request cannot be embarked for merge",
            conclusion=check_api.Conclusion.ACTION_REQUIRED,
            title=title,
            summary=summary,
            details=details,
            exc_info=True,
        )
        await check_api.set_check_run(
            original_ctxt,
            constants.MERGE_QUEUE_SUMMARY_NAME,
            check_api.Result(
                check_api.Conclusion.ACTION_REQUIRED,
                title=title,
                summary=summary,
            ),
        )

        with utils.aredis_for_stream() as redis_stream:
            await utils.send_refresh(
                self.train.repository.installation.redis,
                redis_stream,
                original_ctxt.pull["base"]["repo"],
                pull_request_number=original_ctxt.pull["number"],
                action="internal",
            )
Exemple #5
0
 async def clear_redis_stream():
     with utils.aredis_for_stream() as redis_stream:
         await redis_stream.flushall()
Exemple #6
0
    async def update_summaries(
        self,
        conclusion: check_api.Conclusion,
        *,
        queue_rule: typing.Optional[rules.EvaluatedQueueRule] = None,
        will_be_reset: bool = False,
    ) -> None:
        if conclusion == check_api.Conclusion.SUCCESS:
            tmp_pull_title = (
                f"The pull request #{self.user_pull_request_number} is mergeable"
            )
        elif conclusion == check_api.Conclusion.PENDING:
            tmp_pull_title = f"The pull request #{self.user_pull_request_number} is embarked for merge"
        else:
            tmp_pull_title = f"The pull request #{self.user_pull_request_number} cannot be merged and has been disembarked"

        if queue_rule:
            queue_summary = "\n\nRequired conditions for merge:\n"
            for cond in queue_rule.conditions:
                checked = " " if cond in queue_rule.missing_conditions else "X"
                queue_summary += f"\n- [{checked}] `{cond}`"
        else:
            queue_summary = ""

        original_ctxt = await self.train.repository.get_pull_request_context(
            self.user_pull_request_number)

        if self.state == "created":
            summary = f"Embarking {self._get_embarked_refs(markdown=True)} together"
            summary += queue_summary

            if self.queue_pull_request_number is None:
                raise RuntimeError(
                    "car state is created, but queue_pull_request_number is None"
                )

            tmp_pull_ctxt = await self.train.repository.get_pull_request_context(
                self.queue_pull_request_number)

            if queue_rule is not None:
                body = await self.generate_merge_queue_summary(
                    queue_rule, for_queue_pull_request=True)
                await tmp_pull_ctxt.client.patch(
                    f"{tmp_pull_ctxt.base_url}/pulls/{self.queue_pull_request_number}",
                    json={"body": body},
                )

            await tmp_pull_ctxt.set_summary_check(
                check_api.Result(
                    conclusion,
                    title=tmp_pull_title,
                    summary=summary,
                ))

            checks = await tmp_pull_ctxt.pull_check_runs
            statuses = await tmp_pull_ctxt.pull_statuses
            checked_pull = self.queue_pull_request_number
        elif self.state == "updated":
            checks = await original_ctxt.pull_check_runs
            statuses = await original_ctxt.pull_statuses
            checked_pull = self.user_pull_request_number
        else:
            checks = []
            statuses = []
            checked_pull = github_types.GitHubPullRequestNumber(0)

        if checks or statuses:
            checks_copy_summary = (
                "\n\nCheck-runs and statuses of the embarked "
                f"pull request #{checked_pull}:\n\n<table>")
            for check in checks:
                title = ""
                if check["output"]:
                    title = check["output"]["title"]

                check_icon_url = CHECK_ASSERTS.get(check["conclusion"],
                                                   CHECK_ASSERTS["neutral"])

                checks_copy_summary += (
                    "<tr>"
                    f'<td align="center" width="48" height="48"><img src="{check_icon_url}" width="16" height="16" /></td>'
                    f'<td align="center" width="48" height="48"><img src="{check["app"]["owner"]["avatar_url"]}&s=40" width="16" height="16" /></td>'
                    f'<td><b>{check["app"]["name"]}/{check["name"]}</b> — {title}</td>'
                    f'<td><a href="{check["html_url"]}">details</a></td>'
                    "</tr>")

            for status in statuses:
                status_icon_url = CHECK_ASSERTS[status["state"]]

                checks_copy_summary += (
                    "<tr>"
                    f'<td align="center" width="48" height="48"><img src="{status_icon_url}" width="16" height="16" /></td>'
                    f'<td align="center" width="48" height="48"><img src="{status["avatar_url"]}&s=40" width="16" height="16" /></td>'
                    f'<td><b>{status["context"]}</b> — {status["description"]}</td>'
                    f'<td><a href="{status["target_url"]}">details</a></td>'
                    "</tr>")
            checks_copy_summary += "</table>\n"
        else:
            checks_copy_summary = ""

        # Update the original Pull Request
        if will_be_reset:
            # TODO(sileht): display train cars ?
            original_pull_title = "The pull request is going to be re-embarked soon"
        else:
            if conclusion == check_api.Conclusion.SUCCESS:
                original_pull_title = f"The pull request embarked with {self._get_embarked_refs(include_my_self=False)} is mergeable"
            elif conclusion == check_api.Conclusion.PENDING:
                original_pull_title = f"The pull request is embarked with {self._get_embarked_refs(include_my_self=False)} for merge"
            else:
                original_pull_title = f"The pull request embarked with {self._get_embarked_refs(include_my_self=False)} cannot be merged and has been disembarked"

        report = check_api.Result(
            conclusion,
            title=original_pull_title,
            summary=queue_summary + checks_copy_summary,
        )
        original_ctxt.log.info(
            "pull request train car status update",
            conclusion=conclusion.value,
            report=report,
        )
        await check_api.set_check_run(
            original_ctxt,
            constants.MERGE_QUEUE_SUMMARY_NAME,
            report,
        )

        if self.state != "created":
            return

        # NOTE(sileht): refresh it, so the queue action will merge it and delete the
        # tmp_pull_ctxt branch
        with utils.aredis_for_stream() as redis_stream:
            await github_events.send_refresh(
                self.train.repository.installation.redis,
                redis_stream,
                original_ctxt.pull["base"]["repo"],
                pull_request_number=original_ctxt.pull["number"],
                action="internal",
            )

        if conclusion in [
                check_api.Conclusion.SUCCESS, check_api.Conclusion.FAILURE
        ]:
            await tmp_pull_ctxt.client.post(
                f"{tmp_pull_ctxt.base_url}/issues/{self.queue_pull_request_number}/comments",
                json={"body": tmp_pull_title},
            )
            await tmp_pull_ctxt.client.patch(
                f"{tmp_pull_ctxt.base_url}/pulls/{self.queue_pull_request_number}",
                json={"state": "closed"},
            )