Skip to content

Commit b589984

Browse files
Implement get_commit_comment method and refactor CommitComment (#865)
Implement get_commit_comment method and refactor CommitComment Make the CommitComment inherit from Comment directly to share the common functionality (e.g. adding emojis). Needed for packit/packit-service#2589 RELEASE NOTES BEGIN There is a new method for getting a single commit comment, supporting also retrieval and adding reactions in GitHub. RELEASE NOTES END Reviewed-by: Matej Focko
2 parents fb44e4c + f4889b9 commit b589984

File tree

11 files changed

+1725
-20
lines changed

11 files changed

+1725
-20
lines changed

ogr/abstract.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,18 +1031,21 @@ def edited(self) -> datetime.datetime:
10311031
raise NotImplementedError()
10321032

10331033

1034-
class CommitComment(OgrAbstractClass):
1034+
class CommitComment(Comment):
10351035
"""
10361036
Attributes:
10371037
sha (str): Hash of the related commit.
10381038
body (str): Body of the comment.
10391039
author (str): Login of the author.
10401040
"""
10411041

1042-
def __init__(self, sha: str, body: str, author: str) -> None:
1042+
def __init__(
1043+
self,
1044+
sha: str,
1045+
raw_comment: Any,
1046+
) -> None:
1047+
super().__init__(raw_comment=raw_comment)
10431048
self.sha = sha
1044-
self.body = body
1045-
self.author = author
10461049

10471050
@property # type: ignore
10481051
@deprecate_and_set_removal(
@@ -1875,6 +1878,19 @@ def get_commit_comments(self, commit: str) -> list[CommitComment]:
18751878
"""
18761879
raise NotImplementedError()
18771880

1881+
def get_commit_comment(self, commit_sha: str, comment_id: int) -> CommitComment:
1882+
"""
1883+
Get commit comment.
1884+
1885+
Args:
1886+
commit_sha: SHA of the commit
1887+
comment_id: ID of the commit comment
1888+
1889+
Returns:
1890+
Object representing the commit comment.
1891+
"""
1892+
raise NotImplementedError()
1893+
18781894
def set_commit_status(
18791895
self,
18801896
commit: str,

ogr/read_only.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ def commit_comment(
252252
commit: str,
253253
body: str,
254254
) -> "CommitComment":
255-
return CommitComment(sha=commit, body=body, author=cls.author)
255+
return CommitComment(sha=commit, raw_comment=original_object)
256256

257257
@classmethod
258258
def set_commit_status(

ogr/services/github/comments.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44
import datetime
55
from typing import Union
66

7+
from github.CommitComment import CommitComment as _GithubCommitComment
78
from github.IssueComment import IssueComment as _GithubIssueComment
89
from github.PullRequestComment import PullRequestComment as _GithubPullRequestComment
910
from github.Reaction import Reaction as _Reaction
1011

11-
from ogr.abstract import Comment, IssueComment, PRComment, Reaction
12+
from ogr.abstract import Comment, CommitComment, IssueComment, PRComment, Reaction
1213

1314

1415
class GithubReaction(Reaction):
@@ -24,7 +25,11 @@ def delete(self) -> None:
2425
class GithubComment(Comment):
2526
def _from_raw_comment(
2627
self,
27-
raw_comment: Union[_GithubIssueComment, _GithubPullRequestComment],
28+
raw_comment: Union[
29+
_GithubIssueComment,
30+
_GithubPullRequestComment,
31+
_GithubCommitComment,
32+
],
2833
) -> None:
2934
self._raw_comment = raw_comment
3035
self._id = raw_comment.id
@@ -60,3 +65,8 @@ def __str__(self) -> str:
6065
class GithubPRComment(GithubComment, PRComment):
6166
def __str__(self) -> str:
6267
return "Github" + super().__str__()
68+
69+
70+
class GithubCommitComment(GithubComment, CommitComment):
71+
def __str__(self) -> str:
72+
return "Github" + super().__str__()

ogr/services/github/project.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import github
99
from github import UnknownObjectException
1010
from github.Commit import Commit
11-
from github.CommitComment import CommitComment as GithubCommitComment
11+
from github.CommitComment import CommitComment as _GithubCommitComment
1212
from github.GithubException import GithubException
1313
from github.Repository import Repository
1414

@@ -34,6 +34,7 @@
3434
GithubCheckRunResult,
3535
GithubCheckRunStatus,
3636
)
37+
from ogr.services.github.comments import GithubCommitComment
3738
from ogr.services.github.flag import GithubCommitFlag
3839
from ogr.services.github.issue import GithubIssue
3940
from ogr.services.github.pull_request import GithubPullRequest
@@ -345,11 +346,10 @@ def commit_comment(
345346

346347
@staticmethod
347348
def _commit_comment_from_github_object(
348-
raw_commit_coment: GithubCommitComment,
349+
raw_commit_coment: _GithubCommitComment,
349350
) -> CommitComment:
350-
return CommitComment(
351-
body=raw_commit_coment.body,
352-
author=raw_commit_coment.user.login,
351+
return GithubCommitComment(
352+
raw_comment=raw_commit_coment,
353353
sha=raw_commit_coment.commit_id,
354354
)
355355

@@ -360,6 +360,11 @@ def get_commit_comments(self, commit: str) -> list[CommitComment]:
360360
for comment in github_commit.get_comments()
361361
]
362362

363+
def get_commit_comment(self, commit_sha: str, comment_id: int) -> CommitComment:
364+
return self._commit_comment_from_github_object(
365+
self.github_repo.get_comment(comment_id),
366+
)
367+
363368
@if_readonly(
364369
return_function=GitProjectReadOnly.set_commit_status,
365370
log_message="Create a status on a commit",

ogr/services/gitlab/comments.py

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,25 @@
77

88
import gitlab.exceptions
99
from gitlab.v4.objects import (
10+
ProjectCommitComment,
11+
ProjectCommitDiscussionNote,
1012
ProjectIssueNote,
1113
ProjectIssueNoteAwardEmoji,
1214
ProjectMergeRequestAwardEmoji,
1315
ProjectMergeRequestNote,
1416
)
1517

16-
from ogr.abstract import Comment, IssueComment, PRComment, Reaction
17-
from ogr.exceptions import GitlabAPIException
18+
from ogr.abstract import Comment, CommitComment, IssueComment, PRComment, Reaction
19+
from ogr.exceptions import GitlabAPIException, OperationNotSupported
1820

1921
logger = logging.getLogger(__name__)
2022

2123

2224
class GitlabReaction(Reaction):
23-
_raw_reaction: Union[ProjectIssueNoteAwardEmoji, ProjectMergeRequestAwardEmoji]
25+
_raw_reaction: Union[
26+
ProjectIssueNoteAwardEmoji,
27+
ProjectMergeRequestAwardEmoji,
28+
]
2429

2530
def __str__(self) -> str:
2631
return "Gitlab" + super().__str__()
@@ -32,7 +37,12 @@ def delete(self) -> None:
3237
class GitlabComment(Comment):
3338
def _from_raw_comment(
3439
self,
35-
raw_comment: Union[ProjectIssueNote, ProjectMergeRequestNote],
40+
raw_comment: Union[
41+
ProjectIssueNote,
42+
ProjectMergeRequestNote,
43+
ProjectCommitDiscussionNote,
44+
ProjectCommitComment,
45+
],
3646
) -> None:
3747
self._raw_comment = raw_comment
3848
self._id = raw_comment.get_id()
@@ -94,3 +104,36 @@ def __str__(self) -> str:
94104
class GitlabPRComment(GitlabComment, PRComment):
95105
def __str__(self) -> str:
96106
return "Gitlab" + super().__str__()
107+
108+
109+
class GitlabCommitComment(GitlabComment, CommitComment):
110+
def __str__(self) -> str:
111+
return "Gitlab" + super().__str__()
112+
113+
@property
114+
def body(self) -> str:
115+
# TODO: ideally, the raw comment should be of the same type for both
116+
# individual and all comments retrievals, this comes from the
117+
# Gitlab API inconsistency (see get_commit_comment vs get_commit_comments)
118+
if isinstance(self._raw_comment, ProjectCommitComment):
119+
return self._raw_comment.note
120+
121+
return self._raw_comment.body
122+
123+
@body.setter
124+
def body(self, new_body: str) -> None:
125+
if isinstance(self._raw_comment, ProjectCommitComment):
126+
self._raw_comment.note = new_body
127+
else:
128+
self._raw_comment.body = new_body
129+
self._raw_comment.save()
130+
131+
def get_reactions(self) -> list[Reaction]:
132+
raise OperationNotSupported(
133+
"Interacting with award emojis on commit comments is not supported via API.",
134+
)
135+
136+
def add_reaction(self, reaction: str) -> GitlabReaction:
137+
raise OperationNotSupported(
138+
"Interacting with award emojis on commit comments is not supported via API.",
139+
)

ogr/services/gitlab/project.py

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from ogr.exceptions import GitlabAPIException, OperationNotSupported
2626
from ogr.services import gitlab as ogr_gitlab
2727
from ogr.services.base import BaseGitProject
28+
from ogr.services.gitlab.comments import GitlabCommitComment
2829
from ogr.services.gitlab.flag import GitlabCommitFlag
2930
from ogr.services.gitlab.issue import GitlabIssue
3031
from ogr.services.gitlab.pull_request import GitlabPullRequest
@@ -294,11 +295,10 @@ def commit_comment(
294295
return self._commit_comment_from_gitlab_object(raw_comment, commit)
295296

296297
@staticmethod
297-
def _commit_comment_from_gitlab_object(raw_comment, commit) -> CommitComment:
298-
return CommitComment(
298+
def _commit_comment_from_gitlab_object(raw_comment, commit: str) -> CommitComment:
299+
return GitlabCommitComment(
300+
raw_comment=raw_comment,
299301
sha=commit,
300-
body=raw_comment.note,
301-
author=raw_comment.author["username"],
302302
)
303303

304304
def get_commit_comments(self, commit: str) -> list[CommitComment]:
@@ -313,6 +313,38 @@ def get_commit_comments(self, commit: str) -> list[CommitComment]:
313313
for comment in commit_object.comments.list()
314314
]
315315

316+
def get_commit_comment(self, commit_sha: str, comment_id: int) -> CommitComment:
317+
try:
318+
commit_object: ProjectCommit = self.gitlab_repo.commits.get(commit_sha)
319+
except gitlab.exceptions.GitlabGetError as ex:
320+
logger.error(f"Commit with SHA {commit_sha} was not found: {ex}")
321+
raise GitlabAPIException(
322+
f"Commit with SHA {commit_sha} was not found.",
323+
) from ex
324+
325+
try:
326+
discussions = commit_object.discussions.list(all=True)
327+
comment = None
328+
329+
for discussion in discussions:
330+
note_ids = [note["id"] for note in discussion.attributes["notes"]]
331+
if comment_id in note_ids:
332+
comment = discussion.notes.get(comment_id)
333+
break
334+
335+
if comment is None:
336+
raise GitlabAPIException(
337+
f"Comment with ID {comment_id} not found in commit {commit_sha}.",
338+
)
339+
340+
except gitlab.exceptions.GitlabGetError as ex:
341+
logger.error(f"Failed to retrieve comment with ID {comment_id}: {ex}")
342+
raise GitlabAPIException(
343+
f"Failed to retrieve comment with ID {comment_id}.",
344+
) from ex
345+
346+
return self._commit_comment_from_gitlab_object(comment, commit_sha)
347+
316348
@indirect(GitlabCommitFlag.set)
317349
def set_commit_status(
318350
self,

ogr/services/pagure/project.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,9 @@ def commit_comment(
482482
def get_commit_comments(self, commit: str) -> list[CommitComment]:
483483
raise OperationNotSupported("Commit comments are not supported on Pagure.")
484484

485+
def get_commit_comment(self, commit_sha: str, comment_id: int) -> CommitComment:
486+
raise OperationNotSupported("Commit comments are not supported on Pagure.")
487+
485488
@if_readonly(return_function=GitProjectReadOnly.set_commit_status)
486489
@indirect(PagureCommitFlag.set)
487490
def set_commit_status(

0 commit comments

Comments
 (0)