Skip to content

Commit

Permalink
Introduce get_created() & get_assigned()
Browse files Browse the repository at this point in the history
  • Loading branch information
ricardobranco777 committed Oct 15, 2023
1 parent 1787009 commit 08265d1
Show file tree
Hide file tree
Showing 9 changed files with 313 additions and 4 deletions.
4 changes: 4 additions & 0 deletions creds-example.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"bugzilla.suse.com": {
"user": "SUSE_BUGZILLA_USER",
"api_key": "SUSE_BUGZILLA_API_KEY"
},
"bugzilla.redhat.com": {
Expand Down Expand Up @@ -30,5 +31,8 @@
},
"code.opensuse.org": {
"token": "PAGURE_TOKEN"
},
"launchpad.net": {
"username": "LAUNCHPAD_USER"
}
}
29 changes: 29 additions & 0 deletions services/bugzilla.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from . import Service, Issue, debugme, status


# Reference: https://bugzilla.readthedocs.io/en/latest/api/index.html#apis
class MyBugzilla(Service):
"""
Bugzilla
Expand All @@ -39,6 +40,34 @@ def __del__(self):
except (AttributeError, BugzillaError):
pass

def _get_issues(self, filters: dict) -> list[Issue]:
return [
self._to_issue(bug) for bug in self.client.query(filters) if bug.is_open
]

def get_assigned(self, username: str = "") -> list[Issue] | None:
"""
Get assigned Bugzilla issues
"""
username = username or self.client.user
try:
user = self.client.getuser(username)
return self._get_issues({"assigned_to": user.email})
except (AttributeError, BugzillaError, RequestException) as exc:
logging.error("Bugzilla: %s: get_assigned(%s): %s", self.url, username, exc)
return None

def get_created(self, username: str = "") -> list[Issue] | None:
"""
Get created Bugzilla issues
"""
try:
user = self.client.getuser(username)
return self._get_issues({"reporter": user.email})
except (AttributeError, BugzillaError, RequestException) as exc:
logging.error("Bugzilla: %s: get_created(%s): %s", self.url, username, exc)
return None

def get_issue(self, issue_id: str = "", **kwargs) -> Issue | None:
"""
Get Bugzilla issue
Expand Down
4 changes: 3 additions & 1 deletion services/gitea.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@


# Reference: https://try.gitea.io/api/swagger
# Not possible to filter issues because of:
# https://github.com/go-gitea/gitea/issues/25979
class MyGitea(Generic):
"""
Gitea
Expand All @@ -23,7 +25,7 @@ def __init__(self, url: str, creds: dict):

def _to_issue(self, info: Any, **kwargs) -> Issue:
repo = kwargs.pop("repo")
is_pr = kwargs.pop("is_pr")
is_pr = bool(kwargs.get("is_pr"))
mark = "!" if is_pr else "#"
return Issue(
tag=f'{self.tag}#{repo}{mark}{info["number"]}',
Expand Down
43 changes: 42 additions & 1 deletion services/github.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
from . import Service, Issue, status


# Reference:
# https://docs.github.com/en/search-github/searching-on-github/searching-issues-and-pull-requests
class MyGithub(Service):
"""
Github
Expand All @@ -34,6 +36,44 @@ def __del__(self):
except (AttributeError, GithubException):
pass

def _get_issues(self, filters: str, is_pr: bool) -> list[Issue]:
issue_type = "pr" if is_pr else "issue"
filters = f"{filters} type:{issue_type}"
return [
self._to_issue(issue, is_pr=is_pr)
for issue in self.client.search_issues(filters)
]

def get_assigned(
self, username: str | None = None, is_pr: bool = False, state: str = "open"
) -> list[Issue] | None:
"""
Get assigned Github issues
"""
try:
user = (
self.client.get_user(username) if username else self.client.get_user()
)
return self._get_issues(f"assignee:{user.login} state:{state}", is_pr)
except (GithubException, RequestException) as exc:
logging.error("Github: get_assigned(%s): %s", username, exc)
return None

def get_created(
self, username: str | None = None, is_pr: bool = False, state: str = "open"
) -> list[Issue] | None:
"""
Get created Github issues
"""
try:
user = (
self.client.get_user(username) if username else self.client.get_user()
)
return self._get_issues(f"author:{user.login} state:{state}", is_pr)
except (GithubException, RequestException) as exc:
logging.error("Github: get_created(%s): %s", username, exc)
return None

def get_issue(self, issue_id: str = "", **kwargs) -> Issue | None:
"""
Get Github issue
Expand All @@ -59,7 +99,8 @@ def get_issue(self, issue_id: str = "", **kwargs) -> Issue | None:
return None
return self._to_issue(info, repo, is_pr)

def _to_issue(self, info: Any, repo: str, is_pr: bool) -> Issue:
def _to_issue(self, info: Any, repo: str = "", is_pr: bool = False) -> Issue:
repo = repo or info.repository.full_name
mark = "!" if is_pr else "#"
return Issue(
tag=f"{self.tag}#{repo}{mark}{info.number}",
Expand Down
51 changes: 51 additions & 0 deletions services/gitlab.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
from . import Service, Issue, debugme, status


# References:
# https://docs.gitlab.com/ee/api/issues.html
# https://docs.gitlab.com/ee/api/merge_requests.html
class MyGitlab(Service):
"""
Gitlab
Expand Down Expand Up @@ -42,6 +45,54 @@ def __del__(self):
except (AttributeError, GitlabError):
pass

def _get_issues(self, **filters) -> list[Issue]:
return [
self._to_issue(issue)
for issue in self.client.issues.list(all=True, **filters)
]

def _get_pullrequests(self, **filters) -> list[Issue]:
return [
self._to_issue(issue)
for issue in self.client.mergerequests.list(all=True, **filters)
]

def get_assigned(
self, username: str | None = None, is_pr: bool = False, state: str = "opened"
) -> list[Issue] | None:
"""
Get assigned Github issues
"""
try:
if username:
user = self.client.users.list(username=username)[0] # type: ignore
else:
user = self.client.user
if is_pr:
return self._get_pullrequests(assignee_id=user.id, state=state)
return self._get_issues(assignee_id=user.id, state=state)
except (GitlabError, RequestException) as exc:
logging.error("Gitlab: %s: get_assigned(%s): %s", self.url, username, exc)
return None

def get_created(
self, username: str | None = None, is_pr: bool = False, state: str = "opened"
) -> list[Issue] | None:
"""
Get created Github issues
"""
try:
if username:
user = self.client.users.list(username=username)[0] # type: ignore
else:
user = self.client.user
if is_pr:
return self._get_pullrequests(author=user.id, state=state)
return self._get_issues(author=user.id, state=state)
except (GitlabError, RequestException) as exc:
logging.error("Gitlab: %s: get_created(%s): %s", self.url, username, exc)
return None

def get_issue(self, issue_id: str = "", **kwargs) -> Issue | None:
"""
Get Gitlab issue
Expand Down
31 changes: 31 additions & 0 deletions services/jira.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,37 @@ def __del__(self):
except AttributeError:
pass

def _get_issues(self, filters: str) -> list[Issue]:
filters = f"{filters} AND resolution IS EMPTY"
data = self.client.jql(filters)
issues = data["issues"]
while len(issues) < data["total"]:
data = self.client.jql(filters, start=len(issues))
issues.extend(data["issues"])
return [self._to_issue(issue) for issue in issues]

def get_assigned(self, username: str = "") -> list[Issue] | None:
"""
Get assigned Jira issues
"""
username = username or self.client.username
try:
return self._get_issues(f"assignee = {username}")
except (ApiError, RequestException) as exc:
logging.error("Jira: %s: get_assigned(%s): %s", self.url, username, exc)
return None

def get_created(self, username: str = "") -> list[Issue] | None:
"""
Get created Jira issues
"""
username = username or self.client.username
try:
return self._get_issues(f"reporter = {username}")
except (ApiError, RequestException) as exc:
logging.error("Jira: %s: get_created(%s): %s", self.url, username, exc)
return None

def get_issue(self, issue_id: str = "", **kwargs) -> Issue | None:
"""
Get Jira ticket
Expand Down
33 changes: 33 additions & 0 deletions services/launchpad.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,39 @@ def __init__(self, url: str, creds: dict):
self.issue_api_url = "https://api.launchpad.net/1.0/{repo}/+bug/{issue}"
self.issue_web_url = f"{self.url}/{{repo}}/+bug/{{issue}}"
self.tag = "lp"
self.username = creds.get("username", "")

# NOTE: Filter closed and PR's
def _get_issues(self, filters: dict) -> list[Issue]:
params = {"ws.op": "searchTasks"} | filters
got = self.session.get("https://api.launchpad.net/1.0/bugs", params=params)
got.raise_for_status()
entries = got.json()["entries"]
return [self._to_issue(entry) for entry in entries]

def get_assigned(self, username: str = "") -> list[Issue] | None:
"""
Get assigned Launchpad issues
"""
username = username or self.username
url = f"https://api.launchpad.net/1.0/~{username}"
try:
return self._get_issues({"assignee": url})
except RequestException as exc:
logging.error("Launchpad: get_assigned(%s): %s", username, exc)
return None

def get_created(self, username: str = "") -> list[Issue] | None:
"""
Get created Launchpad issues
"""
username = username or self.username
url = f"https://api.launchpad.net/1.0/~{username}"
try:
return self._get_issues({"bug_reporter": url})
except RequestException as exc:
logging.error("Launchpad: get_created(%s): %s", username, exc)
return None

def get_issue(self, issue_id: str = "", **kwargs) -> Issue | None:
if not kwargs.get("repo"):
Expand Down
93 changes: 91 additions & 2 deletions services/pagure.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
Pagure
"""

import logging
from typing import Any

from requests.exceptions import RequestException

from utils import utc_date
from . import Generic, Issue, status

Expand All @@ -20,10 +23,96 @@ def __init__(self, url: str, creds: dict):
self.issue_web_url = f"{self.url}/{{repo}}/issue/{{issue}}"
self.pr_api_url = f"{self.url}/api/0/{{repo}}/pull-request/{{issue}}"
self.pr_web_url = f"{self.url}/{{repo}}/pull-request/{{issue}}"
self._username: str | None = None

@property
def username(self) -> str:
"""
Get username
"""
if self._username is None:
try:
response = self.session.post(f"{self.url}/api/0/-/whoami", timeout=10)
response.raise_for_status()
except RequestException as exc:
logging.error("Pagure: %s: whoami(): %s", self.url, exc)
raise
self._username = response.json()["username"]
return self._username

def _get_issues(self, username: str, **params) -> list[Issue]:
if params["assignee"]:
key = "issues_assigned"
next_key = "pagination_issues_assigned"
else:
key = "issues_created"
next_key = "pagination_issues_created"
got = self.session.get(
f"{self.url}/api/0/user/{username}/issues", params=params
)
got.raise_for_status()
data = got.json()
entries = data[key]
while data[next_key]["next"]:
got = self.session.get(data[next_key]["next"], params=params)
got.raise_for_status()
data = got.json()
entries.extend(data[key])
return [self._to_issue(entry) for entry in entries]

def _get_pullrequests(
self, username: str, created: bool = False, state: str = "Open"
) -> list[Issue]:
pr_type = "filed" if created else "actionable"
params = {
"status": state,
}
got = self.session.get(
f"{self.url}/api/0/user/{username}/requests/{pr_type}", params=params
)
got.raise_for_status()
data = got.json()
entries = data["requests"]
while data["pagination"]["next"]:
got = self.session.get(data["pagination"]["next"], params=params)
got.raise_for_status()
data = got.json()
entries.extend(data["requests"])
return [self._to_issue(entry, is_pr=True) for entry in entries]

def get_assigned(
self, username: str = "", is_pr: bool = False, state: str = "Open"
) -> list[Issue] | None:
"""
Get assigned Pagure issues
"""
username = username or self.username
try:
if is_pr:
return self._get_pullrequests(username, created=False, state=state)
return self._get_issues(username, assignee=1, author=0, status=state)
except RequestException as exc:
logging.error("Pagure: %s: get_assigned(%s): %s", self.url, username, exc)
return None

def get_created(
self, username: str, is_pr: bool = False, state: str = "Open"
) -> list[Issue] | None:
"""
Get assigned Pagure issues
"""
username = username or self.username
try:
if is_pr:
return self._get_pullrequests(username, created=True, state=state)
return self._get_issues(username, assignee=0, author=1, status=state)
except RequestException as exc:
logging.error("Pagure: %s: get_created(%s): %s", self.url, username, exc)
return None

def _to_issue(self, info: Any, **kwargs) -> Issue:
repo = kwargs.pop("repo")
is_pr = kwargs.pop("is_pr")
repo = kwargs.get("repo", "") or info["project"]["fullname"]
is_pr = bool(kwargs.get("is_pr"))
mark = "!" if is_pr else "#"
return Issue(
tag=f'{self.tag}#{repo}{mark}{info["id"]}',
Expand Down
Loading

0 comments on commit 08265d1

Please sign in to comment.