Exemple #1
0
def test_parse_git_repo(url, result):
    repo_url = parse_git_repo(potential_url=url)
    assert repo_url == result
Exemple #2
0
 def hostname(self) -> Optional[str]:
     """
     Hostname of the service.
     """
     parsed_url = parse_git_repo(potential_url=self.instance_url)
     return parsed_url.hostname if parsed_url else None
Exemple #3
0
 def get_project_from_url(self, url: str) -> "GitProject":
     repo_url = parse_git_repo(potential_url=url)
     if not repo_url:
         raise OgrException(f"Cannot parse project url: '{url}'")
     return self.get_project(repo=repo_url.repo,
                             namespace=repo_url.namespace)
Exemple #4
0
def test_parse_git_repo(url, expected):
    repo_url = parse_git_repo(potential_url=url)
    assert repo_url == expected
Exemple #5
0
def get_hostname_or_none(url: str) -> Optional[str]:
    parsed_url = parse_git_repo(potential_url=url)
    if parsed_url:
        return parsed_url.hostname
    return None
Exemple #6
0
 def get_project_from_url(self, url: str) -> "GitProject":
     repo_url = parse_git_repo(potential_url=url)
     project = self.get_project(repo=repo_url.repo,
                                namespace=repo_url.namespace)
     return project
Exemple #7
0
 def get_project_from_url(self, url: str) -> "GitProject":
     repo_url = parse_git_repo(potential_url=url)
     if not repo_url:
         raise OgrException(f"Failed to find repository for url: {url}")
     return self.get_project(repo=repo_url.repo,
                             namespace=repo_url.namespace)
Exemple #8
0
    def parse_merge_request_comment_event(
        event, ) -> Optional[MergeRequestCommentGitlabEvent]:
        """ Look into the provided event and see if it is Gitlab MR comment event. """
        if event.get("object_kind") != "note":
            return None

        merge_request = event.get("merge_request")
        if not merge_request:
            return None

        state = nested_get(event, "merge_request", "state")
        if state != "opened":
            return None

        action = nested_get(event, "merge_request", "action")
        if action not in {"reopen", "update"}:
            action = state

        object_iid = nested_get(event, "merge_request", "iid")
        if not object_iid:
            logger.warning("No object iid from the event.")

        object_id = nested_get(event, "merge_request", "id")
        if not object_id:
            logger.warning("No object id from the event.")

        comment = nested_get(event, "object_attributes", "note")
        logger.info(
            f"Gitlab MR id#{object_id} iid#{object_iid} comment: {comment!r} {action!r} event."
        )

        source_project_url = nested_get(event, "merge_request", "source",
                                        "web_url")
        if not source_project_url:
            logger.warning("Source project url not found in the event.")
            return None
        parsed_source_url = parse_git_repo(potential_url=source_project_url)
        logger.info(f"Source: "
                    f"repo={parsed_source_url.repo} "
                    f"namespace={parsed_source_url.namespace} "
                    f"url={source_project_url}.")

        target_project_url = nested_get(event, "project", "web_url")
        if not target_project_url:
            logger.warning("Target project url not found in the event.")
            return None
        parsed_target_url = parse_git_repo(potential_url=target_project_url)
        logger.info(f"Target: "
                    f"repo={parsed_target_url.repo} "
                    f"namespace={parsed_target_url.namespace} "
                    f"url={target_project_url}.")

        username = nested_get(event, "user", "username")
        if not username:
            logger.warning("No Gitlab username from event.")
            return None

        commit_sha = nested_get(event, "merge_request", "last_commit", "id")
        if not commit_sha:
            logger.warning("No commit_sha from the event.")
            return None

        return MergeRequestCommentGitlabEvent(
            action=GitlabEventAction[action],
            object_id=object_id,
            object_iid=object_iid,
            source_repo_namespace=parsed_source_url.namespace,
            source_repo_name=parsed_source_url.repo,
            target_repo_namespace=parsed_target_url.namespace,
            target_repo_name=parsed_target_url.repo,
            project_url=target_project_url,
            username=username,
            comment=comment,
            commit_sha=commit_sha,
        )
Exemple #9
0
    def parse_gitlab_issue_comment_event(
            event) -> Optional[IssueCommentGitlabEvent]:
        """ Look into the provided event and see if it is Gitlab Issue comment event. """
        if event.get("object_kind") != "note":
            return None

        issue = event.get("issue")
        if not issue:
            return None

        issue_id = nested_get(event, "issue", "id")
        if not issue_id:
            logger.warning("No issue id from the event.")
            return None
        issue_iid = nested_get(event, "issue", "iid")
        if not issue_iid:
            logger.warning("No issue iid from the event.")
            return None
        comment = nested_get(event, "object_attributes", "note")
        if not comment:
            logger.warning("No note from the event.")
            return None

        state = nested_get(event, "issue", "state")
        if not state:
            logger.warning("No state from the event.")
            return None
        if state != "opened":
            return None
        action = nested_get(event, "object_attributes", "action")
        if action not in {"reopen", "update"}:
            action = state

        logger.info(
            f"Gitlab issue ID: {issue_id} IID: {issue_iid} comment: {comment!r} {action!r} event."
        )

        project_url = nested_get(event, "project", "web_url")
        if not project_url:
            logger.warning("Target project url not found in the event.")
            return None
        parsed_url = parse_git_repo(potential_url=project_url)
        logger.info(f"Project: "
                    f"repo={parsed_url.repo} "
                    f"namespace={parsed_url.namespace} "
                    f"url={project_url}.")

        username = nested_get(event, "user", "username")
        if not username:
            logger.warning("No Gitlab username from event.")
            return None

        return IssueCommentGitlabEvent(
            action=GitlabEventAction[action],
            issue_id=issue_id,
            issue_iid=issue_iid,
            repo_namespace=parsed_url.namespace,
            repo_name=parsed_url.repo,
            project_url=project_url,
            username=username,
            comment=comment,
        )
Exemple #10
0
    def parse_gitlab_push_event(event) -> Optional[PushGitlabEvent]:
        """
        Look into the provided event and see if it's one for a new push to the gitlab branch.
        https://docs.gitlab.com/ee/user/project/integrations/webhooks.html#push-events
        """

        if event.get("object_kind") != "push":
            return None

        raw_ref = event.get("ref")
        before = event.get("before")
        pusher = event.get("user_username")

        commits = event.get("commits")

        if not (raw_ref and commits and before and pusher):
            return None
        elif event.get("after").startswith("0000000"):
            logger.info(
                f"GitLab push event on '{raw_ref}' by {pusher} to delete branch"
            )
            return None

        number_of_commits = event.get("total_commits_count")

        if not number_of_commits:
            logger.warning("No number of commits info from event.")

        raw_ref = raw_ref.split("/", maxsplit=2)

        if not raw_ref:
            logger.warning("No ref info from event.")

        ref = raw_ref[-1]

        head_commit = commits[-1]["id"]

        if not raw_ref:
            logger.warning("No commit_id info from event.")

        logger.info(
            f"Gitlab push event on '{raw_ref}': {before[:8]} -> {head_commit[:8]} "
            f"by {pusher} "
            f"({number_of_commits} {'commit' if number_of_commits == 1 else 'commits'})"
        )

        project_url = nested_get(event, "project", "web_url")
        if not project_url:
            logger.warning("Target project url not found in the event.")
            return None
        parsed_url = parse_git_repo(potential_url=project_url)
        logger.info(f"Project: "
                    f"repo={parsed_url.repo} "
                    f"namespace={parsed_url.namespace} "
                    f"url={project_url}.")

        return PushGitlabEvent(
            repo_namespace=parsed_url.namespace,
            repo_name=parsed_url.repo,
            git_ref=ref,
            project_url=project_url,
            commit_sha=head_commit,
        )
Exemple #11
0
    def parse_mr_event(event) -> Optional[MergeRequestGitlabEvent]:
        """ Look into the provided event and see if it's one for a new gitlab MR. """
        if event.get("object_kind") != "merge_request":
            return None

        state = event["object_attributes"]["state"]
        if state != "opened":
            return None
        action = nested_get(event, "object_attributes", "action")
        if action not in {"reopen", "update"}:
            action = state

        username = event["user"]["username"]
        if not username:
            logger.warning("No Gitlab username from event.")
            return None

        object_id = event["object_attributes"]["id"]
        if not object_id:
            logger.warning("No object id from the event.")
            return None

        object_iid = event["object_attributes"]["iid"]
        if not object_iid:
            logger.warning("No object iid from the event.")
            return None

        source_project_url = nested_get(event, "object_attributes", "source",
                                        "web_url")
        if not source_project_url:
            logger.warning("Source project url not found in the event.")
            return None
        parsed_source_url = parse_git_repo(potential_url=source_project_url)
        logger.info(f"Source: "
                    f"repo={parsed_source_url.repo} "
                    f"namespace={parsed_source_url.namespace} "
                    f"url={source_project_url}.")

        target_project_url = nested_get(event, "project", "web_url")
        if not target_project_url:
            logger.warning("Target project url not found in the event.")
            return None
        parsed_target_url = parse_git_repo(potential_url=target_project_url)
        logger.info(f"Target: "
                    f"repo={parsed_target_url.repo} "
                    f"namespace={parsed_target_url.namespace} "
                    f"url={target_project_url}.")

        commit_sha = nested_get(event, "object_attributes", "last_commit",
                                "id")

        return MergeRequestGitlabEvent(
            action=GitlabEventAction[action],
            username=username,
            object_id=object_id,
            object_iid=object_iid,
            source_repo_namespace=parsed_source_url.namespace,
            source_repo_name=parsed_source_url.repo,
            target_repo_namespace=parsed_target_url.namespace,
            target_repo_name=parsed_target_url.repo,
            project_url=target_project_url,
            commit_sha=commit_sha,
        )
Exemple #12
0
    def create_confidential_issue_with_token(self):
        project_data = request.json["project"]

        http_url = project_data["web_url"]
        parsed_url = parse_git_repo(potential_url=http_url)

        project_authentication_issue = ProjectAuthenticationIssueModel.get_project(
            namespace=parsed_url.namespace,
            repo_name=parsed_url.repo,
            project_url=http_url,
        )

        if not project_authentication_issue:
            token_project = jwt.encode(
                {
                    "namespace": parsed_url.namespace,
                    "repo_name": parsed_url.repo
                },
                config.gitlab_token_secret,
                algorithm="HS256",
            ).decode("utf-8")
            token_group = jwt.encode(
                {
                    "namespace": parsed_url.namespace
                },
                config.gitlab_token_secret,
                algorithm="HS256",
            ).decode("utf-8")

            project = config.get_project(url=http_url)
            packit_user = project.service.user.get_username()

            project.create_issue(
                title="Packit-Service Authentication",
                body=
                f"To configure Packit-Service you need to configure a webhook.\n"
                f"Head to {project.get_web_url()}/hooks and add\n"
                "the following Secret token to authenticate requests coming to Packit:\n"
                "```\n"
                f"{token_project}\n"
                "```\n"
                "\n"
                "Or if you want to configure a Group Hook (Gitlab EE) the Secret token would be:\n"
                "```\n"
                f"{token_group}\n"
                "```\n"
                "\n"
                "Packit also needs rights to set commit status to merge requests. Please, grant\n"
                f"[{packit_user}](https://gitlab.com/{packit_user}) user `Developer` permissions\n"
                f"on the {parsed_url.namespace}/{parsed_url.repo} project. "
                "You can add the rights by clicking\n"
                f"[here]({project.get_web_url()}/-/project_members).",
                private=True,
            )

            logger.info("Confidential issue created successfully.")

            ProjectAuthenticationIssueModel.create(
                namespace=parsed_url.namespace,
                repo_name=parsed_url.repo,
                project_url=http_url,
                issue_created=True,
            )