Skip to content
3 changes: 2 additions & 1 deletion packit_service/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,7 @@ def get_comment_parser_fedora_ci(
prog: Optional[str] = None,
description: Optional[str] = None,
epilog: Optional[str] = None,
supported_test_types: Optional[list[str]] = None,
) -> argparse.ArgumentParser:
parser = _create_base_parser(prog, description, epilog)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

According to the repository's style guide (lines 412-414), all non-trivial functions should have a docstring. Please add a docstring to get_pr_comment_parser_fedora_ci explaining its purpose, arguments, and what it returns.

    """Create a parser for the Fedora CI PR comment.

    Args:
        prog: The name of the program.
        description: The program description.
        epilog: Text to display after the argument help.
        supported_test_types: A list of supported test types.

    Returns:
        An argument parser for Fedora CI PR comments.
    """
    parser = _create_base_parser(prog, description, epilog)
References
  1. With exception of trivial cases, all code must contain accurate and sufficiently detailed docstrings, formatted with accordance with the PEP 257 standard and in Google-style. (link)


Expand All @@ -351,7 +352,7 @@ def get_comment_parser_fedora_ci(
test_parser.add_argument(
"test_identifier",
nargs="?",
choices=["installability", "rpmlint", "rpminspect", "custom"],
choices=supported_test_types,
help="specific type of tests to run",
)

Expand Down
28 changes: 28 additions & 0 deletions packit_service/worker/checker/testing_farm.py
Original file line number Diff line number Diff line change
Expand Up @@ -328,3 +328,31 @@ def pre_check(self) -> bool:
return False

return True


class IsFMFConfigMissing(_TestingFarmTestTypeChecker):
"""
Check whether FMF configuration is missing in the given project.
"""

def pre_check(self) -> bool:
try:
commit_sha = self.data.event_dict.get("commit_sha")

self.project.get_file_content(
path=".fmf/version",
ref=commit_sha,
)
except FileNotFoundError:
logger.debug("FMF configuration not found in repository.")
return True
return False


class IsProjectInTestsNamespace(_TestingFarmTestTypeChecker):
"""
Check whether the current project is located inside the tests namespace.
"""

def pre_check(self) -> bool:
return self.project.namespace == "tests"
28 changes: 17 additions & 11 deletions packit_service/worker/handlers/mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from abc import abstractmethod
from collections.abc import Iterator
from dataclasses import dataclass
from typing import Any, Optional, Protocol, Union
from typing import TYPE_CHECKING, Any, Optional, Protocol, Union

from packit.config import JobConfig, PackageConfig
from packit.exceptions import PackitException
Expand Down Expand Up @@ -35,13 +35,15 @@
from packit_service.worker.helpers.build.copr_build import CoprBuildJobHelper
from packit_service.worker.helpers.build.koji_build import KojiBuildJobHelper
from packit_service.worker.helpers.sidetag import Sidetag, SidetagHelper
from packit_service.worker.helpers.testing_farm import (
DownstreamTestingFarmJobHelper,
TestingFarmJobHelper,
)
from packit_service.worker.mixin import Config, ConfigFromEventMixin, GetBranches
from packit_service.worker.monitoring import Pushgateway

if TYPE_CHECKING:
from packit_service.worker.helpers.testing_farm import (
DownstreamTestingFarmJobHelper,
TestingFarmJobHelper,
)

logger = logging.getLogger(__name__)


Expand Down Expand Up @@ -615,19 +617,21 @@ class GetTestingFarmJobHelper(Protocol):

@property
@abstractmethod
def testing_farm_job_helper(self) -> TestingFarmJobHelper: ...
def testing_farm_job_helper(self) -> "TestingFarmJobHelper": ...


class GetTestingFarmJobHelperMixin(
GetTestingFarmJobHelper,
GetCoprBuildMixin,
ConfigFromEventMixin,
):
_testing_farm_job_helper: Optional[TestingFarmJobHelper] = None
_testing_farm_job_helper: Optional["TestingFarmJobHelper"] = None

@property
def testing_farm_job_helper(self) -> TestingFarmJobHelper:
def testing_farm_job_helper(self) -> "TestingFarmJobHelper":
if not self._testing_farm_job_helper:
from packit_service.worker.helpers.testing_farm import TestingFarmJobHelper

self._testing_farm_job_helper = TestingFarmJobHelper(
service_config=self.service_config,
package_config=self.package_config,
Expand All @@ -647,19 +651,21 @@ class GetDownstreamTestingFarmJobHelper(Protocol):

@property
@abstractmethod
def downstream_testing_farm_job_helper(self) -> DownstreamTestingFarmJobHelper: ...
def downstream_testing_farm_job_helper(self) -> "DownstreamTestingFarmJobHelper": ...


class GetDownstreamTestingFarmJobHelperMixin(
GetDownstreamTestingFarmJobHelper,
GetKojiBuildFromTaskOrPullRequestMixin,
ConfigFromEventMixin,
):
_downstream_testing_farm_job_helper: Optional[DownstreamTestingFarmJobHelper] = None
_downstream_testing_farm_job_helper: Optional["DownstreamTestingFarmJobHelper"] = None

@property
def downstream_testing_farm_job_helper(self) -> DownstreamTestingFarmJobHelper:
def downstream_testing_farm_job_helper(self) -> "DownstreamTestingFarmJobHelper":
if not self._downstream_testing_farm_job_helper:
from packit_service.worker.helpers.testing_farm import DownstreamTestingFarmJobHelper

self._downstream_testing_farm_job_helper = DownstreamTestingFarmJobHelper(
service_config=self.service_config,
project=self.project,
Expand Down
20 changes: 4 additions & 16 deletions packit_service/worker/handlers/testing_farm.py
Original file line number Diff line number Diff line change
Expand Up @@ -400,20 +400,14 @@ def get_checkers() -> tuple[type[Checker], ...]:
PermissionOnDistgitForFedoraCI,
)

@classmethod
def filter_ci_tests(cls, tests: list[str]) -> list[str]:
return tests

@classmethod
def get_all_check_names(
cls, service_config: ServiceConfig, project: GitProject, metadata: EventData
) -> list[str]:
return [
DownstreamTestingFarmJobHelper.get_check_name_from_config(t, service_config)
for t in cls.filter_ci_tests(
DownstreamTestingFarmJobHelper.get_fedora_ci_tests(
service_config, project, metadata
)
for t in DownstreamTestingFarmJobHelper.get_fedora_ci_tests(
service_config, project, metadata
)
]

Expand Down Expand Up @@ -493,10 +487,8 @@ def run_for_fedora_ci_test(
def _run(self) -> TaskResults:
failed: dict[str, str] = {}

fedora_ci_tests = self.filter_ci_tests(
self.downstream_testing_farm_job_helper.get_fedora_ci_tests(
self.service_config, self.project, self.data
)
fedora_ci_tests = self.downstream_testing_farm_job_helper.get_fedora_ci_tests(
self.service_config, self.project, self.data
)

if not fedora_ci_tests:
Expand Down Expand Up @@ -562,10 +554,6 @@ def get_checkers() -> tuple[type[Checker], ...]:
PermissionOnDistgitForFedoraCI,
)

@classmethod
def filter_ci_tests(cls, tests: list[str]) -> list[str]:
return [t for t in tests if t == "custom"]


@configured_as(job_type=JobType.tests)
@reacts_to(event=testing_farm.Result)
Expand Down
109 changes: 63 additions & 46 deletions packit_service/worker/helpers/testing_farm.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@
from packit_service.service.urls import get_testing_farm_info_url
from packit_service.utils import get_package_nvrs, get_packit_commands_from_comment
from packit_service.worker.celery_task import CeleryTask
from packit_service.worker.checker.abstract import Checker
from packit_service.worker.checker.testing_farm import (
IsFMFConfigMissing,
IsProjectInTestsNamespace,
)
from packit_service.worker.handlers.abstract import FedoraCIJobHandler
from packit_service.worker.helpers.build import CoprBuildJobHelper
from packit_service.worker.helpers.fedora_ci import FedoraCIHelper
Expand Down Expand Up @@ -667,14 +672,9 @@ def is_fmf_configured(self) -> bool:
if self.custom_fmf:
return True

try:
self.project.get_file_content(
path=f"{self.fmf_path}/.fmf/version",
ref=self.metadata.commit_sha,
)
return True
except FileNotFoundError:
return False
return not IsFMFConfigMissing(
package_config=None, job_config=None, event=self.metadata.event_dict, task_name=None
).pre_check()

def report_missing_build_chroot(self, chroot: str):
self.report_status_to_tests_for_chroot(
Expand Down Expand Up @@ -1255,9 +1255,11 @@ def cancel_running_tests(self):
FEDORA_CI_TESTS = {}


def implements_fedora_ci_test(test_name: str, skipif: Optional[Callable] = None) -> Callable:
def implements_fedora_ci_test(
test_name: str, checkers: Optional[list[type[Checker]]] = None
) -> Callable:
def _update_mapping(function: Callable) -> Callable:
FEDORA_CI_TESTS[test_name] = (function, skipif)
FEDORA_CI_TESTS[test_name] = (function, checkers)
return function

return _update_mapping
Expand Down Expand Up @@ -1291,7 +1293,10 @@ def koji_helper(self):

@staticmethod
def get_fedora_ci_tests(
service_config: ServiceConfig, project: GitProject, metadata: EventData
service_config: ServiceConfig,
project: GitProject,
metadata: EventData,
filter_specific_tests: bool = True,
) -> list[str]:
"""
Gets relevant Fedora CI tests registered using the `@implements_fedora_ci_test()` decorator.
Expand All @@ -1303,31 +1308,47 @@ def get_fedora_ci_tests(
service_config: Service config.
project: Git project.
metadata: Event metadata.
filter_specific_tests: Whether to filter tests based on the command in user's comment.

Returns:
List of registered Fedora CI test names.
"""

def filter_tests(tests):
if metadata.event_type != pagure.pr.Comment.event_type():
return tests
# TODO: remove this once Fedora CI has its own instances and comment_command_prefixes
# comment_command_prefixes for Fedora CI are /packit-ci and /packit-ci-stg
comment_command_prefix = (
"/packit-ci-stg"
if service_config.comment_command_prefix.endswith("-stg")
else "/packit-ci"
)
commands = get_packit_commands_from_comment(
metadata.event_dict.get("comment"), comment_command_prefix
)
if not commands:
return []
if len(commands) > 1 and commands[1] in tests:
return [commands[1]]
return tests

all_tests = [
name
for name, (_, skipif) in FEDORA_CI_TESTS.items()
if not skipif or not skipif(service_config, project, metadata)
for name, (_, checkers) in FEDORA_CI_TESTS.items()
if not any(
checker(
package_config=None,
job_config=None,
event=metadata.event_dict,
task_name=None,
).pre_check()
for checker in checkers
)
]
if metadata.event_type != pagure.pr.Comment.event_type():
return all_tests
# TODO: remove this once Fedora CI has its own instances and comment_command_prefixes
# comment_command_prefixes for Fedora CI are /packit-ci and /packit-ci-stg
comment_command_prefix = (
"/packit-ci-stg"
if service_config.comment_command_prefix.endswith("-stg")
else "/packit-ci"
)
commands = get_packit_commands_from_comment(
metadata.event_dict.get("comment"), comment_command_prefix
)
if not commands:
return []
if len(commands) > 1 and commands[1] in all_tests:
return [commands[1]]

if filter_specific_tests:
return filter_tests(all_tests)
return all_tests

@property
Expand Down Expand Up @@ -1447,7 +1468,10 @@ def prepare_and_send_tf_request(
response=response,
)

@implements_fedora_ci_test("installability")
@implements_fedora_ci_test(
"installability",
checkers=[IsProjectInTestsNamespace],
)
def _payload_installability(self, distro: str, compose: str) -> dict:
git_repo = "https://github.com/fedora-ci/installability-pipeline.git"
git_ref = (
Expand Down Expand Up @@ -1494,7 +1518,10 @@ def _payload_installability(self, distro: str, compose: str) -> dict:
},
}

@implements_fedora_ci_test("rpminspect")
@implements_fedora_ci_test(
"rpminspect",
checkers=[IsProjectInTestsNamespace],
)
def _payload_rpminspect(self, distro: str, compose: str) -> dict:
git_repo = "https://github.com/fedora-ci/rpminspect-pipeline.git"
git_ref = "master"
Expand All @@ -1509,7 +1536,10 @@ def _payload_rpminspect(self, distro: str, compose: str) -> dict:
}
return payload

@implements_fedora_ci_test("rpmlint")
@implements_fedora_ci_test(
"rpmlint",
checkers=[IsProjectInTestsNamespace],
)
def _payload_rpmlint(self, distro: str, compose: str) -> dict:
git_repo = "https://github.com/packit/tmt-plans.git"
git_ref = "main"
Expand All @@ -1525,22 +1555,9 @@ def _payload_rpmlint(self, distro: str, compose: str) -> dict:
}
return payload

@staticmethod
def is_fmf_configured(project: GitProject, metadata: EventData) -> bool:
try:
project.get_file_content(
path=".fmf/version",
ref=metadata.commit_sha,
)
except FileNotFoundError:
return False
return True

@implements_fedora_ci_test(
"custom",
skipif=lambda _, project, metadata: not DownstreamTestingFarmJobHelper.is_fmf_configured(
project, metadata
),
checkers=[IsFMFConfigMissing],
)
def _payload_custom(self, distro: str, compose: str) -> dict:
payload = self._get_tf_base_payload(distro, compose)
Expand Down
13 changes: 11 additions & 2 deletions packit_service/worker/jobs.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,10 @@
from packit_service.worker.helpers.sync_release.propose_downstream import (
ProposeDownstreamJobHelper,
)
from packit_service.worker.helpers.testing_farm import TestingFarmJobHelper
from packit_service.worker.helpers.testing_farm import (
DownstreamTestingFarmJobHelper,
TestingFarmJobHelper,
)
from packit_service.worker.monitoring import Pushgateway
from packit_service.worker.parser import Parser
from packit_service.worker.reporting import BaseCommitStatus
Expand Down Expand Up @@ -265,7 +268,13 @@ def parse_comment(
return ParsedComment()

if comment.startswith("/packit-ci"):
parser = get_comment_parser_fedora_ci()
supported_test_types = DownstreamTestingFarmJobHelper.get_fedora_ci_tests(
self.service_config,
self.event.project,
EventData.from_event_dict(self.event.get_dict()),
filter_specific_tests=False,
)
parser = get_comment_parser_fedora_ci(supported_test_types=supported_test_types)
else:
parser = get_comment_parser()

Expand Down
Loading
Loading