async def have_unexpected_changes( ctxt: context.Context, car: merge_train.TrainCar ) -> bool: if ctxt.pull["base"]["sha"] != car.initial_current_base_sha: ctxt.log.info( "train car has an unexpected base sha change", base_sha=ctxt.pull["base"]["sha"], initial_current_base_sha=car.initial_current_base_sha, ) return True if ctxt.have_been_synchronized(): ctxt.log.info( "train car has unexpectedly been synchronized", ) return True unexpected_event = first( (source for source in ctxt.sources), key=lambda s: s["event_type"] == "pull_request" and typing.cast(github_types.GitHubEventPullRequest, s["data"])["action"] in ["closed", "reopened"], ) if unexpected_event: ctxt.log.debug( "train car received an unexpected event", unexpected_event=unexpected_event, ) return True return False
async def _should_be_cancel(self, ctxt: context.Context, rule: "rules.EvaluatedRule") -> bool: # It's closed, it's not going to change if ctxt.pull["state"] == "closed": return True if ctxt.have_been_synchronized(): return True q = await merge_train.Train.from_context(ctxt) car = q.get_car(ctxt) if car and car.state == "updated": # NOTE(sileht) check first if PR should be removed from the queue pull_rule_checks_status = await self.get_pull_rule_checks_status( ctxt, rule) if pull_rule_checks_status == check_api.Conclusion.FAILURE: return True # NOTE(sileht): This car have been updated/rebased, so we should not cancel # the merge until we have a check that doesn't pass queue_rule_evaluated = await self.queue_rule.get_pull_request_rule( ctxt) queue_rule_checks_status = await merge_train.get_queue_rule_checks_status( ctxt, queue_rule_evaluated) return queue_rule_checks_status == check_api.Conclusion.FAILURE return True
async def run(self, ctxt: context.Context, rule: rules.EvaluatedRule) -> check_api.Result: if ctxt.have_been_synchronized(): # FIXME(sileht): Currently sender id is not the bot by the admin # user that enroll the repo in Mergify, because branch_updater uses # his access_token instead of the Mergify installation token. # As workaround we track in redis merge commit id # This is only true for method="rebase" if await ctxt.redis.get(f"branch-update-{ctxt.pull['head']['sha']}" ): return check_api.Result( check_api.Conclusion.SUCCESS, "Updated by Mergify, ignoring", "", ) try: message = await ctxt.pull_request.render_template( self.config["message"]) except context.RenderTemplateFailure as rmf: return check_api.Result( check_api.Conclusion.FAILURE, "Invalid dismiss reviews message", str(rmf), ) errors = set() for review in (await ctxt.consolidated_reviews())[1]: conf = self.config.get(review["state"].lower(), False) if conf and (conf is True or review["user"]["login"] in conf): try: await ctxt.client.put( f"{ctxt.base_url}/pulls/{ctxt.pull['number']}/reviews/{review['id']}/dismissals", json={"message": message}, ) except http.HTTPClientSideError as e: # pragma: no cover errors.add( f"GitHub error: [{e.status_code}] `{e.message}`") if errors: return check_api.Result( check_api.Conclusion.PENDING, "Unable to dismiss review", "\n".join(errors), ) else: await signals.send(ctxt, "action.dismiss_reviews") return check_api.Result(check_api.Conclusion.SUCCESS, "Review dismissed", "") else: return check_api.Result( check_api.Conclusion.SUCCESS, "Nothing to do, pull request have not been synchronized", "", )
async def _should_be_cancel( self, ctxt: context.Context, rule: "rules.EvaluatedRule" ) -> bool: # It's closed, it's not going to change if ctxt.pull["state"] == "closed": return True if ctxt.have_been_synchronized(): return True pull_rule_checks_status = await self.get_pull_rule_checks_status(ctxt, rule) return pull_rule_checks_status == check_api.Conclusion.FAILURE
async def run(self, ctxt: context.Context, rule: "rules.EvaluatedRule") -> check_api.Result: if not ctxt.subscription.has_feature( subscription.Features.QUEUE_ACTION): return check_api.Result( check_api.Conclusion.ACTION_REQUIRED, "Queue action is disabled", ctxt.subscription.missing_feature_reason( ctxt.pull["base"]["repo"]["owner"]["login"]), ) q = await merge_train.Train.from_context(ctxt) car = q.get_car(ctxt) if car and car.state == "updated": # NOTE(sileht): This car doesn't have tmp pull, so we have the # MERGE_QUEUE_SUMMARY and train reset here need_reset = ctxt.have_been_synchronized() or await ctxt.is_behind if need_reset: status = check_api.Conclusion.PENDING ctxt.log.info("train will be reset") await q.reset() else: queue_rule_evaluated = await self.queue_rule.get_pull_request_rule( ctxt) status = await merge_train.get_queue_rule_checks_status( ctxt, queue_rule_evaluated) await car.update_summaries(status, will_be_reset=need_reset) if ctxt.user_refresh_requested() or ctxt.admin_refresh_requested(): # NOTE(sileht): user ask a refresh, we just remove the previous state of this # check and the method _should_be_queue will become true again :) check = await ctxt.get_engine_check_run( constants.MERGE_QUEUE_SUMMARY_NAME) if check and check_api.Conclusion(check["conclusion"]) not in [ check_api.Conclusion.SUCCESS, check_api.Conclusion.PENDING, ]: await check_api.set_check_run( ctxt, constants.MERGE_QUEUE_SUMMARY_NAME, check_api.Result( check_api.Conclusion.PENDING, "The pull request has been refreshed and is going to be re-embarked soon", "", ), ) return await super().run(ctxt, rule)
def _should_be_cancel( self, ctxt: context.Context, rule: "rules.EvaluatedRule" ) -> bool: # It's closed, it's not going to change if ctxt.pull["state"] == "closed": return True if ctxt.have_been_synchronized(): return True need_look_at_checks = [] for condition in rule.missing_conditions: if condition.attribute_name.startswith( "check-" ) or condition.attribute_name.startswith("status-"): # TODO(sileht): Just return True here, no need to checks checks anymore, # this method is no more used by teh merge queue need_look_at_checks.append(condition) else: # something else does not match anymore return True if need_look_at_checks: if not ctxt.checks: return False states = [ state for name, state in ctxt.checks.items() for cond in need_look_at_checks if cond(FakePR(cond.attribute_name, name)) ] if not states: return False for state in states: if state in ("pending", None): return False return True