Skip to content

Commit d7d66d1

Browse files
Add GitCommentHelpHandler class (#2853)
Add GitCommentHelpHandler class A new job handler has been created so that packit-service now has the ability to respond to the help command used in issue and PR comments. A comment is then added to the issue / PR, which contains a help message that includes the usage, link to documentation and contacts. Three tests are included to ensure functionality. TODO: Update or write new documentation in packit/packit.dev. In the help message, add reference to /packit-ci when user uses /packit and the other way around. This is in case the user uses /packit when they should be using /packit-ci and vice versa. Fixes #1668 Related to Merge after #2850 RELEASE NOTES BEGIN Packit-service now supports the help command in issue and PR comments. RELEASE NOTES END Reviewed-by: gemini-code-assist[bot] Reviewed-by: Alžběta Kučerová Reviewed-by: Maja Massarini Reviewed-by: Laura Barcziová
2 parents 1d3ed53 + eb7ba9a commit d7d66d1

File tree

13 files changed

+933
-29
lines changed

13 files changed

+933
-29
lines changed

packit_service/constants.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,27 @@
1717
DOCS_VALIDATE_CONFIG = f"{DOCS_URL}/cli/config/validate"
1818
DOCS_VALIDATE_HOOKS = "https://packit.dev/posts/pre-commit-hooks#validate-config"
1919

20-
HELP_COMMENT_PROG = "/packit | /packit-stg"
21-
HELP_COMMENT_PROG_FEDORA_CI = "/packit-ci | /packit-ci-stg"
20+
HELP_COMMENT_PROG = "/packit"
21+
HELP_COMMENT_PROG_STG = "/packit-stg"
22+
HELP_COMMENT_PROG_FEDORA_CI = "/packit-ci"
23+
HELP_COMMENT_PROG_FEDORA_CI_STG = "/packit-ci-stg"
2224
HELP_COMMENT_DESCRIPTION = ""
2325
HELP_COMMENT_EPILOG = (
26+
"Note: {note}\n"
2427
f"Documentation: {DOCS_URL}\n"
2528
"Contact:\n"
2629
" Email: hello@packit.dev\n"
2730
" Matrix: #packit:fedora.im\n"
2831
" Mastodon: @packit@fosstodon.org"
2932
)
33+
HELP_NOTE = (
34+
"If using Fedora CI, refer to `/packit-ci help` instead. "
35+
"Refer to `/packit-ci-stg help` if using the staging instance."
36+
)
37+
HELP_NOTE_FEDORA_CI = (
38+
"For default Packit behaviour, refer to `/packit help` instead. "
39+
"Refer to `/packit-stg help` if using the staging instance."
40+
)
3041

3142
KOJI_PRODUCTION_BUILDS_ISSUE = "https://pagure.io/releng/issue/9801"
3243

@@ -260,6 +271,7 @@ def from_number(number: int):
260271
FASJSON_URL = "https://fasjson.fedoraproject.org"
261272

262273
PACKIT_VERIFY_FAS_COMMAND = "verify-fas"
274+
PACKIT_HELP_COMMAND = "help"
263275

264276
MISSING_PERMISSIONS_TO_BUILD_IN_COPR = "You don't have permissions to build in this copr."
265277
NOT_ALLOWED_TO_BUILD_IN_COPR = "is not allowed to build in the copr"

packit_service/utils.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,11 @@ def get_packit_commands_from_comment(
228228
return []
229229

230230

231-
def _create_base_parser(prog: str, description: str, epilog: str) -> argparse.ArgumentParser:
231+
def _create_base_parser(
232+
prog: Optional[str] = None,
233+
description: Optional[str] = None,
234+
epilog: Optional[str] = None,
235+
) -> argparse.ArgumentParser:
232236
parser = argparse.ArgumentParser(
233237
prog=prog,
234238
description=description,
@@ -239,7 +243,11 @@ def _create_base_parser(prog: str, description: str, epilog: str) -> argparse.Ar
239243
return parser
240244

241245

242-
def get_pr_comment_parser(prog: str, description: str, epilog: str) -> argparse.ArgumentParser:
246+
def get_comment_parser(
247+
prog: Optional[str] = None,
248+
description: Optional[str] = None,
249+
epilog: Optional[str] = None,
250+
) -> argparse.ArgumentParser:
243251
parser = _create_base_parser(prog, description, epilog)
244252

245253
subparsers = parser.add_subparsers(
@@ -313,8 +321,10 @@ def get_pr_comment_parser(prog: str, description: str, epilog: str) -> argparse.
313321
return parser
314322

315323

316-
def get_pr_comment_parser_fedora_ci(
317-
prog: str, description: str, epilog: str
324+
def get_comment_parser_fedora_ci(
325+
prog: Optional[str] = None,
326+
description: Optional[str] = None,
327+
epilog: Optional[str] = None,
318328
) -> argparse.ArgumentParser:
319329
parser = _create_base_parser(prog, description, epilog)
320330

@@ -329,7 +339,7 @@ def get_pr_comment_parser_fedora_ci(
329339
choices=["installability", "rpmlint", "rpminspect", "custom"],
330340
help="Specific type of tests to run",
331341
)
332-
subparsers.add_parser("scratch-build", help="Build package in Scratch")
342+
subparsers.add_parser("scratch-build", help="Build package in Koji")
333343

334344
return parser
335345

packit_service/worker/handlers/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,11 @@
2323
SyncFromDownstream,
2424
)
2525
from packit_service.worker.handlers.forges import (
26+
GitCommentHelpHandler,
2627
GithubAppInstallationHandler,
2728
GithubFasVerificationHandler,
29+
GitIssueCommentHelpHandler,
30+
GitPullRequestCommentHelpHandler,
2831
)
2932
from packit_service.worker.handlers.koji import (
3033
KojiBuildHandler,
@@ -68,6 +71,9 @@
6871
TestingFarmHandler.__name__,
6972
TestingFarmResultsHandler.__name__,
7073
GithubFasVerificationHandler.__name__,
74+
GitCommentHelpHandler.__name__,
75+
GitIssueCommentHelpHandler.__name__,
76+
GitPullRequestCommentHelpHandler.__name__,
7177
VMImageBuildHandler.__name__,
7278
VMImageBuildResultHandler.__name__,
7379
CoprOpenScanHubTaskFinishedHandler.__name__,

packit_service/worker/handlers/abstract.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,8 @@ def _add_to_mapping(kls: type["JobHandler"]):
234234

235235

236236
class TaskName(str, enum.Enum):
237+
help_pr = "task.run_help_pr_handler"
238+
help_issue = "task.run_help_issue_handler"
237239
copr_build_start = "task.run_copr_build_start_handler"
238240
copr_build_end = "task.run_copr_build_end_handler"
239241
copr_build = "task.run_copr_build_handler"

packit_service/worker/handlers/forges.py

Lines changed: 105 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,44 @@
77
"""
88

99
import logging
10+
from abc import ABC, abstractmethod
11+
from typing import Optional
1012

13+
from packit.api import PackitAPI
1114
from packit.config import (
1215
Deployment,
1316
JobConfig,
1417
)
1518
from packit.config.package_config import PackageConfig
1619

17-
from packit_service.constants import CONTACTS_URL, DOCS_APPROVAL_URL, NOTIFICATION_REPO
20+
from packit_service.constants import (
21+
CONTACTS_URL,
22+
DOCS_APPROVAL_URL,
23+
HELP_COMMENT_DESCRIPTION,
24+
HELP_COMMENT_EPILOG,
25+
HELP_COMMENT_PROG,
26+
HELP_COMMENT_PROG_FEDORA_CI,
27+
HELP_COMMENT_PROG_FEDORA_CI_STG,
28+
HELP_COMMENT_PROG_STG,
29+
HELP_NOTE,
30+
HELP_NOTE_FEDORA_CI,
31+
NOTIFICATION_REPO,
32+
)
1833
from packit_service.events import (
1934
github,
35+
gitlab,
36+
pagure,
2037
)
2138
from packit_service.models import (
2239
AllowlistModel,
2340
AllowlistStatus,
2441
GithubInstallationModel,
2542
)
26-
from packit_service.utils import get_packit_commands_from_comment
43+
from packit_service.utils import (
44+
get_comment_parser,
45+
get_comment_parser_fedora_ci,
46+
get_packit_commands_from_comment,
47+
)
2748
from packit_service.worker.allowlist import Allowlist
2849
from packit_service.worker.checker.abstract import Checker
2950
from packit_service.worker.checker.forges import IsIssueInNotificationRepoChecker
@@ -35,6 +56,7 @@
3556
from packit_service.worker.mixin import (
3657
ConfigFromEventMixin,
3758
GetIssueMixin,
59+
GetPullRequestMixin,
3860
PackitAPIWithDownstreamMixin,
3961
)
4062
from packit_service.worker.reporting import create_issue_if_needed
@@ -279,3 +301,84 @@ def verify(self, namespace: str, fas_account: str) -> TaskResults:
279301
self.issue.comment(msg)
280302

281303
return TaskResults(success=True, details={"msg": msg})
304+
305+
306+
class GitCommentHelpHandler(
307+
ABC,
308+
JobHandler,
309+
):
310+
@property
311+
def packit_api(self) -> PackitAPI: ...
312+
313+
def clean_api(self) -> None: ...
314+
315+
def __init__(
316+
self,
317+
package_config: Optional[PackageConfig],
318+
job_config: Optional[JobConfig],
319+
event: dict,
320+
):
321+
super().__init__(
322+
package_config=package_config,
323+
job_config=job_config,
324+
event=event,
325+
)
326+
self.sender_login = self.data.actor
327+
self.comment = self.data.event_dict.get("comment")
328+
329+
@abstractmethod
330+
def add_comment(self, body: str) -> None:
331+
pass
332+
333+
def run(self) -> TaskResults:
334+
if self.comment.startswith("/packit-ci-stg"): # type: ignore
335+
parser = get_comment_parser_fedora_ci(
336+
prog=HELP_COMMENT_PROG_FEDORA_CI_STG,
337+
description=HELP_COMMENT_DESCRIPTION,
338+
epilog=HELP_COMMENT_EPILOG.format(note=HELP_NOTE_FEDORA_CI),
339+
)
340+
341+
elif self.comment.startswith("/packit-ci"): # type: ignore
342+
parser = get_comment_parser_fedora_ci(
343+
prog=HELP_COMMENT_PROG_FEDORA_CI,
344+
description=HELP_COMMENT_DESCRIPTION,
345+
epilog=HELP_COMMENT_EPILOG.format(note=HELP_NOTE_FEDORA_CI),
346+
)
347+
348+
elif self.comment.startswith("/packit-stg"): # type: ignore
349+
parser = get_comment_parser(
350+
prog=HELP_COMMENT_PROG_STG,
351+
description=HELP_COMMENT_DESCRIPTION,
352+
epilog=HELP_COMMENT_EPILOG.format(note=HELP_NOTE),
353+
)
354+
355+
else:
356+
parser = get_comment_parser(
357+
prog=HELP_COMMENT_PROG,
358+
description=HELP_COMMENT_DESCRIPTION,
359+
epilog=HELP_COMMENT_EPILOG.format(note=HELP_NOTE),
360+
)
361+
362+
help_message = parser.format_help()
363+
self.add_comment(body=help_message)
364+
365+
return TaskResults(success=True, details={"msg": help_message})
366+
367+
368+
@reacts_to(event=github.pr.Comment)
369+
@reacts_to(event=gitlab.mr.Comment)
370+
@reacts_to(event=pagure.pr.Comment)
371+
class GitPullRequestCommentHelpHandler(GitCommentHelpHandler, GetPullRequestMixin):
372+
task_name = TaskName.help_pr
373+
374+
def add_comment(self, body: str) -> None:
375+
self.pr.comment(body=body)
376+
377+
378+
@reacts_to(event=github.issue.Comment)
379+
@reacts_to(event=gitlab.issue.Comment)
380+
class GitIssueCommentHelpHandler(GitCommentHelpHandler, GetIssueMixin):
381+
task_name = TaskName.help_issue
382+
383+
def add_comment(self, body: str) -> None:
384+
self.issue.comment(body=body)

packit_service/worker/jobs.py

Lines changed: 72 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,14 @@
2828
from packit_service.constants import (
2929
COMMENT_REACTION,
3030
FEDORA_CI_TRANSITION_COMMENT,
31-
HELP_COMMENT_DESCRIPTION,
32-
HELP_COMMENT_EPILOG,
33-
HELP_COMMENT_PROG,
34-
HELP_COMMENT_PROG_FEDORA_CI,
31+
PACKIT_HELP_COMMAND,
3532
PACKIT_VERIFY_FAS_COMMAND,
3633
TASK_ACCEPTED,
3734
)
3835
from packit_service.events import (
3936
abstract,
4037
github,
38+
gitlab,
4139
koji,
4240
logdetective,
4341
pagure,
@@ -48,9 +46,9 @@
4846
from packit_service.package_config_getter import PackageConfigGetter
4947
from packit_service.utils import (
5048
elapsed_seconds,
49+
get_comment_parser,
50+
get_comment_parser_fedora_ci,
5151
get_packit_commands_from_comment,
52-
get_pr_comment_parser,
53-
get_pr_comment_parser_fedora_ci,
5452
pr_labels_match_configuration,
5553
)
5654
from packit_service.worker.allowlist import Allowlist
@@ -83,6 +81,10 @@
8381
RetriggerDownstreamKojiBuildHandler,
8482
TagIntoSidetagHandler,
8583
)
84+
from packit_service.worker.handlers.forges import (
85+
GitIssueCommentHelpHandler,
86+
GitPullRequestCommentHelpHandler,
87+
)
8688
from packit_service.worker.helpers.build import (
8789
BaseBuildJobHelper,
8890
CoprBuildJobHelper,
@@ -135,17 +137,9 @@ def parse_comment(
135137
return ParsedComment()
136138

137139
if comment.startswith("/packit-ci"):
138-
parser = get_pr_comment_parser_fedora_ci(
139-
prog=HELP_COMMENT_PROG_FEDORA_CI,
140-
description=HELP_COMMENT_DESCRIPTION,
141-
epilog=HELP_COMMENT_EPILOG,
142-
)
140+
parser = get_comment_parser_fedora_ci()
143141
else:
144-
parser = get_pr_comment_parser(
145-
prog=HELP_COMMENT_PROG,
146-
description=HELP_COMMENT_DESCRIPTION,
147-
epilog=HELP_COMMENT_EPILOG,
148-
)
142+
parser = get_comment_parser()
149143

150144
try:
151145
args = parser.parse_args(commands)
@@ -359,6 +353,29 @@ def process(self) -> list[TaskResults]:
359353
).apply_async()
360354
# should we comment about not processing if the comment is not
361355
# on the issue created by us or not in packit/notifications?
356+
elif isinstance(
357+
self.event,
358+
(
359+
github.pr.Comment,
360+
gitlab.mr.Comment,
361+
pagure.pr.Comment,
362+
github.issue.Comment,
363+
gitlab.issue.Comment,
364+
),
365+
) and self.is_help_comment(self.event.comment):
366+
self.event.comment_object.add_reaction(COMMENT_REACTION)
367+
handler = (
368+
GitPullRequestCommentHelpHandler
369+
if isinstance(
370+
self.event,
371+
(github.pr.Comment, gitlab.mr.Comment, pagure.pr.Comment),
372+
)
373+
else GitIssueCommentHelpHandler
374+
)
375+
handler.get_signature(
376+
event=self.event,
377+
job=None,
378+
).apply_async()
362379
else:
363380
if (
364381
isinstance(
@@ -1313,6 +1330,45 @@ def is_fas_verification_comment(self, comment: str) -> bool:
13131330

13141331
return bool(command and command[0] == PACKIT_VERIFY_FAS_COMMAND)
13151332

1333+
def retrieve_comment_command_prefix(self, comment: str) -> Optional[str]:
1334+
"""
1335+
Retrieves the Packit prefix used in comment.
1336+
1337+
Args:
1338+
comment: Comment to retrieve prefix from.
1339+
1340+
Returns:
1341+
Packit comment command prefix or None if none is found.
1342+
"""
1343+
prefixes = ["/packit-ci-stg", "/packit-ci", "/packit-stg", "/packit"]
1344+
1345+
for prefix in prefixes:
1346+
if comment.startswith(prefix):
1347+
return prefix
1348+
1349+
return None
1350+
1351+
def is_help_comment(self, comment: str) -> bool:
1352+
"""
1353+
Checks whether the comment contains Packit help command:
1354+
`/packit(-stg) | /packit-ci(-stg) help`
1355+
1356+
Args:
1357+
comment: Comment to be checked.
1358+
1359+
Returns:
1360+
`True`, if is help comment, `False` otherwise.
1361+
"""
1362+
if not (packit_comment_command_prefix := self.retrieve_comment_command_prefix(comment)):
1363+
return False
1364+
1365+
command = get_packit_commands_from_comment(
1366+
comment,
1367+
packit_comment_command_prefix,
1368+
)
1369+
1370+
return bool(command and command[0] == PACKIT_HELP_COMMAND)
1371+
13161372
def report_task_accepted_for_downstream_retrigger_comments(
13171373
self,
13181374
handler_kls: type[JobHandler],

0 commit comments

Comments
 (0)