示例#1
0
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"],
        )
示例#3
0
    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)
示例#4
0
    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)
示例#6
0
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
示例#7
0
    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'])
示例#8
0
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)
示例#10
0
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'])
示例#12
0
 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
示例#13
0
    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)
示例#14
0
    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"]
示例#15
0
    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'])
示例#16
0
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
            },
        )
示例#17
0
 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"
示例#18
0
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)
示例#19
0
    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"],
        )
示例#20
0
 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"
示例#21
0
 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"
示例#22
0
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)
示例#23
0
    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
示例#24
0
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)
示例#25
0
    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"
示例#26
0
    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"]
示例#27
0
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
示例#28
0
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
示例#29
0
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
示例#30
0
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