Skip to content

Commit b562dce

Browse files
committed
gitlab: add avatar method
1 parent 218c466 commit b562dce

File tree

1 file changed

+90
-2
lines changed

1 file changed

+90
-2
lines changed

buildbot_nix/buildbot_nix/gitlab_project.py

+90-2
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
import os
22
import signal
3+
from collections.abc import Generator
34
from pathlib import Path
45
from typing import Any
5-
from urllib.parse import urlparse
6+
from urllib.parse import urlencode, urlparse
67

78
from buildbot.changes.base import ChangeSource
89
from buildbot.config.builder import BuilderConfig
910
from buildbot.plugins import util
1011
from buildbot.reporters.base import ReporterBase
1112
from buildbot.reporters.gitlab import GitLabStatusPush
13+
from buildbot.util import httpclientservice
14+
from buildbot.www import resource
1215
from buildbot.www.auth import AuthBase
1316
from buildbot.www.avatar import AvatarBase
1417
from pydantic import BaseModel
18+
from twisted.internet import defer
1519
from twisted.logger import Logger
1620
from twisted.python import log
1721

@@ -186,7 +190,7 @@ def create_auth(self) -> AuthBase:
186190
raise NotImplementedError
187191

188192
def create_avatar_method(self) -> AvatarBase | None:
189-
return None
193+
return AvatarGitlab(gitlab_base_url=self.config.instance_url)
190194

191195
@property
192196
def reload_builder_name(self) -> str:
@@ -260,6 +264,90 @@ def run_post(self) -> Any:
260264
return util.SUCCESS
261265

262266

267+
class AvatarGitlab(AvatarBase):
268+
name = "gitlab"
269+
270+
gitlab_base_url: str
271+
272+
def __init__(
273+
self,
274+
gitlab_base_url: str,
275+
debug: bool = False,
276+
verify: bool = True,
277+
) -> None:
278+
self.gitlab_base_url = gitlab_base_url
279+
self.debug = debug
280+
self.verify = verify
281+
282+
self.master = None
283+
self.client = None
284+
285+
@defer.inlineCallbacks
286+
def _get_http_client(
287+
self,
288+
) -> Generator[defer.Deferred, None, httpclientservice.HTTPSession]:
289+
if self.client is not None:
290+
return self.client
291+
292+
headers = {
293+
"User-Agent": "Buildbot",
294+
}
295+
296+
self.client = yield httpclientservice.HTTPSession(
297+
self.master.httpservice,
298+
self.gitlab_base_url,
299+
headers=headers,
300+
debug=self.debug,
301+
verify=self.verify,
302+
)
303+
304+
return self.client
305+
306+
@defer.inlineCallbacks
307+
def getUserAvatar( # noqa: N802
308+
self,
309+
email: str,
310+
username: str,
311+
size: str | int,
312+
defaultAvatarUrl: str, # noqa: N803
313+
) -> Generator[defer.Deferred, None, None]:
314+
# avatar_url = self._get_avatar_by_username(username)
315+
if isinstance(size, int):
316+
size = str(size)
317+
avatar_url = yield self._get_avatar_by_email(email, size)
318+
if not avatar_url:
319+
avatar_url = defaultAvatarUrl
320+
raise resource.Redirect(avatar_url)
321+
322+
def _get_avatar_by_username(self, username: str) -> str | None:
323+
qs = urlencode(dict(username=username))
324+
users = paginated_github_request(
325+
f"{self.config.instance_url}/api/v4/users?{qs}"
326+
)
327+
if len(users) == 1:
328+
return users[0]["avatar_url"]
329+
if len(users) > 1:
330+
# TODO: log warning
331+
...
332+
return None
333+
334+
@defer.inlineCallbacks
335+
def _get_avatar_by_email(
336+
self, email: str, size: str | None
337+
) -> Generator[defer.Deferred, None, str | None]:
338+
http = yield self._get_http_client()
339+
q = dict(email=email)
340+
if size is not None:
341+
q["size"] = size
342+
qs = urlencode(q)
343+
res = yield http.get(f"/api/v4/avatar?{qs}")
344+
data = yield res.json()
345+
if "avatar_url" in data:
346+
return data["avatar_url"]
347+
else:
348+
return None
349+
350+
263351
def refresh_projects(config: GitlabConfig, cache_file: Path) -> list[RepoData]:
264352
# access level 40 == Maintainer. See https://docs.gitlab.com/api/members/#roles
265353
return [

0 commit comments

Comments
 (0)