33from typing import Mapping , Optional
44from urllib .parse import urlparse
55
6+ from socketsecurity .core .git_remote import parse_git_remote
7+
68
79@dataclass (frozen = True )
810class PullRequestContext :
@@ -28,35 +30,6 @@ def _repository_url(value: Optional[str]) -> Optional[str]:
2830 return url if parsed .scheme in ("http" , "https" ) and parsed .netloc else None
2931
3032
31- # git@host:owner/repo - the scp-like syntax urlparse cannot handle. The negative
32- # lookahead keeps scheme-prefixed URLs (https://, ssh://) out of this branch.
33- _SCP_LIKE_REMOTE = re .compile (r"^(?:[^@/]+@)?([^:/]+):(?!//)(.+)$" )
34-
35-
36- def _parse_remote (value : Optional [str ]) -> tuple [Optional [str ], Optional [str ]]:
37- """Split a git remote URL into its host and its ``owner/repo`` path.
38-
39- Providers expose the checkout URL rather than a slug on CI systems that are
40- not tied to a single SCM (Buildkite's ``BUILDKITE_REPO``, for example), so
41- the slug the URL builders need has to be recovered from it. The path is
42- returned whole because GitLab projects can be nested under subgroups.
43- """
44- if not value :
45- return None , None
46- url = value .strip ().rstrip ("/" )
47- if url .endswith (".git" ):
48- url = url [:- 4 ]
49-
50- match = _SCP_LIKE_REMOTE .match (url )
51- if match :
52- return match .group (1 ), match .group (2 ).strip ("/" )
53-
54- parsed = urlparse (url )
55- if parsed .scheme in ("http" , "https" , "ssh" , "git" ) and parsed .hostname :
56- return parsed .hostname , parsed .path .strip ("/" )
57- return None , None
58-
59-
6033def _github_number (env : Mapping [str , str ]) -> int :
6134 number = _positive_int (env .get ("PR_NUMBER" ))
6235 if number :
@@ -66,7 +39,7 @@ def _github_number(env: Mapping[str, str]) -> int:
6639
6740
6841def _github_url (number : int , repo : Optional [str ], env : Mapping [str , str ]) -> Optional [str ]:
69- remote_host , remote_path = _parse_remote (env .get ("BUILDKITE_REPO" ))
42+ remote_host , remote_path = parse_git_remote (env .get ("BUILDKITE_REPO" ))
7043 # config.repo is only ever a bare repository name, so it cannot produce a
7144 # slug on its own; it is kept last for callers that pass a full owner/repo.
7245 repository = env .get ("GITHUB_REPOSITORY" ) or remote_path or repo
@@ -80,7 +53,7 @@ def _github_url(number: int, repo: Optional[str], env: Mapping[str, str]) -> Opt
8053def _gitlab_url (number : int , repo : Optional [str ], env : Mapping [str , str ]) -> Optional [str ]:
8154 project_url = _repository_url (env .get ("CI_PROJECT_URL" ))
8255 if not project_url :
83- remote_host , remote_path = _parse_remote (env .get ("BUILDKITE_REPO" ))
56+ remote_host , remote_path = parse_git_remote (env .get ("BUILDKITE_REPO" ))
8457 project_path = env .get ("CI_PROJECT_PATH" ) or remote_path or repo
8558 server = env .get ("CI_SERVER_URL" ) or (f"https://{ remote_host } " if remote_host else "" )
8659 server = server .rstrip ("/" )
0 commit comments