@@ -28,6 +28,14 @@ def __post_init__(self) -> None:
2828
2929 self .gitlab_graphql_url = f"{ gitlab_url } /api/graphql"
3030
31+ async def _query_gitlab_graphql (self , body : dict [str , Any ], header : dict [str , Any ]) -> dict [str , Any ]:
32+ async with httpx .AsyncClient (verify = get_ssl_context (), timeout = 5 ) as client :
33+ resp = await client .post (self .gitlab_graphql_url , json = body , headers = header , timeout = 10 )
34+ if resp .status_code != 200 :
35+ raise errors .BaseError (message = f"Error querying Gitlab api { self .gitlab_graphql_url } : { resp .text } " )
36+ result = cast (dict [str , Any ], resp .json ())
37+ return result
38+
3139 async def filter_projects_by_access_level (
3240 self , user : APIUser , project_ids : list [str ], min_access_level : GitlabAccessLevel
3341 ) -> list [str ]:
@@ -65,18 +73,9 @@ async def filter_projects_by_access_level(
6573 """
6674 }
6775
68- async def _query_gitlab_graphql (body : dict [str , Any ], header : dict [str , Any ]) -> dict [str , Any ]:
69- async with httpx .AsyncClient (verify = get_ssl_context (), timeout = 5 ) as client :
70- resp = await client .post (self .gitlab_graphql_url , json = body , headers = header , timeout = 10 )
71- if resp .status_code != 200 :
72- raise errors .BaseError (message = f"Error querying Gitlab api { self .gitlab_graphql_url } : { resp .text } " )
73- result = cast (dict [str , Any ], resp .json ())
74-
75- if "data" not in result or "projects" not in result ["data" ]:
76- raise errors .BaseError (message = f"Got unexpected response from Gitlab: { result } " )
77- return result
78-
79- resp_body = await _query_gitlab_graphql (body , header )
76+ resp_body = await self ._query_gitlab_graphql (body , header )
77+ if "data" not in resp_body or "projects" not in resp_body ["data" ]:
78+ raise errors .BaseError (message = f"Got unexpected response from Gitlab: { resp_body } " )
8079 result : list [str ] = []
8180
8281 def _process_projects (
@@ -108,12 +107,28 @@ def _process_projects(
108107 }}
109108 """
110109 }
111- resp_body = await _query_gitlab_graphql (body , header )
110+ resp_body = await self ._query_gitlab_graphql (body , header )
111+ if "data" not in resp_body or "projects" not in resp_body ["data" ]:
112+ raise errors .BaseError (message = f"Got unexpected response from Gitlab: { resp_body } " )
112113 page_info = resp_body ["data" ]["projects" ]["pageInfo" ]
113114 _process_projects (resp_body , min_access_level , result )
114115
115116 return result
116117
118+ async def get_project_url_from_path (self , user : APIUser , project_path : str ) -> str | None :
119+ """Get the project ID from the path i.e. from /group1/subgroup2/project3."""
120+ header = {"Content-Type" : "application/json" }
121+ if user .access_token :
122+ header ["Authorization" ] = f"Bearer { user .access_token } "
123+ body = {
124+ "query" : f'{{project(fullPath: "{ project_path } ") {{httpUrlToRepo}}}}' ,
125+ }
126+
127+ resp_body = await self ._query_gitlab_graphql (body , header )
128+ if "data" not in resp_body or "project" not in resp_body ["data" ]:
129+ raise errors .BaseError (message = f"Got unexpected response from Gitlab: { resp_body } " )
130+ return cast (str | None , resp_body ["data" ]["project" ].get ("httpUrlToRepo" ))
131+
117132
118133@dataclass (kw_only = True )
119134class DummyGitlabAPI :
@@ -139,3 +154,7 @@ async def filter_projects_by_access_level(
139154 return []
140155 user_projects = self ._store .get (user .full_name , {}).get (min_access_level , [])
141156 return [p for p in project_ids if p in user_projects ]
157+
158+ async def get_project_url_from_path (self , user : APIUser , project_path : str ) -> str | None :
159+ """Get the project ID from the path i.e. from /group1/subgroup2/project3."""
160+ raise NotImplementedError ()
0 commit comments