diff --git a/packit_service/utils.py b/packit_service/utils.py index 648dac1384..21fe3cfe33 100644 --- a/packit_service/utils.py +++ b/packit_service/utils.py @@ -2,16 +2,21 @@ # SPDX-License-Identifier: MIT import logging +import os from datetime import datetime, timezone from io import StringIO from logging import StreamHandler +from pathlib import Path from re import search from typing import List, Tuple, Optional +import requests + from ogr.abstract import PullRequest from packit.config import JobConfig, PackageConfig from packit.schema import JobConfigSchema, PackageConfigSchema from packit.utils import PackitFormatter +from packit_service import __version__ as ps_version logger = logging.getLogger(__name__) @@ -253,3 +258,34 @@ def pr_labels_match_configuration( not configured_labels_absent or all(label not in pr_labels for label in configured_labels_absent) ) + + +def download_file(url: str, path: Path): + """ + Download a file from given url to the given path. + + Returns: + True if the download was successful, False otherwise + """ + user_agent = ( + os.getenv("PACKIT_USER_AGENT") + or f"packit-service/{ps_version} (hello@packit.dev)" + ) + try: + with requests.get( + url, + headers={"User-Agent": user_agent}, + # connection and read timout + timeout=(10, 30), + stream=True, + ) as response: + response.raise_for_status() + with open(path, "wb") as f: + for chunk in response.iter_content(chunk_size=8192): + f.write(chunk) + except requests.exceptions.RequestException as e: + msg = f"Failed to download file from {url}" + logger.debug(f"{msg}: {e!r}") + return False + + return True diff --git a/packit_service/worker/handlers/copr.py b/packit_service/worker/handlers/copr.py index 5ba34ae0c5..780fa2ed0b 100644 --- a/packit_service/worker/handlers/copr.py +++ b/packit_service/worker/handlers/copr.py @@ -2,7 +2,10 @@ # SPDX-License-Identifier: MIT import logging +import tempfile from datetime import datetime, timezone +from os.path import basename +from pathlib import Path from typing import Tuple, Type, Optional from celery import signature, Task @@ -29,6 +32,7 @@ dump_package_config, elapsed_seconds, pr_labels_match_configuration, + download_file, ) from packit_service.worker.checker.abstract import Checker from packit_service.worker.checker.copr import ( @@ -344,6 +348,7 @@ def run(self): self.set_built_packages() self.build.set_status(BuildStatus.success) self.handle_testing_farm() + # self.handle_scan() return TaskResults(success=True, details={}) @@ -463,3 +468,26 @@ def handle_testing_farm(self): "build_id": self.build.id, }, ).apply_async() + + def handle_scan(self): + if ( + self.build.target != "fedora-rawhide-x86_64" + or not self.job_config.differential_scan_after_copr_build + ): + return + + logger.info("About to trigger scan in OpenScanHub.") + + # TODO handle the base build check and download and add it to the run_osh_build call + + directory = tempfile.mkdtemp() + + srpm_model = self.build.get_srpm_build() + srpm_path = Path(directory).joinpath(basename(srpm_model.url)) + + if not download_file(srpm_model.url, srpm_path): + return + + self.copr_build_helper.api.run_osh_build(srpm_path=srpm_path) + + # TODO reporting and cleanup diff --git a/tests/unit/test_scan.py b/tests/unit/test_scan.py new file mode 100644 index 0000000000..a8b32c0c61 --- /dev/null +++ b/tests/unit/test_scan.py @@ -0,0 +1,32 @@ +# Copyright Contributors to the Packit project. +# SPDX-License-Identifier: MIT + +from packit.api import PackitAPI +from packit_service.models import CoprBuildTargetModel +from packit_service.worker.handlers import CoprBuildEndHandler +from packit_service.worker.handlers import copr +from packit_service.worker.events import AbstractCoprBuildEvent +from flexmock import flexmock + + +def test_handle_scan(): + srpm_mock = flexmock(url="https://some-url/my-srpm.src.rpm") + flexmock(CoprBuildTargetModel).should_receive("get_by_build_id").and_return( + flexmock( + get_srpm_build=lambda: srpm_mock, + target="fedora-rawhide-x86_64", + get_project_event_model=lambda: None, + ) + ) + flexmock(AbstractCoprBuildEvent).should_receive("from_event_dict").and_return( + flexmock(chroot="fedora-rawhide-x86_64", build_id="123") + ) + + flexmock(copr).should_receive("download_file").once().and_return(True) + flexmock(PackitAPI).should_receive("run_osh_build").once() + + CoprBuildEndHandler( + package_config=flexmock(), + job_config=flexmock(differential_scan_after_copr_build=True), + event={}, + ).handle_scan()