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()
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="")
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", )
async def clear_redis_stream(): with utils.aredis_for_stream() as redis_stream: await redis_stream.flushall()
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"}, )