def test_parse_git_repo(url, result): repo_url = parse_git_repo(potential_url=url) assert repo_url == result
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
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)
def test_parse_git_repo(url, expected): repo_url = parse_git_repo(potential_url=url) assert repo_url == expected
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
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
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)
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, )
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, )
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, )
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, )
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, )