Skip to content

Commit

Permalink
Add KojiBuildTagHandler
Browse files Browse the repository at this point in the history
Signed-off-by: Nikola Forró <[email protected]>
  • Loading branch information
nforro committed Jul 15, 2024
1 parent 66ecf73 commit 76b844f
Show file tree
Hide file tree
Showing 9 changed files with 266 additions and 6 deletions.
6 changes: 6 additions & 0 deletions packit_service/worker/checker/koji.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
KOJI_PRODUCTION_BUILDS_ISSUE,
PERMISSIONS_ERROR_WRITE_OR_ADMIN,
)
from packit_service.models import SidetagModel
from packit_service.worker.checker.abstract import Checker
from packit_service.worker.events import (
MergeRequestGitlabEvent,
Expand Down Expand Up @@ -55,3 +56,8 @@ def pre_check(self) -> bool:
return False

return True


class SidetagExists(Checker):
def pre_check(self) -> bool:
return SidetagModel.get_by_koji_name(self.data.tag_name) is not None
3 changes: 2 additions & 1 deletion packit_service/worker/handlers/abstract.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,9 @@ class TaskName(str, enum.Enum):
github_fas_verification = "task.github_fas_verification"
vm_image_build = "task.run_vm_image_build_handler"
vm_image_build_result = "task.run_vm_image_build_result_handler"
pull_from_upstream = "pull_from_upstream"
pull_from_upstream = "task.pull_from_upstream"
check_onboarded_projects = "task.check_onboarded_projects"
koji_build_tag = "task.koji_build_tag"


class Handler(PackitAPIProtocol, Config):
Expand Down
7 changes: 7 additions & 0 deletions packit_service/worker/handlers/distgit.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
IssueCommentEvent,
IssueCommentGitlabEvent,
)
from packit_service.worker.events.koji import KojiBuildTagEvent
from packit_service.worker.events.new_hotness import NewHotnessUpdateEvent
from packit_service.worker.handlers.abstract import (
JobHandler,
Expand Down Expand Up @@ -877,6 +878,7 @@ def report_in_issue_repository(self, errors: dict[str, str]) -> None:
@run_for_comment(command="koji-build")
@reacts_to(event=PushPagureEvent)
@reacts_to(event=PullRequestCommentPagureEvent)
@reacts_to(event=KojiBuildTagEvent)
class DownstreamKojiBuildHandler(
AbstractDownstreamKojiBuildHandler,
ConfigFromEventMixin,
Expand Down Expand Up @@ -922,6 +924,11 @@ def get_trigger_type_description(self) -> str:
f"Fedora Koji build was triggered "
f"by push with sha {self.data.commit_sha}."
)
elif self.data.event_type == KojiBuildTagEvent.__name__:
trigger_type_description += (
f"Fedora Koji build was triggered "
f"by tagging of build {self.data.build_id} to {self.data.koji_tag_name}."
)
return trigger_type_description

@staticmethod
Expand Down
90 changes: 89 additions & 1 deletion packit_service/worker/handlers/koji.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,34 @@
"""

import logging
from os import getenv
from datetime import datetime
from typing import Optional, Tuple, Type

from celery import signature

from ogr.abstract import GitProject
from packit.config import (
JobConfig,
JobType,
)
from packit.config.package_config import PackageConfig
from packit.constants import DISTGIT_INSTANCES
from packit.utils.koji_helper import KojiHelper
from packit_service.config import PackageConfigGetter
from packit_service.constants import (
KojiBuildState,
)
from packit_service.constants import KojiTaskState
from packit_service.utils import (
dump_job_config,
dump_package_config,
)
from packit_service.models import (
AbstractProjectObjectDbType,
KojiBuildTargetModel,
ProjectEventModel,
SidetagModel,
)
from packit_service.service.urls import (
get_koji_build_info_url,
Expand All @@ -31,6 +42,7 @@
from packit_service.worker.checker.koji import (
PermissionOnKoji,
IsJobConfigTriggerMatching,
SidetagExists,
)
from packit_service.worker.events import (
CheckRerunCommitEvent,
Expand All @@ -45,7 +57,7 @@
AbstractPRCommentEvent,
ReleaseGitlabEvent,
)
from packit_service.worker.events.koji import KojiBuildEvent
from packit_service.worker.events.koji import KojiBuildEvent, KojiBuildTagEvent
from packit_service.worker.handlers.abstract import (
JobHandler,
TaskName,
Expand Down Expand Up @@ -354,3 +366,79 @@ def run(self):
self.build.set_build_logs_urls(koji_build_logs)

return TaskResults(success=True, details={"msg": msg})


@configured_as(job_type=JobType.koji_build_tag)
@reacts_to(event=KojiBuildTagEvent)
class KojiBuildTagHandler(
JobHandler, ConfigFromEventMixin, PackitAPIWithDownstreamMixin
):
task_name = TaskName.koji_build_tag

_koji_helper: Optional[KojiHelper] = None

@property
def koji_helper(self):
if not self._koji_helper:
self._koji_helper = KojiHelper()
return self._koji_helper

@staticmethod
def get_checkers() -> Tuple[Type[Checker], ...]:
return (SidetagExists,)

def run(self) -> TaskResults:
dg_base_url = getenv("DISTGIT_URL", DISTGIT_INSTANCES["fedpkg"].url)
sidetag = SidetagModel.get_by_koji_name(self.data.tag_name)
sidetag_group = sidetag.sidetag_group.name
builds = self.koji_helper.get_builds_in_tag(self.data.tag_name)
tagged_packages = {b["package_name"] for b in builds}
logger.debug(f"Packages tagged into {self.data.tag_name}: {tagged_packages}")

packages_to_trigger = set()
for package_name in tagged_packages:
distgit_project_url = f"{dg_base_url}rpms/{package_name}"
project = self.service_config.get_project(url=distgit_project_url)
packages_config = PackageConfigGetter.get_package_config_from_repo(
base_project=None,
project=project,
pr_id=None,
reference=None,
fail_when_missing=True,
)
for job in packages_config.get_job_views():
if (
job.type == JobType.koji_build
and job.sidetag_group == sidetag_group
):
packages_to_trigger.update(job.dependents)
logger.debug(f"Packages to trigger: {packages_to_trigger}")

for package_name in packages_to_trigger:
distgit_project_url = f"{dg_base_url}rpms/{package_name}"
project = self.service_config.get_project(url=distgit_project_url)
packages_config = PackageConfigGetter.get_package_config_from_repo(
base_project=None,
project=project,
pr_id=None,
reference=None,
fail_when_missing=True,
)
for job in packages_config.get_job_views():
if (
job.type == JobType.koji_build
and job.sidetag_group == sidetag_group
):
event_dict = self.data.get_dict()
event_dict["git_ref"] = sidetag.target
signature(
TaskName.downstream_koji_build.value,
kwargs={
"event": event_dict,
"package_config": dump_package_config(packages_config),
"job_config": dump_job_config(job),
},
).apply_async()

msg = f"Tag {self.data.tag_name} event handled."
return TaskResults(success=True, details={"msg": msg})
11 changes: 10 additions & 1 deletion packit_service/worker/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,10 @@
PullFromUpstreamHandler,
)
from packit_service.worker.handlers.forges import GithubFasVerificationHandler
from packit_service.worker.handlers.koji import KojiBuildReportHandler
from packit_service.worker.handlers.koji import (
KojiBuildReportHandler,
KojiBuildTagHandler,
)
from packit_service.worker.helpers.build.babysit import (
check_copr_build,
check_pending_copr_builds,
Expand Down Expand Up @@ -557,6 +560,12 @@ def babysit_vm_image_build(self, build_id: int):
)


@celery_app.task(name=TaskName.koji_build_tag, base=TaskWithRetry)
def run_koji_build_tag_handler(event: dict, package_config: dict, job_config: dict):
handler = KojiBuildTagHandler(package_config=None, job_config=None, event=event)
return get_handlers_task_results(handler.run_job(), event)


def get_handlers_task_results(results: dict, event: dict) -> dict:
# include original event to provide more info
return {"job": results, "event": event}
Expand Down
6 changes: 6 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,12 @@ def koji_build_completed_epel8():
return load_the_message_from_file(outfile)


@pytest.fixture()
def koji_build_tagged():
with open(DATA_DIR / "fedmsg" / "koji_build_tagged.json") as outfile:
return load_the_message_from_file(outfile)


def pytest_assertrepr_compare(op, left, right):
if isinstance(left, JobConfig) and isinstance(right, JobConfig) and op == "==":
from packit.schema import JobConfigSchema
Expand Down
26 changes: 26 additions & 0 deletions tests/data/fedmsg/koji_build_tagged.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"body": {
"base_url": "https://koji.fedoraproject.org",
"build_id": 1234567,
"instance": "primary",
"name": "python-specfile",
"owner": "nforro",
"release": "1.fc40",
"tag": "f40-build-side-12345",
"tag_id": 12345,
"user": "nforro",
"version": "0.31.0"
},
"headers": {
"fedora_messaging_rpm_python-specfile": true,
"fedora_messaging_schema": "koji_fedoramessaging.tag.TagV1",
"fedora_messaging_severity": 10,
"fedora_messaging_user_nforro": true,
"priority": 2,
"sent-at": "2024-06-20T15:04:24+00:00"
},
"id": "0b2addd5-e1b8-4ebe-9e2a-9b1b21a8bbad",
"priority": 2,
"queue": null,
"topic": "org.fedoraproject.prod.buildsys.tag"
}
95 changes: 95 additions & 0 deletions tests/integration/test_listen_to_fedmsg.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from packit.config.requirements import RequirementsConfig, LabelRequirementsConfig
from packit.copr_helper import CoprHelper
from packit.local_project import LocalProject
from packit.utils.koji_helper import KojiHelper
from packit_service.config import PackageConfigGetter, ServiceConfig
from packit_service.constants import COPR_API_FAIL_STATE, DEFAULT_RETRY_LIMIT
from packit_service.models import (
Expand All @@ -37,6 +38,7 @@
BuildStatus,
ProjectReleaseModel,
GitBranchModel,
SidetagModel,
)
from packit_service.service.urls import (
get_copr_build_info_url,
Expand All @@ -45,6 +47,7 @@
)
from packit_service.worker.helpers.build.copr_build import CoprBuildJobHelper
from packit_service.worker.events import AbstractCoprBuildEvent, KojiTaskEvent
from packit_service.worker.events.koji import KojiBuildTagEvent
from packit_service.worker.handlers import CoprBuildEndHandler
from packit_service.worker.jobs import SteveJobs
from packit_service.worker.monitoring import Pushgateway
Expand All @@ -53,6 +56,7 @@
run_copr_build_end_handler,
run_copr_build_start_handler,
run_koji_build_report_handler,
run_koji_build_tag_handler,
run_testing_farm_handler,
)
from packit_service.worker.helpers.testing_farm import TestingFarmJobHelper
Expand Down Expand Up @@ -166,6 +170,56 @@ def pc_koji_build_pr():
)


@pytest.fixture(scope="module")
def pc_koji_build_tag_specfile():
return PackageConfig(
jobs=[
JobConfig(
type=JobType.koji_build,
trigger=JobConfigTriggerType.commit,
sidetag_group="test",
dependents=["packit"],
packages={
"specfile": CommonPackageConfig(
_targets=["fedora-all"],
specfile_path="python-specfile.spec",
)
},
),
],
packages={
"specfile": CommonPackageConfig(
specfile_path="python-specfile.spec",
),
},
)


@pytest.fixture(scope="module")
def pc_koji_build_tag_packit():
return PackageConfig(
jobs=[
JobConfig(
type=JobType.koji_build,
trigger=JobConfigTriggerType.koji_build,
sidetag_group="test",
dependencies=["python-specfile"],
packages={
"packit": CommonPackageConfig(
_targets=["fedora-all"],
specfile_path="packit.spec",
)
},
),
],
packages={
"packit": CommonPackageConfig(
specfile_path="packit.spec",
),
},
)


@pytest.fixture(scope="module")
def pc_build_push():
return PackageConfig(
Expand Down Expand Up @@ -2493,6 +2547,47 @@ def test_koji_build_end(koji_build_scratch_end, pc_koji_build_pr, koji_build_pr)
assert first_dict_value(results["job"])["success"]


def test_koji_build_tag(
koji_build_tagged, pc_koji_build_tag_specfile, pc_koji_build_tag_packit
):
flexmock(KojiHelper).should_receive("get_build_info").with_args(1234567).and_return(
{"task_id": 7654321}
)

flexmock(KojiBuildTagEvent).should_receive("get_packages_config").and_return(
pc_koji_build_tag_specfile
)

flexmock(SidetagModel).should_receive("get_by_koji_name").with_args(
"f40-build-side-12345"
).and_return(flexmock(sidetag_group=flexmock(name="test"), target="f40"))

flexmock(KojiHelper).should_receive("get_builds_in_tag").with_args(
"f40-build-side-12345"
).and_return([{"package_name": "python-specfile"}])

flexmock(PackageConfigGetter).should_receive(
"get_package_config_from_repo"
).and_return(pc_koji_build_tag_specfile).and_return(pc_koji_build_tag_packit)

flexmock(Signature).should_receive("apply_async").once()
flexmock(celery_group).should_receive("apply_async").once()

processing_results = SteveJobs().process_message(koji_build_tagged)
event_dict, job, job_config, package_config = get_parameters_from_results(
processing_results
)
assert json.dumps(event_dict)

results = run_koji_build_tag_handler(
package_config=package_config,
event=event_dict,
job_config=job_config,
)

assert first_dict_value(results["job"])["success"]


def test_srpm_build_end(srpm_build_end, pc_build_pr, srpm_build_model):
pr = flexmock(source_project=flexmock())
flexmock(GithubProject).should_receive("is_private").and_return(False)
Expand Down
Loading

0 comments on commit 76b844f

Please sign in to comment.