This commit is contained in:
parent
51706d2d11
commit
853e99ca5f
21 changed files with 1402 additions and 77 deletions
|
|
@ -14,9 +14,15 @@ class ForgejoClientError(RuntimeError):
|
|||
|
||||
|
||||
class ForgejoClient:
|
||||
def __init__(self, settings: Settings, forgejo_token: str | None = None) -> None:
|
||||
def __init__(
|
||||
self,
|
||||
settings: Settings,
|
||||
forgejo_token: str | None = None,
|
||||
auth_scheme: str = "token",
|
||||
) -> None:
|
||||
self._settings = settings
|
||||
self._forgejo_token = forgejo_token or settings.forgejo_token
|
||||
self._auth_scheme = auth_scheme
|
||||
self._client = httpx.AsyncClient(timeout=settings.forgejo_request_timeout_seconds)
|
||||
|
||||
async def __aenter__(self) -> ForgejoClient:
|
||||
|
|
@ -193,17 +199,76 @@ class ForgejoClient:
|
|||
repo: str,
|
||||
title: str,
|
||||
body: str,
|
||||
label_ids: list[int] | None = None,
|
||||
) -> dict[str, Any]:
|
||||
payload_data: dict[str, object] = {"title": title, "body": body}
|
||||
if label_ids:
|
||||
payload_data["labels"] = label_ids
|
||||
|
||||
payload = await self._request_json(
|
||||
"POST",
|
||||
f"/api/v1/repos/{owner}/{repo}/issues",
|
||||
json_payload={"title": title, "body": body},
|
||||
json_payload=payload_data,
|
||||
auth_required=True,
|
||||
)
|
||||
if isinstance(payload, dict):
|
||||
return payload
|
||||
raise ForgejoClientError(f"Unexpected issue payload for {owner}/{repo}")
|
||||
|
||||
async def ensure_repo_label(
|
||||
self,
|
||||
owner: str,
|
||||
repo: str,
|
||||
name: str,
|
||||
*,
|
||||
color: str,
|
||||
description: str,
|
||||
) -> int:
|
||||
for label in await self.list_repo_labels(owner, repo):
|
||||
if str(label.get("name", "")).strip().casefold() != name.casefold():
|
||||
continue
|
||||
|
||||
label_id = int(label.get("id", 0) or 0)
|
||||
if label_id > 0:
|
||||
return label_id
|
||||
|
||||
label = await self.create_repo_label(
|
||||
owner, repo, name, color=color, description=description
|
||||
)
|
||||
label_id = int(label.get("id", 0) or 0)
|
||||
if label_id <= 0:
|
||||
raise ForgejoClientError(f"Forgejo did not return an id for label {name!r}.")
|
||||
return label_id
|
||||
|
||||
async def list_repo_labels(self, owner: str, repo: str) -> list[dict[str, Any]]:
|
||||
payload = await self._get_json(
|
||||
f"/api/v1/repos/{owner}/{repo}/labels",
|
||||
params={"page": 1, "limit": 100},
|
||||
auth_required=True,
|
||||
)
|
||||
if isinstance(payload, list):
|
||||
return [label for label in payload if isinstance(label, dict)]
|
||||
return []
|
||||
|
||||
async def create_repo_label(
|
||||
self,
|
||||
owner: str,
|
||||
repo: str,
|
||||
name: str,
|
||||
*,
|
||||
color: str,
|
||||
description: str,
|
||||
) -> dict[str, Any]:
|
||||
payload = await self._request_json(
|
||||
"POST",
|
||||
f"/api/v1/repos/{owner}/{repo}/labels",
|
||||
json_payload={"name": name, "color": color, "description": description},
|
||||
auth_required=True,
|
||||
)
|
||||
if isinstance(payload, dict):
|
||||
return payload
|
||||
raise ForgejoClientError(f"Unexpected label payload for {owner}/{repo}")
|
||||
|
||||
async def get_file_content(self, owner: str, repo: str, path: str) -> dict[str, str]:
|
||||
payload = await self._get_json(
|
||||
f"/api/v1/repos/{owner}/{repo}/contents/{path.strip('/')}",
|
||||
|
|
@ -261,7 +326,8 @@ class ForgejoClient:
|
|||
url = path if absolute_url else f"{self._settings.forgejo_base_url}{path}"
|
||||
headers = {}
|
||||
if self._forgejo_token:
|
||||
headers["Authorization"] = f"token {self._forgejo_token}"
|
||||
scheme = "Bearer" if self._auth_scheme.casefold() == "bearer" else "token"
|
||||
headers["Authorization"] = f"{scheme} {self._forgejo_token}"
|
||||
|
||||
response = await self._client.request(
|
||||
method,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue