Пример #1
0
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)
Пример #2
0
def run_command(installation_id, event_type, data, comment, rerun=False):
    installation_token = utils.get_installation_token(installation_id)
    if not installation_token:
        return

    pull = mergify_pull.MergifyPull.from_raw(
        installation_id, installation_token, data["pull_request"]
    )

    # Run command only if this is a pending task or if user have permission to do it.
    if (
        rerun
        or data["comment"]["user"]["id"] == config.BOT_USER_ID
        or pull.g_pull.base.repo.get_collaborator_permission(
            data["comment"]["user"]["login"]
        )
        in ["admin", "write"]
    ):
        action = load_action(comment)
        if action:
            command, method = action

            statsd.increment("engine.commands.count", tags=["name:%s" % command])

            report = method.run(
                installation_id, installation_token, event_type, data, pull, []
            )

            if report:
                conclusion, title, summary = report
                if conclusion is None:
                    if rerun:
                        return
                    conclusion = "pending"
                result = "**Command `{command}`: {conclusion}**\n> **{title}**\n{summary}\n".format(
                    command=command,
                    conclusion=conclusion,
                    title=title,
                    summary=("\n> ".join(summary.split("\n"))).strip(),
                )
            else:
                result = "**Command `{}`: success**".format(command)
        else:
            result = UNKNOWN_COMMAND_MESSAGE

        if "@mergifyio" not in comment:  # @mergify have been used instead
            result += "\n\n" + WRONG_ACCOUNT_MESSAGE
    else:
        result = "@{} is not allowed to run commands".format(
            data["comment"]["user"]["login"]
        )

    try:
        pull.g_pull.create_issue_comment(result)
    except github.GithubException as e:  # pragma: no cover
        pull.log.error(
            "fail to post comment on the pull request",
            status=e.status,
            error=e.data["message"],
        )
Пример #3
0
def _handle(installation_id, subscription, branch_rules, event_type, data,
            event_pull_raw):
    installation_token = utils.get_installation_token(installation_id)
    if not installation_token:
        return
    pull = MergifyPullV1.from_raw(installation_id, installation_token,
                                  event_pull_raw)
    MergifyEngine(installation_id, installation_token, subscription,
                  pull.g_pull.base.repo).handle(branch_rules, event_type, data,
                                                pull)
Пример #4
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)
Пример #5
0
def run(event_type, data):
    """Everything starts here."""
    installation_id = data["installation"]["id"]
    installation_token = utils.get_installation_token(installation_id)
    if not installation_token:
        return

    g = github.Github(installation_token,
                      base_url="https://api.%s" % config.GITHUB_DOMAIN)

    if config.LOG_RATELIMIT:  # pragma: no cover
        rate = g.get_rate_limit().rate
        LOG.info("ratelimit: %s/%s, reset at %s",
                 rate.remaining, rate.limit, rate.reset,
                 repository=data["repository"]["name"])

    repo = g.get_repo(data["repository"]["owner"]["login"] + "/" +
                      data["repository"]["name"])

    event_pull = get_github_pull_from_event(repo, event_type, data)

    if not event_pull:  # pragma: no cover
        LOG.info("No pull request found in the event %s, "
                 "ignoring", event_type)
        return

    LOG.info("Pull request found in the event %s", event_type,
             repo=repo.full_name,
             pull_request=event_pull)

    subscription = sub_utils.get_subscription(utils.get_redis_for_cache(),
                                              installation_id)

    if repo.private and not subscription["subscription_active"]:
        check_api.set_check_run(
            event_pull, "Summary",
            "completed", "failure", output={
                "title": "Mergify is disabled",
                "summary": subscription["subscription_reason"],
            })
        return

    if ("base" not in event_pull.raw_data or
            "repo" not in event_pull.raw_data["base"] or
            len(list(event_pull.raw_data["base"]["repo"].keys())) < 70):
        LOG.warning("the pull request payload looks suspicious",
                    event_type=event_type,
                    data=data,
                    pull_request=event_pull.raw_data,
                    repo=repo.fullname)

    if (event_type == "status" and
            event_pull.head.sha != data["sha"]):  # pragma: no cover
        LOG.info("No need to proceed queue (got status of an old commit)",
                 repo=repo.full_name,
                 pull_request=event_pull)
        return

    elif (event_type in ["status", "check_suite", "check_run"] and
          event_pull.merged):  # pragma: no cover
        LOG.info("No need to proceed queue (got status of a merged "
                 "pull request)",
                 repo=repo.full_name,
                 pull_request=event_pull)
        return
    elif (event_type in ["check_suite", "check_run"] and
          event_pull.head.sha != data[event_type]["head_sha"]
          ):  # pragma: no cover
        LOG.info("No need to proceed queue (got %s of an old "
                 "commit)", event_type,
                 repo=repo.full_name,
                 pull_request=event_pull)
        return

    if check_configuration_changes(event_pull):
        LOG.info("Configuration changed, ignoring",
                 repo=repo.full_name,
                 pull_request=event_pull)
        return

    # BRANCH CONFIGURATION CHECKING
    try:
        mergify_config = rules.get_mergify_config(repo)
    except rules.NoRules:  # pragma: no cover
        LOG.info("No need to proceed queue (.mergify.yml is missing)",
                 repo=repo.full_name,
                 pull_request=event_pull)
        return
    except rules.InvalidRules as e:  # pragma: no cover
        # Not configured, post status check with the error message
        if (event_type == "pull_request" and
                data["action"] in ["opened", "synchronize"]):
            check_api.set_check_run(
                event_pull, "Summary", "completed",
                "failure", output={
                    "title": "The Mergify configuration is invalid",
                    "summary": str(e)
                })
        return

    create_metrics(event_type, data)

    v2.handle.s(
        installation_id,
        mergify_config["pull_request_rules"].as_dict(),
        event_type, data, event_pull.raw_data
    ).apply_async()
Пример #6
0
def run(event_type, data):
    """Everything starts here."""
    installation_id = data["installation"]["id"]
    installation_token = utils.get_installation_token(installation_id)
    if not installation_token:
        return

    g = github.Github(installation_token,
                      base_url="https://api.%s" % config.GITHUB_DOMAIN)

    if config.LOG_RATELIMIT:  # pragma: no cover
        rate = g.get_rate_limit().rate
        LOG.info(
            "ratelimit: %s/%s, reset at %s",
            rate.remaining,
            rate.limit,
            rate.reset,
            repository=data["repository"]["name"],
        )

    try:
        repo = g.get_repo(data["repository"]["owner"]["login"] + "/" +
                          data["repository"]["name"])
    except github.UnknownObjectException:  # pragma: no cover
        LOG.info("Repository not found in the event %s, ignoring", event_type)
        return

    event_pull = get_github_pull_from_event(repo, event_type, data)

    if not event_pull:  # pragma: no cover
        LOG.info("No pull request found in the event %s, "
                 "ignoring", event_type)
        return

    # Override pull_request with the updated one
    data["pull_request"] = event_pull.raw_data

    LOG.info(
        "Pull request found in the event %s",
        event_type,
        repo=repo.full_name,
        pull_request=event_pull,
    )

    if ("base" not in event_pull.raw_data
            or "repo" not in event_pull.raw_data["base"]
            or len(list(event_pull.raw_data["base"]["repo"].keys())) < 70):
        LOG.warning(
            "the pull request payload looks suspicious",
            event_type=event_type,
            data=data,
            pull_request=event_pull.raw_data,
            repo=repo.fullname,
        )

    if (event_type == "status"
            and event_pull.head.sha != data["sha"]):  # pragma: no cover
        LOG.info(
            "No need to proceed queue (got status of an old commit)",
            repo=repo.full_name,
            pull_request=event_pull,
        )
        return

    elif (event_type in ["status", "check_suite", "check_run"]
          and event_pull.merged):  # pragma: no cover
        LOG.info(
            "No need to proceed queue (got status of a merged "
            "pull request)",
            repo=repo.full_name,
            pull_request=event_pull,
        )
        return
    elif (event_type in ["check_suite", "check_run"] and event_pull.head.sha !=
          data[event_type]["head_sha"]):  # pragma: no cover
        LOG.info(
            "No need to proceed queue (got %s of an old "
            "commit)",
            event_type,
            repo=repo.full_name,
            pull_request=event_pull,
        )
        return

    if check_configuration_changes(event_pull):
        LOG.info(
            "Configuration changed, ignoring",
            repo=repo.full_name,
            pull_request=event_pull,
        )
        return

    # BRANCH CONFIGURATION CHECKING
    try:
        mergify_config = rules.get_mergify_config(repo)
    except rules.NoRules:  # pragma: no cover
        LOG.info(
            "No need to proceed queue (.mergify.yml is missing)",
            repo=repo.full_name,
            pull_request=event_pull,
        )
        return
    except rules.InvalidRules as e:  # pragma: no cover
        # Not configured, post status check with the error message
        if event_type == "pull_request" and data["action"] in [
                "opened", "synchronize"
        ]:
            check_api.set_check_run(
                event_pull,
                "Summary",
                "completed",
                "failure",
                output={
                    "title": "The Mergify configuration is invalid",
                    "summary": str(e),
                },
            )
        return

    subscription = sub_utils.get_subscription(utils.get_redis_for_cache(),
                                              installation_id)

    if repo.private and not subscription["subscription_active"]:
        check_api.set_check_run(
            event_pull,
            "Summary",
            "completed",
            "failure",
            output={
                "title": "Mergify is disabled",
                "summary": subscription["subscription_reason"],
            },
        )
        return

    # CheckRun are attached to head sha, so when user add commits or force push
    # we can't directly get the previous Mergify Summary. So we copy it here, then
    # anything that looks at it in next celery tasks will find it.
    if event_type == "pull_request" and data["action"] == "synchronize":
        copy_summary_from_previous_head_sha(event_pull, data["before"])

    commands_runner.spawn_pending_commands_tasks(installation_id, event_type,
                                                 data, event_pull)

    if event_type == "issue_comment":
        commands_runner.run_command.s(installation_id, event_type, data,
                                      data["comment"]["body"]).apply_async()
    else:
        actions_runner.handle.s(
            installation_id,
            mergify_config["pull_request_rules"].as_dict(),
            event_type,
            data,
        ).apply_async()
Пример #7
0
def run(event_type, data, subscription):
    """Everything starts here."""
    installation_id = data["installation"]["id"]
    installation_token = utils.get_installation_token(installation_id)
    if not installation_token:
        return

    g = github.Github(installation_token,
                      base_url="https://api.%s" % config.GITHUB_DOMAIN)
    try:
        if config.LOG_RATELIMIT:  # pragma: no cover
            rate = g.get_rate_limit().rate
            LOG.info("ratelimit: %s/%s, reset at %s",
                     rate.remaining,
                     rate.limit,
                     rate.reset,
                     repository=data["repository"]["name"])

        repo = g.get_repo(data["repository"]["owner"]["login"] + "/" +
                          data["repository"]["name"])

        event_pull = get_github_pull_from_event(g, repo, installation_id,
                                                installation_token, event_type,
                                                data)

        if not event_pull:  # pragma: no cover
            LOG.info("No pull request found in the event %s, "
                     "ignoring", event_type)
            return

        LOG.info("Pull request found in the event %s",
                 event_type,
                 repo=repo.full_name,
                 pull_request=event_pull)

        if ("base" not in event_pull.raw_data
                or "repo" not in event_pull.raw_data["base"]
                or len(list(event_pull.raw_data["base"]["repo"].keys())) < 70):
            LOG.warning("the pull request payload looks suspicious",
                        event_type=event_type,
                        data=data,
                        pull_request=event_pull.raw_data,
                        repo=repo.fullname)

        if (event_type == "status"
                and event_pull.head.sha != data["sha"]):  # pragma: no cover
            LOG.info("No need to proceed queue (got status of an old commit)",
                     repo=repo.full_name,
                     pull_request=event_pull)
            return

        elif (event_type in ["status", "check_suite", "check_run"]
              and event_pull.merged):  # pragma: no cover
            LOG.info(
                "No need to proceed queue (got status of a merged "
                "pull request)",
                repo=repo.full_name,
                pull_request=event_pull)
            return
        elif (event_type in ["check_suite", "check_run"]
              and event_pull.head.sha !=
              data[event_type]["head_sha"]):  # pragma: no cover
            LOG.info("No need to proceed queue (got %s of an old "
                     "commit)",
                     event_type,
                     repo=repo.full_name,
                     pull_request=event_pull)
            return

        if check_configuration_changes(event_type, data, event_pull):
            LOG.info("Configuration changed, ignoring",
                     repo=repo.full_name,
                     pull_request=event_pull)
            return

        # BRANCH CONFIGURATION CHECKING
        try:
            mergify_config = rules.get_mergify_config(repo)
        except rules.NoRules:  # pragma: no cover
            LOG.info("No need to proceed queue (.mergify.yml is missing)",
                     repo=repo.full_name,
                     pull_request=event_pull)
            return
        except rules.InvalidRules as e:  # pragma: no cover
            # Not configured, post status check with the error message
            if (event_type == "pull_request"
                    and data["action"] in ["opened", "synchronize"]):
                check_api.set_check_run(
                    event_pull,
                    "current-config-checker",
                    "completed",
                    "failure",
                    output={
                        "title": "The Mergify configuration is invalid",
                        "summary": str(e)
                    })
            return

        create_metrics(event_type, data)

        # NOTE(sileht): At some point we may need to reget the
        # installation_token within each next tasks, in case we reach the
        # expiration
        if "rules" in mergify_config:
            v1.handle.s(installation_id, subscription, mergify_config["rules"],
                        event_type, data, event_pull.raw_data).apply_async()

        elif "pull_request_rules" in mergify_config:
            v2.handle.s(installation_id, subscription,
                        mergify_config["pull_request_rules"].as_dict(),
                        event_type, data, event_pull.raw_data).apply_async()

        else:  # pragma: no cover
            raise RuntimeError("Unexpected configuration version")

    except github.BadCredentialsException:  # pragma: no cover
        LOG.error("token for install %d is no longuer valid (%s)",
                  data["installation"]["id"], data["repository"]["full_name"])
    except github.RateLimitExceededException:  # pragma: no cover
        LOG.error("rate limit reached for install %d (%s)",
                  data["installation"]["id"], data["repository"]["full_name"])