def _handle_first_pull_in_queue(queue, pull): _, installation_id, owner, reponame, branch = queue.split("~") old_checks = [c for c in check_api.get_checks(pull.g_pull) if (c.name.endswith(" (merge)") and c._rawData['app']['id'] == config.INTEGRATION_ID)] merge_output = helpers.merge_report(pull) mergeable_state_output = helpers.output_for_mergeable_state(pull, True) if merge_output or mergeable_state_output: remove_pull(pull) conclusion, title, summary = merge_output or mergeable_state_output else: LOG.debug("updating base branch of pull request", pull=pull) redis = utils.get_redis_for_cache() method = redis.get(_get_update_method_cache_key(pull)) or "merge" conclusion, title, summary = helpers.update_pull_base_branch( pull, installation_id, method) if pull.g_pull.state == "closed": remove_pull(pull) elif conclusion == "failure": _move_pull_at_end(pull) status = "completed" if conclusion else "in_progress" for c in old_checks: check_api.set_check_run( pull.g_pull, c.name, status, conclusion, output={"title": title, "summary": summary})
def test_backport_cancelled(self): rules = { "pull_request_rules": [{ "name": "backport", "conditions": ["base=master", "label=backport-3.1"], "actions": { "backport": { "branches": ["stable/3.1"] } }, }] } self.setup_repo(yaml.dump(rules), test_branches=["stable/3.1"]) p, _ = self.create_pr() self.add_label(p, "backport-3.1") p.remove_from_labels("backport-3.1") self.wait_for("pull_request", {"action": "unlabeled"}) checks = list( check_api.get_checks(p, {"check_name": "Rule: backport (backport)"})) self.assertEqual("neutral", checks[0].conclusion) self.assertEqual( "The rule doesn't match anymore, this action has been cancelled", checks[0].output["title"], )
def test_backport_cancelled(self): rules = {'pull_request_rules': [ {"name": "backport", "conditions": [ "base=master", "label=backport-3.1", ], "actions": { "backport": { "branches": ['stable/3.1'], }} } ]} self.setup_repo(yaml.dump(rules), test_branches=['stable/3.1']) p, _ = self.create_pr(check="success") self.add_label_and_push_events(p, "backport-3.1") self.push_events([ ("check_run", {"check_run": {"conclusion": "success"}}), # Summary ("check_run", {"check_run": {"conclusion": None}}), # Backport ]) p.remove_from_labels("backport-3.1") self.push_events([ ("pull_request", {"action": "unlabeled"}), ("check_run", {"check_run": {"conclusion": "success"}}), # Summary # Backport ("check_run", {"check_run": {"conclusion": "cancelled"}}), ], ordered=False) checks = list(check_api.get_checks(p, { "check_name": "Mergify — Rule: backport (backport)"})) self.assertEqual("cancelled", checks[0].conclusion)
def _get_checks(self): generic_checks = set() try: # NOTE(sileht): conclusion can be one of success, failure, neutral, # cancelled, timed_out, or action_required, and None for "pending" generic_checks |= set( [ GenericCheck(c.name, c.conclusion) for c in check_api.get_checks(self.g_pull) ] ) except pygithub.GithubException as e: if ( e.status != 403 or e.data["message"] != "Resource not accessible by integration" ): raise statuses = list( self.client.items( f"commits/{self.data['head']['sha']}/status", list_items="statuses" ) ) # NOTE(sileht): state can be one of error, failure, pending, # or success. generic_checks |= set( [GenericCheck(s["context"], s["state"]) for s in statuses] ) return generic_checks
def handle(installation_id, pull_request_rules_raw, event_type, data): installation_token = utils.get_installation_token(installation_id) if not installation_token: return # Some mandatory rules pull_request_rules_raw["rules"].extend(MERGIFY_RULE["rules"]) pull_request_rules = rules.PullRequestRules(**pull_request_rules_raw) pull = mergify_pull.MergifyPull.from_raw( installation_id, installation_token, data["pull_request"] ) match = pull_request_rules.get_pull_request_rule(pull) checks = dict( (c.name, c) for c in check_api.get_checks(pull.g_pull, mergify_only=True) ) summary_check = checks.get(SUMMARY_NAME) previous_conclusions = load_conclusions(pull, summary_check) conclusions = run_actions( installation_id, installation_token, event_type, data, pull, match, checks, previous_conclusions, ) post_summary(event_type, data, pull, match, summary_check, conclusions)
def report(url): path = url.replace("https://github.com/", "") owner, repo, _, pull_number = path.split("/") integration = github.GithubIntegration(config.INTEGRATION_ID, config.PRIVATE_KEY) install_id = utils.get_installation_id(integration, owner) installation_token = integration.get_access_token(install_id).token g = github.Github(installation_token) r = g.get_repo(owner + "/" + repo) p = r.get_pull(int(pull_number)) print("* CONFIGURATION:") print(r.get_contents(".mergify.yml").decoded_content.decode()) mp = mergify_pull.MergifyPull(p, installation_token) print("* PULL REQUEST:") pprint.pprint(mp.to_dict(), width=160) print("is_behind: %s" % mp.is_behind()) print("* MERGIFY STATUSES:") commit = p.base.repo.get_commit(p.head.sha) for s in commit.get_combined_status().statuses: if s.context.startswith("mergify"): print("[%s]: %s" % (s.context, s.state)) print("* MERGIFY CHECKS:") checks = list(check_api.get_checks(p)) for c in checks: if c.name.startswith("Mergify"): print("[%s]: %s | %s" % (c.name, c.conclusion, c.output.get("title"))) print("> " + "\n> ".join(c.output.get("summary").split("\n"))) return g, p
def test_merge_branch_protection_strict(self): rules = {'pull_request_rules': [ {"name": "merge", "conditions": [ "base=master", "status-success=continuous-integration/fake-ci", ], "actions": { "merge": {} }}, ]} self.setup_repo(yaml.dump(rules)) # Check policy of that branch is the expected one rule = { "protection": { "required_status_checks": { "strict": True, "contexts": ["continuous-integration/fake-ci"], }, "required_pull_request_reviews": None, "restrictions": None, "enforce_admins": False, } } p1, _ = self.create_pr() p2, _ = self.create_pr() p1.merge() self.branch_protection_protect("master", rule) self.push_events([ ("pull_request", {"action": "closed"}), ("check_suite", {"action": "requested"}), # Summary update about manual merge ("check_run", {"check_run": {"conclusion": "success"}}), ], ordered=False) self.create_status_and_push_event(p2) self.push_events([ # Summary ("check_run", {"check_run": {"conclusion": "success"}}), # FIXME(sileht): Why twice ?? # Merge ("check_run", {"check_run": {"conclusion": "failure"}}), # Merge ("check_run", {"check_run": {"conclusion": "failure"}}), ("check_suite", {"action": "completed"}), ], ordered=False) checks = list(check_api.get_checks(p2, { "check_name": "Mergify — Rule: merge (merge)"})) self.assertEqual("failure", checks[0].conclusion) self.assertIn("Branch protection setting 'strict' conflicts with " "Mergify configuration", checks[0].output['title'])
def update_next_pull(installation_id, installation_token, subscription, owner, reponame, branch, key, cur_key): redis = utils.get_redis_for_cache() pull_number = redis.srandmember(key) if not pull_number: LOG.debug("no more pull request to update", installation_id=installation_id, pull_number=pull_number, repo=owner + "/" + reponame, branch=branch) return LOG.debug("next pull to rebase", installation_id=installation_id, pull_number=pull_number, repo=owner + "/" + reponame, branch=branch) pull = mergify_pull.MergifyPull.from_number(installation_id, installation_token, owner, reponame, int(pull_number)) old_checks = [ c for c in check_api.get_checks(pull.g_pull) if (c.name.endswith(" (merge)") and c._rawData['app']['id'] == config.INTEGRATION_ID) ] output = output_for_mergeable_state(pull, True) if output: redis.srem(_get_cache_key(pull), pull.g_pull.number) conclusion, title, summary = output elif pull.g_pull.state == "closed": redis.srem(_get_cache_key(pull), pull.g_pull.number) if pull.g_pull.merged: conclusion = "success" title = "The pull request has been merged manually" summary = ("The pull request has been merged manually " "at *%s*" % pull.g_pull.merge_commit_sha) else: conclusion = "cancelled" title = "The pull request has been closed manually" summary = "" else: conclusion, title, summary = update_pull_base_branch( pull, subscription) redis.set(cur_key, pull_number) status = "completed" if conclusion else "in_progress" for c in old_checks: check_api.set_check_run(pull.g_pull, c.name, status, conclusion, output={ "title": title, "summary": summary })
def test_merge_branch_protection_ci(self): rules = { "pull_request_rules": [{ "name": "merge", "conditions": ["base=master"], "actions": { "merge": {} }, }] } self.setup_repo(yaml.dump(rules)) # Check policy of that branch is the expected one rule = { "protection": { "required_status_checks": { "strict": False, "contexts": ["continuous-integration/fake-ci"], }, "required_pull_request_reviews": None, "restrictions": None, "enforce_admins": False, } } self.branch_protection_protect("master", rule) p, _ = self.create_pr() self.wait_for( "check_run", {"check_run": { "conclusion": None, "status": "in_progress" }}, ) checks = list( check_api.get_checks(p, {"check_name": "Rule: merge (merge)"})) self.assertEqual(None, checks[0].conclusion) self.assertEqual("in_progress", checks[0].status) self.assertIn( "Waiting for the Branch Protection to be validated", checks[0].output["title"], ) self.create_status(p) self.wait_for("pull_request", {"action": "closed"}) pulls = list(self.r_o_admin.get_pulls(state="all")) self.assertEqual(1, len(pulls)) self.assertEqual(1, pulls[0].number) self.assertEqual(True, pulls[0].merged)
def update_next_pull(installation_id, installation_token, owner, reponame, branch, key, cur_key): redis = utils.get_redis_for_cache() pull_number = redis.srandmember(key) if not pull_number: LOG.debug("no more pull request to update", installation_id=installation_id, pull_number=pull_number, repo=owner + "/" + reponame, branch=branch) return LOG.debug("next pull to rebase", installation_id=installation_id, pull_number=pull_number, repo=owner + "/" + reponame, branch=branch) pull = mergify_pull.MergifyPull.from_number(installation_id, installation_token, owner, reponame, int(pull_number)) old_checks = [ c for c in check_api.get_checks(pull.g_pull) if (c.name.endswith(" (merge)") and c._rawData['app']['id'] == config.INTEGRATION_ID) ] merge_output = merge_report(pull) mergeable_state_output = output_for_mergeable_state(pull, True) if merge_output: redis.srem(_get_queue_cache_key(pull), pull.g_pull.number) conclusion, title, summary = merge_output elif mergeable_state_output: redis.srem(_get_queue_cache_key(pull), pull.g_pull.number) conclusion, title, summary = mergeable_state_output else: method = redis.get(_get_update_method_cache_key(pull)) or "merge" conclusion, title, summary = update_pull_base_branch( pull, installation_id, method) if pull.g_pull.state == "closed": redis.srem(_get_queue_cache_key(pull), pull.g_pull.number) else: redis.set(cur_key, pull_number) status = "completed" if conclusion else "in_progress" for c in old_checks: check_api.set_check_run(pull.g_pull, c.name, status, conclusion, output={ "title": title, "summary": summary })
def test_backport_cancelled(self): rules = { 'pull_request_rules': [{ "name": "backport", "conditions": [ "base=master", "label=backport-3.1", ], "actions": { "backport": { "branches": ['stable/3.1'], } } }] } self.setup_repo(yaml.dump(rules), test_branches=['stable/3.1']) p, _ = self.create_pr() self.add_label_and_push_events(p, "backport-3.1") self.push_events([ ("check_run", { "check_run": { "conclusion": None } }), # Backport ]) p.remove_from_labels("backport-3.1") title = ("The rule doesn't match anymore, " "this action has been cancelled") self.push_events([ ("pull_request", { "action": "unlabeled" }), ("check_run", { "check_run": { "conclusion": "neutral", "output": { "title": title } } }), ], ordered=False) checks = list( check_api.get_checks(p, {"check_name": "Rule: backport (backport)"})) self.assertEqual("neutral", checks[0].conclusion) self.assertEqual(title, checks[0].output['title'])
def checks(self): # NOTE(sileht): conclusion can be one of success, failure, neutral, # cancelled, timed_out, or action_required, and None for "pending" checks = dict( (c["name"], c["conclusion"]) for c in check_api.get_checks(self)) # NOTE(sileht): state can be one of error, failure, pending, # or success. checks.update((s["context"], s["state"]) for s in self.client.items( f"commits/{self.pull['head']['sha']}/status", list_items="statuses")) return checks
def test_command_refresh(self): rules = { "pull_request_rules": [{ "name": "nothing", "conditions": ["base!=master"], "actions": { "merge": {} }, }] } self.setup_repo(yaml.dump(rules)) p, commits = self.create_pr() check_api.set_check_run( p, "Summary", "completed", "success", output={ "title": "whatever", "summary": "erased" }, ) checks = list(check_api.get_checks(p)) assert len(checks) == 1 assert checks[0].name == "Summary" completed_at = checks[0].completed_at p.create_issue_comment("@mergifyio refresh") self.wait_for("issue_comment", {"action": "created"}) checks = list(check_api.get_checks(p)) assert len(checks) == 1 assert checks[0].name == "Summary" assert completed_at != checks[0].completed_at p.update() comments = list(p.get_issue_comments()) self.assertEqual("**Command `refresh`: success**", comments[-1].body)
def test_merge_custom_msg(self): rules = { 'pull_request_rules': [ { "name": "Merge on master", "conditions": [ "base=master", "status-success=continuous-integration/fake-ci", ], "actions": { "merge": { "method": "squash" } } }, ] } self.setup_repo(yaml.dump(rules)) msg = "This is the title\n\nAnd this is the message" p, _ = self.create_pr(message="It fixes it\n\n## Commit Message:\n%s" % msg) self.create_status_and_push_event(p) self.push_events([("pull_request", { "action": "closed" }), ("check_run", { "check_run": { "conclusion": "success" } }), ("check_run", { "check_run": { "conclusion": "success" } }), ("check_suite", { "action": "requested" })], ordered=False) pulls = list(self.r_o_admin.get_pulls(state="all")) self.assertEqual(1, len(pulls)) self.assertEqual(1, pulls[0].number) self.assertEqual(True, pulls[0].merged) commit = self.r_o_admin.get_commits()[0].commit self.assertEqual(msg, commit.message) checks = list(check_api.get_checks(p)) assert len(checks) == 2 assert checks[1].name == "Summary" assert msg in checks[1].output["summary"]
def test_merge_branch_protection_ci(self): rules = { 'pull_request_rules': [ { "name": "merge", "conditions": [ "base=master", ], "actions": { "merge": {} } }, ] } self.setup_repo(yaml.dump(rules)) # Check policy of that branch is the expected one rule = { "protection": { "required_status_checks": { "strict": False, "contexts": ["continuous-integration/fake-ci"], }, "required_pull_request_reviews": None, "restrictions": None, "enforce_admins": False, } } self.branch_protection_protect("master", rule) p, _ = self.create_pr() self.push_events([ ("check_suite", { "check_suite": { "conclusion": "failure" } }), ("check_run", { "check_run": { "conclusion": "failure" } }), ]) checks = list( check_api.get_checks(p, {"check_name": "Rule: merge (merge)"})) self.assertEqual("failure", checks[0].conclusion) self.assertIn( "Branch protection settings are blocking " "automatic merging", checks[0].output['title'])
def _handle_first_pull_in_queue(queue, pull): _, installation_id, owner, reponame, branch = queue.split("~") old_checks = [ c for c in check_api.get_checks(pull.g_pull, mergify_only=True) if c.name.endswith(" (merge)") ] output = helpers.merge_report(pull, True) if output: conclusion, title, summary = output LOG.debug( "pull request closed in the meantime", pull=pull, conclusion=conclusion, title=title, summary=summary, ) remove_pull(pull) else: LOG.debug("updating base branch of pull request", pull=pull) redis = utils.get_redis_for_cache() method = redis.get(_get_update_method_cache_key(pull)) or "merge" conclusion, title, summary = helpers.update_pull_base_branch( pull, installation_id, method) if pull.g_pull.state == "closed": LOG.debug( "pull request closed in the meantime", pull=pull, conclusion=conclusion, title=title, summary=summary, ) remove_pull(pull) elif conclusion == "failure": LOG.debug("base branch update failed", pull=pull, title=title, summary=summary) _move_pull_at_end(pull) status = "completed" if conclusion else "in_progress" for c in old_checks: check_api.set_check_run( pull.g_pull, c.name, status, conclusion, output={ "title": title, "summary": summary }, )
def test_change_mergify_yml(self): config = yaml.load(CONFIG) config["rules"]["branches"]["master"]["protection"][ "required_pull_request_reviews"][ "required_approving_review_count"] = 6 config = yaml.dump(config) p1, commits1 = self.create_pr(files={".mergify.yml": config}) checks = list(check_api.get_checks(p1)) assert len(checks) == 2 assert checks[0].name == ("Mergify — disabled due to configuration " "change") assert checks[1].name == "Mergify — future config checker"
def handle(pull_request_rules, pull, sources): match = pull_request_rules.get_pull_request_rule(pull) checks = dict( (c["name"], c) for c in check_api.get_checks(pull, mergify_only=True)) summary_check = checks.get(SUMMARY_NAME) previous_conclusions = load_conclusions(pull, summary_check) conclusions = run_actions(pull, sources, match, checks, previous_conclusions) post_summary(pull, sources, match, summary_check, conclusions)
def test_merge_branch_protection_strict(self): rules = { "pull_request_rules": [{ "name": "merge", "conditions": [ "base=master", "status-success=continuous-integration/fake-ci", ], "actions": { "merge": {} }, }] } self.setup_repo(yaml.dump(rules)) # Check policy of that branch is the expected one rule = { "protection": { "required_status_checks": { "strict": True, "contexts": ["continuous-integration/fake-ci"], }, "required_pull_request_reviews": None, "restrictions": None, "enforce_admins": False, } } p1, _ = self.create_pr() p2, _ = self.create_pr() p1.merge() self.branch_protection_protect("master", rule) self.wait_for("pull_request", {"action": "closed"}) self.create_status(p2) self.wait_for("check_run", {"check_run": {"conclusion": "failure"}}) checks = list( check_api.get_checks(p2, {"check_name": "Rule: merge (merge)"})) self.assertEqual("failure", checks[0].conclusion) self.assertIn( "Branch protection setting 'strict' conflicts with " "Mergify configuration", checks[0].output["title"], )
def test_change_mergify_yml(self): rules = {'pull_request_rules': []} self.setup_repo(yaml.dump(rules)) rules["pull_request_rules"].append( {"name": "foobar", "conditions": ["label!=wip"], "actions": {"merge": {}}} ) p1, commits1 = self.create_pr(files={".mergify.yml": yaml.dump(rules)}) checks = list(check_api.get_checks(p1)) assert len(checks) == 2 assert checks[0].name == ("Mergify — disabled due to configuration " "change") assert checks[1].name == "Mergify — future config checker"
def test_change_mergify_yml(self): rules = {'pull_request_rules': []} self.setup_repo(yaml.dump(rules)) rules["pull_request_rules"].append({ "name": "foobar", "conditions": ["label!=wip"], "actions": { "merge": {} } }) p1, commits1 = self.create_pr(files={".mergify.yml": yaml.dump(rules)}) checks = list(check_api.get_checks(p1)) assert len(checks) == 1 assert checks[0].name == "Summary"
def handle(installation_id, installation_token, subscription, pull_request_rules_raw, event_type, data, pull_raw): pull_request_rules = rules.PullRequestRules(**pull_request_rules_raw) pull = mergify_pull.MergifyPull.from_raw(installation_id, installation_token, pull_raw) match = pull_request_rules.get_pull_request_rule(pull) checks = dict((c.name, c) for c in check_api.get_checks(pull.g_pull) if c._rawData['app']['id'] == config.INTEGRATION_ID) post_summary(pull, match, checks) run_actions(installation_id, installation_token, subscription, event_type, data, pull, match, checks)
def _get_checks(self): generic_checks = set() try: # NOTE(sileht): conclusion can be one of success, failure, neutral, # cancelled, timed_out, or action_required, and None for "pending" generic_checks |= set([ GenericCheck(c.name, c.conclusion) for c in check_api.get_checks(self.g_pull) ]) except github.GithubException as e: if (e.status != 403 or e.data["message"] != "Resource not accessible by integration"): raise # NOTE(sileht): state can be one of error, failure, pending, # or success. generic_checks |= set( [GenericCheck(s.context, s.state) for s in self._get_statuses()]) return generic_checks
def handle(installation_id, pull_request_rules_raw, event_type, data, pull_raw): installation_token = utils.get_installation_token(installation_id) if not installation_token: return # Some mandatory rules pull_request_rules_raw["rules"].extend(MERGIFY_RULE["rules"]) pull_request_rules = rules.PullRequestRules(**pull_request_rules_raw) pull = mergify_pull.MergifyPull.from_raw(installation_id, installation_token, pull_raw) match = pull_request_rules.get_pull_request_rule(pull) checks = dict((c.name, c) for c in check_api.get_checks(pull.g_pull) if c._rawData['app']['id'] == config.INTEGRATION_ID) post_summary(event_type, data, pull, match, checks) run_actions(installation_id, installation_token, event_type, data, pull, match, checks)
def test_change_mergify_yml(self): config = yaml.load(CONFIG) config["rules"]["branches"]["master"]["protection"][ "required_pull_request_reviews"][ "required_approving_review_count"] = 6 config = yaml.dump(config) p1, commits1 = self.create_pr(files={".mergify.yml": config}, status="failure") pulls = self._get_queue("master") self.assertEqual(1, len(pulls)) self.assertEqual(1, pulls[0]._reviews_required) # Check policy of that branch is the expected one expected_rule = { "protection": { "required_status_checks": { "strict": True, "contexts": ["continuous-integration/fake-ci"], }, "required_pull_request_reviews": { "dismiss_stale_reviews": True, "require_code_owner_reviews": False, "required_approving_review_count": 1, }, "restrictions": None, "enforce_admins": False, } } data = branch_protection.get_protection(self.r_main, "master") self.assertTrue(branch_protection.is_configured(self.r_main, "master", expected_rule, data)) p1 = self.r_main.get_pull(p1.number) checks = list(check_api.get_checks(p1, { "check_name": "future-config-checker"})) assert len(checks) == 1 assert checks[0].name == "future-config-checker"
def _test_merge_custom_msg(self, header): rules = { "pull_request_rules": [{ "name": "Merge on master", "conditions": [ "base=master", "status-success=continuous-integration/fake-ci", ], "actions": { "merge": { "method": "squash" } }, }] } self.setup_repo(yaml.dump(rules)) msg = "This is the title\n\nAnd this is the message" p, _ = self.create_pr(message=f"It fixes it\n\n## {header}{msg}") self.create_status(p) self.wait_for("pull_request", {"action": "closed"}) pulls = list(self.r_o_admin.get_pulls(state="all")) self.assertEqual(1, len(pulls)) self.assertEqual(1, pulls[0].number) self.assertEqual(True, pulls[0].merged) commit = self.r_o_admin.get_commits()[0].commit self.assertEqual(msg, commit.message) checks = list(check_api.get_checks(p)) assert len(checks) == 2 assert checks[0].name == "Summary" assert msg in checks[0].output["summary"]
def report(url): redis = utils.get_redis_for_cache() path = url.replace("https://github.com/", "") owner, repo, _, pull_number = path.split("/") integration = github.GithubIntegration(config.INTEGRATION_ID, config.PRIVATE_KEY) install_id = utils.get_installation_id(integration, owner) print("* INSTALLATION ID: %s" % install_id) cached_sub = sub_utils.get_subscription(redis, install_id) db_sub = sub_utils._retrieve_subscription_from_db(install_id) print("* SUBSCRIBED (cache/db): %s / %s" % (cached_sub["subscription_active"], db_sub["subscription_active"])) print("* SUB DETAIL: %s" % db_sub["subscription_reason"]) print("* NUMBER OF CACHED TOKENS: %d" % len(cached_sub["tokens"])) try: for login, token in cached_sub["tokens"].items(): try: repos = get_repositories_setuped(token, install_id) except github.BadCredentialsException: print("** token for %s invalid" % login) except github.GithubException as e: if e.status != 401: raise print("** token for %s invalid" % login) else: if any((r["full_name"] == owner + "/" + repo) for r in repos): print("* MERGIFY INSTALLED AND ENABLED ON THIS REPOSITORY") else: print("* MERGIFY INSTALLED BUT DISABLED " "ON THIS REPOSITORY") break else: print("* MERGIFY DOESN'T HAVE ANY VALID OAUTH TOKENS") except github.UnknownObjectException: print("* MERGIFY SEEMS NOT INSTALLED") installation_token = integration.get_access_token(install_id).token g = github.Github(installation_token, base_url="https://api.%s" % config.GITHUB_DOMAIN) r = g.get_repo(owner + "/" + repo) print("* REPOSITORY IS %s" % "PRIVATE" if r.private else "PUBLIC") p = r.get_pull(int(pull_number)) print("* CONFIGURATION:") print(r.get_contents(".mergify.yml").decoded_content.decode()) mp = mergify_pull.MergifyPull(g, p, install_id) print("* PULL REQUEST:") pprint.pprint(mp.to_dict(), width=160) try: print("is_behind: %s" % mp.is_behind()) except github.GithubException as e: print("Unable to know if pull request branch is behind: %s" % e) print("mergeable_state: %s" % mp.g_pull.mergeable_state) print("* MERGIFY STATUSES:") commit = p.base.repo.get_commit(p.head.sha) for s in commit.get_combined_status().statuses: if s.context.startswith("mergify"): print("[%s]: %s" % (s.context, s.state)) print("* MERGIFY CHECKS:") checks = list(check_api.get_checks(p)) for c in checks: if c._rawData['app']['id'] == config.INTEGRATION_ID: print("[%s]: %s | %s" % (c.name, c.conclusion, c.output.get("title"))) print("> " + "\n> ".join(c.output.get("summary").split("\n"))) return g, p
def report(url): redis = utils.get_redis_for_cache() path = url.replace("https://github.com/", "") try: owner, repo, _, pull_number = path.split("/") except ValueError: print(f"Wrong URL: {url}") return slug = owner + "/" + repo integration = github.GithubIntegration(config.INTEGRATION_ID, config.PRIVATE_KEY) install_id = utils.get_installation_id(integration, owner, repo=repo) print("* INSTALLATION ID: %s" % install_id) cached_sub = sub_utils.get_subscription(redis, install_id) db_sub = sub_utils._retrieve_subscription_from_db(install_id) print("* SUBSCRIBED (cache/db): %s / %s" % (cached_sub["subscription_active"], db_sub["subscription_active"])) report_sub(install_id, slug, cached_sub, "ENGINE-CACHE") report_sub(install_id, slug, db_sub, "DASHBOARD") installation_token = integration.get_access_token(install_id).token g = github.Github(installation_token, base_url="https://api.%s" % config.GITHUB_DOMAIN) r = g.get_repo(owner + "/" + repo) print("* REPOSITORY IS %s" % "PRIVATE" if r.private else "PUBLIC") print("* CONFIGURATION:") try: mergify_config_content = rules.get_mergify_config_content(r) except rules.NoRules: # pragma: no cover print(".mergify.yml is missing") else: print(mergify_config_content.decode()) try: mergify_config = rules.UserConfigurationSchema(mergify_config_content) except rules.InvalidRules as e: # pragma: no cover print("configuration is invalid %s" % str(e)) else: pull_request_rules_raw = mergify_config["pull_request_rules"].as_dict() pull_request_rules_raw["rules"].extend( actions_runner.MERGIFY_RULE["rules"]) pull_request_rules = rules.PullRequestRules(**pull_request_rules_raw) try: p = r.get_pull(int(pull_number)) except github.UnknownObjectException: print("Wrong pull request number") return g, None mp = mergify_pull.MergifyPull(g, p, install_id) print("* PULL REQUEST:") pprint.pprint(mp.to_dict(), width=160) try: print("is_behind: %s" % mp.is_behind()) except github.GithubException as e: print("Unable to know if pull request branch is behind: %s" % e) print("mergeable_state: %s" % mp.g_pull.mergeable_state) print("* MERGIFY LAST CHECKS:") checks = list(check_api.get_checks(p)) for c in checks: if c._rawData["app"]["id"] == config.INTEGRATION_ID: print("[%s]: %s | %s" % (c.name, c.conclusion, c.output.get("title"))) print("> " + "\n> ".join(c.output.get("summary").split("\n"))) print("* MERGIFY LIVE MATCHES:") match = pull_request_rules.get_pull_request_rule(mp) summary_title, summary = actions_runner.gen_summary( "refresh", {}, mp, match) print("> %s" % summary_title) print(summary) return g, p
def report(url): redis = utils.get_redis_for_cache() path = url.replace("https://github.com/", "") owner, repo, _, pull_number = path.split("/") integration = github.GithubIntegration(config.INTEGRATION_ID, config.PRIVATE_KEY) install_id = utils.get_installation_id(integration, owner, repo=repo) print("* INSTALLATION ID: %s" % install_id) cached_sub = sub_utils.get_subscription(redis, install_id) db_sub = sub_utils._retrieve_subscription_from_db(install_id) print("* SUBSCRIBED (cache/db): %s / %s" % (cached_sub["subscription_active"], db_sub["subscription_active"])) print("* SUB DETAIL: %s" % db_sub["subscription_reason"]) print("* NUMBER OF CACHED TOKENS: %d" % len(cached_sub["tokens"])) try: for login, token in cached_sub["tokens"].items(): try: repos = get_repositories_setuped(token, install_id) except github.BadCredentialsException: print("** token for %s invalid" % login) except github.GithubException as e: if e.status != 401: raise print("** token for %s invalid" % login) else: if any((r["full_name"] == owner + "/" + repo) for r in repos): print("* MERGIFY INSTALLED AND ENABLED ON THIS REPOSITORY") else: print("* MERGIFY INSTALLED BUT DISABLED " "ON THIS REPOSITORY") break else: print("* MERGIFY DOESN'T HAVE ANY VALID OAUTH TOKENS") except github.UnknownObjectException: print("* MERGIFY SEEMS NOT INSTALLED") installation_token = integration.get_access_token(install_id).token g = github.Github(installation_token, base_url="https://api.%s" % config.GITHUB_DOMAIN) r = g.get_repo(owner + "/" + repo) print("* REPOSITORY IS %s" % "PRIVATE" if r.private else "PUBLIC") print("* CONFIGURATION:") try: mergify_config_content = rules.get_mergify_config_content(r) except rules.NoRules: # pragma: no cover print(".mergify.yml is missing") print(mergify_config_content.decode()) try: mergify_config = rules.UserConfigurationSchema(mergify_config_content) except rules.InvalidRules as e: # pragma: no cover print("configuration is invalid %s" % str(e)) else: pull_request_rules_raw = mergify_config["pull_request_rules"].as_dict() pull_request_rules_raw["rules"].extend( actions_runner.MERGIFY_RULE["rules"]) pull_request_rules = rules.PullRequestRules(**pull_request_rules_raw) try: p = r.get_pull(int(pull_number)) except github.UnknownObjectException: print("Wrong pull request number") return g, None mp = mergify_pull.MergifyPull(g, p, install_id) print("* PULL REQUEST:") pprint.pprint(mp.to_dict(), width=160) try: print("is_behind: %s" % mp.is_behind()) except github.GithubException as e: print("Unable to know if pull request branch is behind: %s" % e) print("mergeable_state: %s" % mp.g_pull.mergeable_state) print("* MERGIFY LAST CHECKS:") checks = list(check_api.get_checks(p)) for c in checks: if c._rawData["app"]["id"] == config.INTEGRATION_ID: print("[%s]: %s | %s" % (c.name, c.conclusion, c.output.get("title"))) print("> " + "\n> ".join(c.output.get("summary").split("\n"))) print("* MERGIFY LIVE MATCHES:") match = pull_request_rules.get_pull_request_rule(mp) summary_title, summary = actions_runner.gen_summary( "refresh", {}, mp, match) print("> %s" % summary_title) print(summary) return g, p
def report(url): redis = utils.get_redis_for_cache() path = url.replace("https://github.com/", "") try: owner, repo, _, pull_number = path.split("/") except ValueError: print(f"Wrong URL: {url}") return slug = owner + "/" + repo try: installation = github.get_installation(owner, repo) except exceptions.MergifyNotInstalled: print("* Mergify is not installed there") return client = github.get_client(owner, repo, installation) print("* INSTALLATION ID: %s" % client.installation["id"]) cached_sub = sub_utils.get_subscription(redis, client.installation["id"]) db_sub = sub_utils._retrieve_subscription_from_db( client.installation["id"]) print("* SUBSCRIBED (cache/db): %s / %s" % (cached_sub["subscription_active"], db_sub["subscription_active"])) report_sub(client.installation["id"], slug, cached_sub, "ENGINE-CACHE") report_sub(client.installation["id"], slug, db_sub, "DASHBOARD") pull_raw = client.item(f"pulls/{pull_number}") ctxt = mergify_context.MergifyContext(client, pull_raw) print("* REPOSITORY IS %s" % "PRIVATE" if ctxt.pull["base"]["repo"]["private"] else "PUBLIC") print("* CONFIGURATION:") try: mergify_config_content = rules.get_mergify_config_content(ctxt) except rules.NoRules: # pragma: no cover print(".mergify.yml is missing") pull_request_rules = None else: print(mergify_config_content.decode()) try: mergify_config = rules.UserConfigurationSchema( mergify_config_content) except rules.InvalidRules as e: # pragma: no cover print("configuration is invalid %s" % str(e)) else: pull_request_rules_raw = mergify_config[ "pull_request_rules"].as_dict() pull_request_rules_raw["rules"].extend( engine.MERGIFY_RULE["rules"]) pull_request_rules = rules.PullRequestRules( **pull_request_rules_raw) print("* PULL REQUEST:") pprint.pprint(ctxt.to_dict(), width=160) print("is_behind: %s" % ctxt.is_behind) print("mergeable_state: %s" % ctxt.pull["mergeable_state"]) print("* MERGIFY LAST CHECKS:") checks = list(check_api.get_checks(ctxt, mergify_only=True)) for c in checks: print("[%s]: %s | %s" % (c["name"], c["conclusion"], c["output"].get("title"))) print("> " + "\n> ".join(c["output"].get("summary").split("\n"))) if pull_request_rules is not None: print("* MERGIFY LIVE MATCHES:") match = pull_request_rules.get_pull_request_rule(ctxt) summary_title, summary = actions_runner.gen_summary( ctxt, [{ "event_type": "refresh", "data": {} }], match) print("> %s" % summary_title) print(summary) return ctxt