Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add base support for forgejo #891

Merged
merged 6 commits into from
Feb 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .packit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,18 @@ jobs:
- fedora-all
- fedora-all-aarch64
- epel-9
additional_repos:
- "copr://packit/packit-dev"
- job: tests
trigger: pull_request
targets:
- fedora-all
- epel-9
tf_extra_params:
environments:
- artifacts:
- type: repository-file
id: https://copr.fedorainfracloud.org/coprs/packit/packit-dev/repo/fedora-$releasever/packit-packit-dev-fedora-$releasever.repo

- job: upstream_koji_build
trigger: pull_request
Expand Down
2 changes: 2 additions & 0 deletions ogr/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
get_service_class,
get_service_class_or_none,
)
from ogr.services.forgejo import ForgejoService
from ogr.services.github import GithubService
from ogr.services.gitlab import GitlabService
from ogr.services.pagure import PagureService
Expand All @@ -26,6 +27,7 @@
GithubService.__name__,
PagureService.__name__,
GitlabService.__name__,
ForgejoService.__name__,
AuthMethod.__name__,
get_project.__name__,
get_service_class.__name__,
Expand Down
15 changes: 13 additions & 2 deletions ogr/abstract.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@

import github
import gitlab
import pyforgejo
import requests

from ogr.deprecation import deprecate_and_set_removal
from ogr.exceptions import (
APIException,
ForgejoAPIException,
GitForgeInternalError,
GithubAPIException,
GitlabAPIException,
Expand Down Expand Up @@ -59,7 +61,11 @@ def __check_for_internal_failure(ex: APIException):


def __wrap_exception(
ex: Union[github.GithubException, gitlab.GitlabError],
ex: Union[
github.GithubException,
gitlab.GitlabError,
pyforgejo.core.api_error.ApiError,
],
) -> APIException:
"""
Wraps uncaught exception in one of ogr exceptions.
Expand All @@ -76,6 +82,7 @@ def __wrap_exception(
MAPPING = {
github.GithubException: GithubAPIException,
gitlab.GitlabError: GitlabAPIException,
pyforgejo.core.api_error.ApiError: ForgejoAPIException,
}

for caught_exception, ogr_exception in MAPPING.items():
Expand Down Expand Up @@ -114,7 +121,11 @@ def wrapper(*args, **kwargs):
) from ex
except APIException as ex:
__check_for_internal_failure(ex)
except (github.GithubException, gitlab.GitlabError) as ex:
except (
github.GithubException,
gitlab.GitlabError,
pyforgejo.core.api_error.ApiError,
) as ex:
__check_for_internal_failure(__wrap_exception(ex))

return wrapper
Expand Down
14 changes: 14 additions & 0 deletions ogr/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import github
import gitlab
import pyforgejo


class OgrException(Exception):
Expand Down Expand Up @@ -66,6 +67,19 @@ def response_code(self):
return self.__cause__.response_code


class ForgejoAPIException(APIException):
"""Exception related to Forgejo API."""

@property
def response_code(self):
if self.__cause__ is None or not isinstance(
self.__cause__,
pyforgejo.core.api_error.ApiError,
):
return None
return self.__cause__.status_code


class OperationNotSupported(OgrException):
"""Raise when the operation is not supported by the backend."""

Expand Down
14 changes: 14 additions & 0 deletions ogr/services/forgejo/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Copyright Contributors to the Packit project.
# SPDX-License-Identifier: MIT

from ogr.services.forgejo.issue import ForgejoIssue
from ogr.services.forgejo.project import ForgejoProject
from ogr.services.forgejo.pull_request import ForgejoPullRequest
from ogr.services.forgejo.service import ForgejoService

__all__ = [
ForgejoPullRequest.__name__,
ForgejoIssue.__name__,
ForgejoProject.__name__,
ForgejoService.__name__,
]
10 changes: 10 additions & 0 deletions ogr/services/forgejo/issue.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Copyright Contributors to the Packit project.
# SPDX-License-Identifier: MIT

from ogr.services import forgejo
from ogr.services.base import BaseIssue


class ForgejoIssue(BaseIssue):
def __init__(self, raw_issue, project: "forgejo.ForgejoProject"):
super().__init__(raw_issue, project)
30 changes: 30 additions & 0 deletions ogr/services/forgejo/project.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Copyright Contributors to the Packit project.
# SPDX-License-Identifier: MIT


from functools import cached_property

from ogr.services import forgejo
from ogr.services.base import BaseGitProject


class ForgejoProject(BaseGitProject):
service: "forgejo.ForgejoService"

def __init__(
self,
repo: str,
service: "forgejo.ForgejoService",
namespace: str,
**kwargs,
):
super().__init__(repo, service, namespace)
self._forgejo_repo = None

@cached_property
def forgejo_repo(self):
namespace = self.namespace or self.service.user.get_username()
return self.service.api.repository.repo_get(
owner=namespace,
repo=self.repo,
)
16 changes: 16 additions & 0 deletions ogr/services/forgejo/pull_request.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Copyright Contributors to the Packit project.
# SPDX-License-Identifier: MIT

from typing import Any

from ogr.services import forgejo
from ogr.services.base import BasePullRequest


class ForgejoPullRequest(BasePullRequest):
def __init__(
self,
raw_pr: Any,
project: "forgejo.ForgejoProject",
):
super().__init__(raw_pr, project)
89 changes: 89 additions & 0 deletions ogr/services/forgejo/service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# Copyright Contributors to the Packit project.
# SPDX-License-Identifier: MIT

from functools import cached_property
from typing import Optional
from urllib.parse import urlparse

from pyforgejo import PyforgejoApi

from ogr.abstract import GitUser
from ogr.exceptions import OgrException
from ogr.factory import use_for_service
from ogr.services.base import BaseGitService
from ogr.services.forgejo.project import ForgejoProject
from ogr.services.forgejo.user import ForgejoUser


@use_for_service("forgejo")
@use_for_service("codeberg.org")
class ForgejoService(BaseGitService):
version = "/api/v1"

def __init__(
self,
instance_url: str = "https://codeberg.org",
api_key: Optional[str] = None,
**kwargs,
):
super().__init__()
self.instance_url = instance_url + self.version
self._token = f"token {api_key}"
self._api = None

@cached_property
def api(self):
return PyforgejoApi(base_url=self.instance_url, api_key=self._token)

def get_project( # type: ignore[override]
self,
repo: str,
namespace: str,
**kwargs,
) -> "ForgejoProject":
return ForgejoProject(
repo=repo,
namespace=namespace,
service=self,
**kwargs,
)

@property
def user(self) -> GitUser:
return ForgejoUser(self)

def project_create(
self,
repo: str,
namespace: Optional[str] = None,
description: Optional[str] = None,
) -> "ForgejoProject":
if namespace:
new_repo = self.api.organization.create_org_repo(
org=namespace,
name=repo,
description=description,
)
else:
new_repo = self.api.repository.create_current_user_repo(
name=repo,
description=description,
)
return ForgejoProject(
repo=repo,
namespace=namespace,
service=self,
github_repo=new_repo,
)

def get_project_from_url(self, url: str) -> "ForgejoProject":
parsed_url = urlparse(url)
path_parts = parsed_url.path.strip("/").split("/")

if len(path_parts) < 2:
raise OgrException(f"Invalid Forgejo URL: {url}")

namespace = path_parts[0]
repo = path_parts[1]

return self.get_project(repo=repo, namespace=namespace)
26 changes: 26 additions & 0 deletions ogr/services/forgejo/user.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Copyright Contributors to the Packit project.
# SPDX-License-Identifier: MIT


from functools import cached_property

from ogr.services import forgejo
from ogr.services.base import BaseGitUser


class ForgejoUser(BaseGitUser):
service: "forgejo.ForgejoService"

def __init__(self, service: "forgejo.ForgejoService") -> None:
super().__init__(service=service)
self._forgejo_user = None

def __str__(self) -> str:
return f'ForgejoUser(username="{self.get_username()}")'

@cached_property
def forgejo_user(self):
return self.service.api.user.get_current()

def get_username(self) -> str:
return self.forgejo_user.login
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ dependencies = [
"PyYAML",
"requests",
"urllib3",
"pyforgejo>=2.0.0",
]

[project.urls]
Expand Down
Loading
Loading