Ejemplo n.º 1
0
    def report_successful_build(self):
        if (self.copr_build_helper.job_build
                and self.copr_build_helper.job_build.trigger
                == JobConfigTriggerType.pull_request and self.copr_event.pr_id
                and isinstance(self.project, (GithubProject, GitlabProject))
                and not self.was_last_packit_comment_with_congratulation() and
                self.job_config.notifications.pull_request.successful_build):
            msg = (
                f"Congratulations! One of the builds has completed. :champagne:\n\n"
                "You can install the built RPMs by following these steps:\n\n"
                "* `sudo yum install -y dnf-plugins-core` on RHEL 8\n"
                "* `sudo dnf install -y dnf-plugins-core` on Fedora\n"
                f"* `dnf copr enable {self.copr_event.owner}/{self.copr_event.project_name}`\n"
                "* And now you can install the packages.\n"
                "\nPlease note that the RPMs should be used only in a testing environment."
            )
            self.project.get_pr(self.copr_event.pr_id).comment(msg)

        url = get_copr_build_info_url(self.build.id)

        self.copr_build_helper.report_status_to_build_for_chroot(
            state=BaseCommitStatus.success,
            description="RPMs were built successfully.",
            url=url,
            chroot=self.copr_event.chroot,
        )
        self.copr_build_helper.report_status_to_test_for_chroot(
            state=BaseCommitStatus.pending,
            description="RPMs were built successfully.",
            url=url,
            chroot=self.copr_event.chroot,
        )
Ejemplo n.º 2
0
    def run(self):
        if not self.build:
            model = ("SRPMBuildDB" if self.copr_event.chroot
                     == COPR_SRPM_CHROOT else "CoprBuildDB")
            msg = f"Copr build {self.copr_event.build_id} not in {model}."
            logger.warning(msg)
            return TaskResults(success=False, details={"msg": msg})

        self.set_start_time()
        self.set_logs_url()

        if self.copr_event.chroot == COPR_SRPM_CHROOT:
            url = get_srpm_build_info_url(self.build.id)
            self.copr_build_helper.report_status_to_all(
                description="SRPM build is in progress...",
                state=BaseCommitStatus.running,
                url=url,
            )
            msg = "SRPM build in Copr has started..."
            return TaskResults(success=True, details={"msg": msg})

        self.pushgateway.copr_builds_started.inc()
        url = get_copr_build_info_url(self.build.id)
        self.build.set_status("pending")

        self.copr_build_helper.report_status_to_all_for_chroot(
            description="RPM build is in progress...",
            state=BaseCommitStatus.running,
            url=url,
            chroot=self.copr_event.chroot,
        )
        msg = f"Build on {self.copr_event.chroot} in copr has started..."
        return TaskResults(success=True, details={"msg": msg})
Ejemplo n.º 3
0
    def handle_rpm_build_start(
        self, build_id: int, web_url: str, waiting_for_srpm: bool = False
    ):
        """
        Create models for Copr build chroots and report start of RPM build
        if the SRPM is already built.
        """
        unprocessed_chroots = []
        for chroot in self.build_targets:
            if chroot not in self.available_chroots:
                self.report_status_to_all_for_chroot(
                    state=BaseCommitStatus.error,
                    description=f"Not supported target: {chroot}",
                    url=get_srpm_build_info_url(self.srpm_model.id),
                    chroot=chroot,
                )
                self.monitor_not_submitted_copr_builds(1, "not_supported_target")
                unprocessed_chroots.append(chroot)
                continue

            copr_build = CoprBuildModel.create(
                build_id=str(build_id),
                commit_sha=self.metadata.commit_sha,
                project_name=self.job_project,
                owner=self.job_owner,
                web_url=web_url,
                target=chroot,
                status="waiting_for_srpm" if waiting_for_srpm else "pending",
                run_model=self.run_model,
                task_accepted_time=self.metadata.task_accepted_time,
            )
            if not waiting_for_srpm:
                url = get_copr_build_info_url(id_=copr_build.id)
                self.report_status_to_all_for_chroot(
                    state=BaseCommitStatus.running,
                    description="Starting RPM build...",
                    url=url,
                    chroot=chroot,
                )

        if unprocessed_chroots:
            unprocessed = "\n".join(sorted(unprocessed_chroots))
            available = "\n".join(sorted(self.available_chroots))
            self.status_reporter.comment(
                body="There are build targets that are not supported by COPR.\n"
                "<details>\n<summary>Unprocessed build targets</summary>\n\n"
                f"```\n{unprocessed}\n```\n</details>\n"
                "<details>\n<summary>Available build targets</summary>\n\n"
                f"```\n{available}\n```\n</details>",
            )

        # release the hounds!
        celery_app.send_task(
            "task.babysit_copr_build",
            args=(build_id,),
            countdown=120,  # do the first check in 120s
        )
Ejemplo n.º 4
0
    def run_with_copr_builds(self, targets: List[str], failed: Dict):
        targets_without_builds = []
        targets_with_builds = {}

        for target in targets:
            if self.build_id:
                copr_build = CoprBuildModel.get_by_id(self.build_id)
            else:
                copr_build = self.testing_farm_job_helper.get_latest_copr_build(
                    target=target, commit_sha=self.data.commit_sha)

            if copr_build:
                targets_with_builds[target] = copr_build
            else:
                targets_without_builds.append(target)

        # Trigger copr build for targets missing build
        if targets_without_builds:
            logger.info(
                f"Missing Copr build for targets {targets_without_builds} in "
                f"{self.testing_farm_job_helper.job_owner}/"
                f"{self.testing_farm_job_helper.job_project}"
                f" and commit:{self.data.commit_sha}, running a new Copr build."
            )

            for missing_target in targets_without_builds:
                self.testing_farm_job_helper.report_status_to_test_for_chroot(
                    state=BaseCommitStatus.pending,
                    description="Missing Copr build for this target, "
                    "running a new Copr build.",
                    url="",
                    chroot=missing_target,
                )

            event_data = self.data.get_dict()
            event_data["targets_override"] = targets_without_builds
            self.run_copr_build_handler(event_data,
                                        len(targets_without_builds))

        for target, copr_build in targets_with_builds.items():
            if copr_build.status != PG_COPR_BUILD_STATUS_SUCCESS:
                logger.info(
                    "The latest build was not successful, not running tests for it."
                )
                self.testing_farm_job_helper.report_status_to_test_for_chroot(
                    state=BaseCommitStatus.failure,
                    description="The latest build was not successful, "
                    "not running tests for it.",
                    chroot=target,
                    url=get_copr_build_info_url(copr_build.id),
                )
                continue

            logger.info(f"Running testing farm for {copr_build}:{target}.")
            self.run_for_target(target=target, build=copr_build, failed=failed)
Ejemplo n.º 5
0
def test_copr_build_not_comment_on_success(copr_build_end, pc_build_pr,
                                           copr_build_pr):
    flexmock(GithubProject).should_receive("is_private").and_return(False)
    flexmock(GithubProject).should_receive("get_pr").and_return(
        flexmock(source_project=flexmock()).should_receive("comment").never())
    flexmock(AbstractCoprBuildEvent).should_receive(
        "get_package_config").and_return(pc_build_pr)
    flexmock(CoprBuildJobHelper).should_receive("get_build_check").and_return(
        EXPECTED_BUILD_CHECK_NAME)

    flexmock(CoprBuildEndHandler).should_receive(
        "was_last_packit_comment_with_congratulation").and_return(True)

    flexmock(CoprBuildModel).should_receive("get_by_build_id").and_return(
        copr_build_pr)
    copr_build_pr.should_call("set_status").with_args("success").once()
    copr_build_pr.should_receive("set_end_time").once()
    url = get_copr_build_info_url(1)
    flexmock(requests).should_receive("get").and_return(requests.Response())
    flexmock(
        requests.Response).should_receive("raise_for_status").and_return(None)

    # check if packit-service set correct PR status
    flexmock(StatusReporter).should_receive("report").with_args(
        state=BaseCommitStatus.success,
        description="RPMs were built successfully.",
        url=url,
        check_names=CoprBuildJobHelper.get_build_check(
            copr_build_end["chroot"]),
        markdown_content=None,
    ).once()

    # skip testing farm
    flexmock(CoprBuildJobHelper).should_receive(
        "get_built_packages").and_return([])
    flexmock(CoprBuildJobHelper).should_receive("job_tests").and_return(None)
    flexmock(Signature).should_receive("apply_async").once()
    flexmock(Pushgateway).should_receive("push").once().and_return()

    # skip SRPM url since it touches multiple classes
    flexmock(CoprBuildEndHandler).should_receive("set_srpm_url").and_return(
        None)

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

    run_copr_build_end_handler(
        package_config=package_config,
        event=event_dict,
        job_config=job_config,
    )
Ejemplo n.º 6
0
    def run(self):
        if not self.build:
            # TODO: how could this happen?
            model = ("SRPMBuildDB" if self.copr_event.chroot
                     == COPR_SRPM_CHROOT else "CoprBuildDB")
            msg = f"Copr build {self.copr_event.build_id} not in {model}."
            logger.warning(msg)
            return TaskResults(success=False, details={"msg": msg})

        if self.build.status in [
                PG_BUILD_STATUS_FAILURE,
                PG_BUILD_STATUS_SUCCESS,
        ]:
            msg = (f"Copr build {self.copr_event.build_id} is already"
                   f" processed (status={self.copr_event.build.status}).")
            logger.info(msg)
            return TaskResults(success=True, details={"msg": msg})

        self.set_end_time()
        self.set_srpm_url()

        if self.copr_event.chroot == COPR_SRPM_CHROOT:
            return self.handle_srpm_end()

        self.pushgateway.copr_builds_finished.inc()

        # if the build is needed only for test, it doesn't have the task_accepted_time
        if self.build.task_accepted_time:
            copr_build_time = measure_time(end=datetime.now(timezone.utc),
                                           begin=self.build.task_accepted_time)
            self.pushgateway.copr_build_finished_time.observe(copr_build_time)

        # https://pagure.io/copr/copr/blob/master/f/common/copr_common/enums.py#_42
        if self.copr_event.status != COPR_API_SUCC_STATE:
            failed_msg = "RPMs failed to be built."
            self.copr_build_helper.report_status_to_all_for_chroot(
                state=BaseCommitStatus.failure,
                description=failed_msg,
                url=get_copr_build_info_url(self.build.id),
                chroot=self.copr_event.chroot,
            )
            self.build.set_status(PG_BUILD_STATUS_FAILURE)
            return TaskResults(success=False, details={"msg": failed_msg})

        self.report_successful_build()
        self.build.set_status(PG_BUILD_STATUS_SUCCESS)

        built_packages = self.copr_build_helper.get_built_packages(
            int(self.build.build_id), self.build.target)
        self.build.set_built_packages(built_packages)
        self.handle_testing_farm()

        return TaskResults(success=True, details={})
Ejemplo n.º 7
0
def test_copr_build_just_tests_defined(copr_build_start, pc_tests,
                                       copr_build_pr):
    flexmock(GithubProject).should_receive("is_private").and_return(False)
    flexmock(GithubProject).should_receive("get_pr").and_return(
        flexmock(source_project=flexmock()))
    flexmock(AbstractCoprBuildEvent).should_receive(
        "get_package_config").and_return(pc_tests)
    flexmock(TestingFarmJobHelper).should_receive(
        "get_build_check").and_return(EXPECTED_BUILD_CHECK_NAME)
    flexmock(TestingFarmJobHelper).should_receive("get_test_check").and_return(
        EXPECTED_TESTING_FARM_CHECK_NAME)

    flexmock(CoprBuildModel).should_receive("get_by_build_id").and_return(
        copr_build_pr)
    url = get_copr_build_info_url(1)
    flexmock(requests).should_receive("get").and_return(requests.Response())
    flexmock(
        requests.Response).should_receive("raise_for_status").and_return(None)
    copr_build_pr.should_receive("set_start_time").once()
    copr_build_pr.should_call("set_status").with_args("pending").once()
    copr_build_pr.should_receive("set_build_logs_url")

    # check if packit-service sets the correct PR status
    flexmock(StatusReporter).should_receive("report").with_args(
        state=BaseCommitStatus.running,
        description="RPM build is in progress...",
        url=url,
        check_names=EXPECTED_BUILD_CHECK_NAME,
        markdown_content=None,
    ).never()

    flexmock(StatusReporter).should_receive("report").with_args(
        state=BaseCommitStatus.running,
        description="RPM build is in progress...",
        url=url,
        check_names=TestingFarmJobHelper.get_test_check(
            copr_build_start["chroot"]),
        markdown_content=None,
    ).once()
    flexmock(Signature).should_receive("apply_async").once()
    flexmock(Pushgateway).should_receive("push").once().and_return()

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

    run_copr_build_start_handler(
        package_config=package_config,
        event=event_dict,
        job_config=job_config,
    )
Ejemplo n.º 8
0
def test_get_logs(client):
    chroot = "foo-1-x86_64"
    state = "success"
    build_id = 2

    project_mock = flexmock()
    project_mock.namespace = "john-foo"
    project_mock.repo_name = "bar"

    pr_mock = flexmock()
    pr_mock.job_trigger_model_type = JobTriggerModelType.pull_request
    pr_mock.pr_id = 234
    pr_mock.target_project = project_mock

    srpm_build_mock = flexmock()
    srpm_build_mock.id = 11
    srpm_build_mock.url = "https://some.random.copr.subdomain.org/my_srpm.srpm"
    srpm_build_mock.build_submitted_time = datetime(
        year=2020, month=1, day=1, hour=0, minute=0, second=0, microsecond=0
    )

    copr_build_mock = flexmock()
    copr_build_mock.target = chroot
    copr_build_mock.build_id = str(build_id)
    copr_build_mock.status = state
    copr_build_mock.web_url = (
        "https://copr.fedorainfracloud.org/coprs/john-foo-bar/john-foo-bar/build/2/"
    )
    copr_build_mock.build_logs_url = "https://localhost:5000/build/2/foo-1-x86_64/logs"
    copr_build_mock.owner = "packit"
    copr_build_mock.build_submitted_time = datetime(
        year=2020, month=1, day=1, hour=0, minute=0, second=0, microsecond=0
    )
    copr_build_mock.project_name = "example_project"
    copr_build_mock.should_receive("get_trigger_object").and_return(pr_mock)
    copr_build_mock.should_receive("get_project").and_return(project_mock)
    copr_build_mock.should_receive("get_srpm_build").and_return(srpm_build_mock)

    flexmock(CoprBuildModel).should_receive("get_by_id").and_return(copr_build_mock)

    logs_url = get_copr_build_info_url(1)
    assert logs_url == "https://localhost/results/copr-builds/1"
Ejemplo n.º 9
0
    def run(self):
        build_job_helper = CoprBuildJobHelper(
            service_config=self.service_config,
            package_config=self.package_config,
            project=self.project,
            metadata=self.data,
            db_trigger=self.db_trigger,
            job_config=self.job_config,
            pushgateway=self.pushgateway,
        )

        if self.copr_event.chroot == "srpm-builds":
            # we don't want to set the check status for this
            msg = "SRPM build in copr has started."
            logger.debug(msg)
            return TaskResults(success=True, details={"msg": msg})

        if not self.build:
            msg = f"Copr build {self.copr_event.build_id} not in CoprBuildDB."
            logger.warning(msg)
            return TaskResults(success=False, details={"msg": msg})

        self.pushgateway.copr_builds_started.inc()
        start_time = (datetime.utcfromtimestamp(self.copr_event.timestamp)
                      if self.copr_event.timestamp else None)
        self.build.set_start_time(start_time)
        url = get_copr_build_info_url(self.build.id)
        self.build.set_status("pending")
        copr_build_logs = self.copr_event.get_copr_build_logs_url()
        self.build.set_build_logs_url(copr_build_logs)

        build_job_helper.report_status_to_all_for_chroot(
            description="RPM build is in progress...",
            state=BaseCommitStatus.running,
            url=url,
            chroot=self.copr_event.chroot,
        )
        msg = f"Build on {self.copr_event.chroot} in copr has started..."
        return TaskResults(success=True, details={"msg": msg})
Ejemplo n.º 10
0
def test_copr_build_end_failed_testing_farm_no_json(copr_build_end,
                                                    copr_build_pr):
    flexmock(GithubProject).should_receive("is_private").and_return(False)
    flexmock(GithubProject).should_receive("get_pr").and_return(
        flexmock(
            source_project=flexmock(get_web_url=lambda: "abc"),
            target_branch_head_commit="deadbeef",
        ).should_receive("comment").mock())

    config = PackageConfig(jobs=[
        JobConfig(
            type=JobType.copr_build,
            trigger=JobConfigTriggerType.pull_request,
            metadata=JobMetadataConfig(
                _targets=["fedora-rawhide"],
                owner="some-owner",
                project="some-project",
            ),
        ),
        JobConfig(
            type=JobType.tests,
            trigger=JobConfigTriggerType.pull_request,
            metadata=JobMetadataConfig(_targets=["fedora-rawhide"]),
        ),
    ])

    flexmock(AbstractCoprBuildEvent).should_receive(
        "get_package_config").and_return(config)
    flexmock(PackageConfigGetter).should_receive(
        "get_package_config_from_repo").and_return(config)
    flexmock(CoprBuildEndHandler).should_receive(
        "was_last_packit_comment_with_congratulation").and_return(False)

    flexmock(LocalProject).should_receive("refresh_the_arguments").and_return(
        None)

    flexmock(CoprBuildModel).should_receive("get_by_build_id").and_return(
        copr_build_pr)
    flexmock(CoprBuildModel).should_receive("get_by_id").and_return(
        copr_build_pr)
    copr_build_pr.should_call("set_status").with_args("success").once()
    copr_build_pr.should_receive("set_end_time").once()
    url = get_copr_build_info_url(1)
    flexmock(requests).should_receive("get").and_return(requests.Response())
    flexmock(
        requests.Response).should_receive("raise_for_status").and_return(None)
    # check if packit-service set correct PR status
    flexmock(StatusReporter).should_receive("report").with_args(
        state=BaseCommitStatus.success,
        description="RPMs were built successfully.",
        url=url,
        check_names=EXPECTED_BUILD_CHECK_NAME,
        markdown_content=None,
    ).once()

    flexmock(StatusReporter).should_receive("report").with_args(
        state=BaseCommitStatus.pending,
        description="RPMs were built successfully.",
        url=url,
        check_names=EXPECTED_TESTING_FARM_CHECK_NAME,
        markdown_content=None,
    ).once()

    flexmock(TestingFarmJobHelper).should_receive(
        "is_fmf_configured").and_return(True)
    flexmock(TestingFarmJobHelper).should_receive(
        "send_testing_farm_request").and_return(
            RequestResponse(
                status_code=400,
                ok=False,
                content=b"some text error",
                reason="some text error",
                json=None,
            ))

    flexmock(CoprBuildModel).should_receive("set_status").with_args("failure")
    flexmock(StatusReporter).should_receive("report").with_args(
        state=BaseCommitStatus.running,
        description="Build succeeded. Submitting the tests ...",
        check_names=EXPECTED_TESTING_FARM_CHECK_NAME,
        url="",
        markdown_content=None,
    ).once()
    flexmock(StatusReporter).should_receive("report").with_args(
        state=BaseCommitStatus.failure,
        description="Failed to submit tests: some text error",
        check_names=EXPECTED_TESTING_FARM_CHECK_NAME,
        url="",
        markdown_content=None,
    ).once()

    flexmock(Signature).should_receive("apply_async").twice()
    flexmock(Pushgateway).should_receive("push").twice().and_return()

    # skip SRPM url since it touches multiple classes
    flexmock(CoprBuildEndHandler).should_receive("set_srpm_url").and_return(
        None)

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

    flexmock(CoprBuildJobHelper).should_receive(
        "get_built_packages").and_return([])

    run_copr_build_end_handler(
        package_config=package_config,
        event=event_dict,
        job_config=job_config,
    )

    flexmock(TestingFarmHandler).should_receive("db_trigger").and_return(
        copr_build_pr.get_trigger_object())

    run_testing_farm_handler(
        package_config=package_config,
        event=event_dict,
        job_config=job_config,
        chroot="fedora-rawhide-x86_64",
        build_id=flexmock(),
    )
Ejemplo n.º 11
0
def test_copr_build_end_testing_farm(copr_build_end, copr_build_pr):
    tft_api_url = "https://api.dev.testing-farm.io/v0.1/"
    service_config = ServiceConfig(testing_farm_api_url=tft_api_url,
                                   testing_farm_secret="secret token")
    flexmock(ServiceConfig).should_receive("get_service_config").and_return(
        service_config)
    flexmock(GithubProject).should_receive("is_private").and_return(False)
    flexmock(GithubProject).should_receive("get_pr").and_return(
        flexmock(
            source_project=flexmock(
                get_web_url=lambda: "https://github.com/foo/bar"),
            target_branch_head_commit="deadbeef",
        ).should_receive("comment").mock())
    urls.DASHBOARD_URL = "https://dashboard.localhost"

    config = PackageConfig(jobs=[
        JobConfig(
            type=JobType.copr_build,
            trigger=JobConfigTriggerType.pull_request,
            metadata=JobMetadataConfig(
                _targets=["fedora-rawhide"],
                owner="some-owner",
                project="some-project",
            ),
        ),
        JobConfig(
            type=JobType.tests,
            trigger=JobConfigTriggerType.pull_request,
            metadata=JobMetadataConfig(_targets=["fedora-rawhide"]),
        ),
    ])

    flexmock(AbstractCoprBuildEvent).should_receive(
        "get_package_config").and_return(config)
    flexmock(PackageConfigGetter).should_receive(
        "get_package_config_from_repo").and_return(config)
    flexmock(CoprBuildEndHandler).should_receive(
        "was_last_packit_comment_with_congratulation").and_return(False)

    flexmock(LocalProject).should_receive("refresh_the_arguments").and_return(
        None)

    flexmock(CoprBuildModel).should_receive("get_by_build_id").and_return(
        copr_build_pr)
    flexmock(CoprBuildModel).should_receive("get_by_id").and_return(
        copr_build_pr)
    copr_build_pr.should_call("set_status").with_args("success").once()
    copr_build_pr.should_receive("set_end_time").once()
    flexmock(requests).should_receive("get").and_return(requests.Response())
    flexmock(
        requests.Response).should_receive("raise_for_status").and_return(None)
    # check if packit-service set correct PR status
    url = get_copr_build_info_url(1)
    flexmock(StatusReporter).should_receive("report").with_args(
        state=BaseCommitStatus.success,
        description="RPMs were built successfully.",
        url=url,
        check_names=EXPECTED_BUILD_CHECK_NAME,
        markdown_content=None,
    ).once()

    flexmock(StatusReporter).should_receive("report").with_args(
        state=BaseCommitStatus.pending,
        description="RPMs were built successfully.",
        url=url,
        check_names=EXPECTED_TESTING_FARM_CHECK_NAME,
        markdown_content=None,
    ).once()

    payload = {
        "api_key":
        "secret token",
        "test": {
            "fmf": {
                "url": "https://github.com/foo/bar",
                "ref": "0011223344",
            },
        },
        "environments": [{
            "arch":
            "x86_64",
            "os": {
                "compose": "Fedora-Rawhide"
            },
            "tmt": {
                "context": {
                    "distro": "fedora-rawhide",
                    "arch": "x86_64",
                    "trigger": "commit",
                }
            },
            "artifacts": [
                {
                    "id": "1:fedora-rawhide-x86_64",
                    "type": "fedora-copr-build",
                    "packages": ["bar-0.1-1.noarch"],
                },
            ],
            "variables": {
                "PACKIT_FULL_REPO_NAME": "foo/bar",
                "PACKIT_COMMIT_SHA": "0011223344",
                "PACKIT_PACKAGE_NVR": "bar-0.1-1",
                "PACKIT_BUILD_LOG_URL": "https://log-url",
                "PACKIT_TARGET_SHA": "deadbeef",
            },
        }],
        "notification": {
            "webhook": {
                "url": "https://stg.packit.dev/api/testing-farm/results",
                "token": "secret token",
            }
        },
    }

    flexmock(TestingFarmJobHelper).should_receive(
        "is_fmf_configured").and_return(True)
    flexmock(TestingFarmJobHelper).should_receive("distro2compose").with_args(
        "fedora-rawhide", "x86_64").and_return("Fedora-Rawhide")

    pipeline_id = "5e8079d8-f181-41cf-af96-28e99774eb68"
    flexmock(TestingFarmJobHelper).should_receive(
        "send_testing_farm_request").with_args(
            endpoint="requests", method="POST", data=payload).and_return(
                RequestResponse(
                    status_code=200,
                    ok=True,
                    content=json.dumps({
                        "id": pipeline_id
                    }).encode(),
                    json={"id": pipeline_id},
                ))

    flexmock(StatusReporter).should_receive("report").with_args(
        state=BaseCommitStatus.running,
        description="Build succeeded. Submitting the tests ...",
        check_names=EXPECTED_TESTING_FARM_CHECK_NAME,
        url="",
        markdown_content=None,
    ).once()

    flexmock(GithubProject).should_receive("get_web_url").and_return(
        "https://github.com/foo/bar")

    tft_test_run_model = flexmock(id=5)
    flexmock(TFTTestRunModel).should_receive("create").with_args(
        pipeline_id=pipeline_id,
        commit_sha="0011223344",
        status=TestingFarmResult.new,
        target="fedora-rawhide-x86_64",
        web_url=None,
        run_model=copr_build_pr.runs[0],
        data={
            "base_project_url": "https://github.com/foo/bar"
        },
    ).and_return(tft_test_run_model)

    flexmock(StatusReporter).should_receive("report").with_args(
        state=BaseCommitStatus.running,
        description="Tests have been submitted ...",
        url="https://dashboard.localhost/results/testing-farm/5",
        check_names=EXPECTED_TESTING_FARM_CHECK_NAME,
        markdown_content=None,
    ).once()
    flexmock(Signature).should_receive("apply_async").twice()

    # skip SRPM url since it touches multiple classes
    flexmock(CoprBuildEndHandler).should_receive("set_srpm_url").and_return(
        None)

    flexmock(Pushgateway).should_receive("push").twice().and_return()

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

    flexmock(CoprBuildJobHelper).should_receive(
        "get_built_packages").and_return([])

    run_copr_build_end_handler(
        package_config=package_config,
        event=event_dict,
        job_config=job_config,
    )

    flexmock(TestingFarmHandler).should_receive("db_trigger").and_return(
        copr_build_pr.get_trigger_object())

    flexmock(CoprBuildModel).should_receive("get_all_by").and_return(
        [copr_build_pr])

    run_testing_farm_handler(
        package_config=package_config,
        event=event_dict,
        job_config=job_config,
        chroot="fedora-rawhide-x86_64",
        build_id=1,
    )
Ejemplo n.º 12
0
def test_copr_build_end(
    copr_build_end,
    pc_build_pr,
    copr_build_pr,
    pc_comment_pr_succ,
    pr_comment_called,
):
    pr = flexmock(source_project=flexmock())
    flexmock(GithubProject).should_receive("is_private").and_return(False)
    flexmock(GithubProject).should_receive("get_pr").and_return(pr)
    pc_build_pr.jobs[
        0].notifications.pull_request.successful_build = pc_comment_pr_succ
    flexmock(AbstractCoprBuildEvent).should_receive(
        "get_package_config").and_return(pc_build_pr)
    flexmock(CoprBuildEndHandler).should_receive(
        "was_last_packit_comment_with_congratulation").and_return(False)
    if pr_comment_called:
        pr.should_receive("comment")
    else:
        pr.should_receive("comment").never()
    flexmock(CoprBuildModel).should_receive("get_by_build_id").and_return(
        copr_build_pr)
    copr_build_pr.should_call("set_status").with_args("success").once()
    copr_build_pr.should_receive("set_end_time").once()

    url = get_copr_build_info_url(1)
    flexmock(requests).should_receive("get").and_return(requests.Response())
    flexmock(
        requests.Response).should_receive("raise_for_status").and_return(None)
    # check if packit-service set correct PR status
    flexmock(StatusReporter).should_receive("report").with_args(
        state=BaseCommitStatus.success,
        description="RPMs were built successfully.",
        url=url,
        check_names=CoprBuildJobHelper.get_build_check(
            copr_build_end["chroot"]),
        markdown_content=None,
    ).once()

    # no test job defined => testing farm should be skipped
    flexmock(TestingFarmJobHelper).should_receive("run_testing_farm").times(0)
    flexmock(Signature).should_receive("apply_async").once()

    # fix SRPM url since it touches multiple classes

    (flexmock(CoprBuildJobHelper).should_receive("get_build").with_args(
        1044215).and_return(
            flexmock(source_package={"url": "https://my.host/my.srpm"
                                     })).at_least().once())
    flexmock(copr_build_pr._srpm_build_for_mocking).should_receive(
        "set_url").with_args("https://my.host/my.srpm").mock()

    flexmock(Pushgateway).should_receive("push").once().and_return()

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

    flexmock(CoprBuildJobHelper).should_receive(
        "get_built_packages").and_return([])

    run_copr_build_end_handler(
        package_config=package_config,
        event=event_dict,
        job_config=job_config,
    )
Ejemplo n.º 13
0
    def run(self):
        build_job_helper = CoprBuildJobHelper(
            service_config=self.service_config,
            package_config=self.package_config,
            project=self.project,
            metadata=self.data,
            db_trigger=self.db_trigger,
            job_config=self.job_config,
            pushgateway=self.pushgateway,
        )

        if self.copr_event.chroot == "srpm-builds":
            # we don't want to set check for this
            msg = "SRPM build in copr has finished."
            logger.debug(msg)
            return TaskResults(success=True, details={"msg": msg})

        if not self.build:
            # TODO: how could this happen?
            msg = f"Copr build {self.copr_event.build_id} not in CoprBuildDB."
            logger.warning(msg)
            return TaskResults(success=False, details={"msg": msg})
        if self.build.status in [
                PG_COPR_BUILD_STATUS_FAILURE,
                PG_COPR_BUILD_STATUS_SUCCESS,
        ]:
            msg = (f"Copr build {self.copr_event.build_id} is already"
                   f" processed (status={self.copr_event.build.status}).")
            logger.info(msg)
            return TaskResults(success=True, details={"msg": msg})

        self.pushgateway.copr_builds_finished.inc()

        # if the build is needed only for test, it doesn't have the task_accepted_time
        if self.build.task_accepted_time:
            copr_build_time = measure_time(end=datetime.now(timezone.utc),
                                           begin=self.build.task_accepted_time)
            self.pushgateway.copr_build_finished_time.observe(copr_build_time)

        end_time = (datetime.utcfromtimestamp(self.copr_event.timestamp)
                    if self.copr_event.timestamp else None)
        self.build.set_end_time(end_time)

        self.set_srpm_url(build_job_helper)

        url = get_copr_build_info_url(self.build.id)

        # https://pagure.io/copr/copr/blob/master/f/common/copr_common/enums.py#_42
        if self.copr_event.status != COPR_API_SUCC_STATE:
            failed_msg = "RPMs failed to be built."
            build_job_helper.report_status_to_all_for_chroot(
                state=BaseCommitStatus.failure,
                description=failed_msg,
                url=url,
                chroot=self.copr_event.chroot,
            )
            self.build.set_status(PG_COPR_BUILD_STATUS_FAILURE)
            return TaskResults(success=False, details={"msg": failed_msg})

        if (build_job_helper.job_build and build_job_helper.job_build.trigger
                == JobConfigTriggerType.pull_request and self.copr_event.pr_id
                and isinstance(self.project, (GithubProject, GitlabProject))
                and not self.was_last_packit_comment_with_congratulation() and
                self.job_config.notifications.pull_request.successful_build):
            msg = (
                f"Congratulations! One of the builds has completed. :champagne:\n\n"
                "You can install the built RPMs by following these steps:\n\n"
                "* `sudo yum install -y dnf-plugins-core` on RHEL 8\n"
                "* `sudo dnf install -y dnf-plugins-core` on Fedora\n"
                f"* `dnf copr enable {self.copr_event.owner}/{self.copr_event.project_name}`\n"
                "* And now you can install the packages.\n"
                "\nPlease note that the RPMs should be used only in a testing environment."
            )
            self.project.get_pr(self.copr_event.pr_id).comment(msg)

        build_job_helper.report_status_to_build_for_chroot(
            state=BaseCommitStatus.success,
            description="RPMs were built successfully.",
            url=url,
            chroot=self.copr_event.chroot,
        )
        build_job_helper.report_status_to_test_for_chroot(
            state=BaseCommitStatus.pending,
            description="RPMs were built successfully.",
            url=url,
            chroot=self.copr_event.chroot,
        )
        self.build.set_status(PG_COPR_BUILD_STATUS_SUCCESS)

        built_packages = build_job_helper.get_built_packages(
            int(self.build.build_id), self.build.target)
        self.build.set_built_packages(built_packages)

        if (build_job_helper.job_tests
                and self.copr_event.chroot in build_job_helper.tests_targets):
            signature(
                TaskName.testing_farm.value,
                kwargs={
                    "package_config": dump_package_config(self.package_config),
                    "job_config": dump_job_config(build_job_helper.job_tests),
                    "event": self.data.get_dict(),
                    "chroot": self.copr_event.chroot,
                    "build_id": self.build.id,
                },
            ).apply_async()
        else:
            logger.debug("Testing farm not in the job config.")

        return TaskResults(success=True, details={})
Ejemplo n.º 14
0
class CoprBuildJobHelper(BaseBuildJobHelper):
    job_type_build = JobType.copr_build
    job_type_test = JobType.tests
    status_name_build: str = "rpm-build"
    status_name_test: str = "testing-farm"

    def __init__(
        self,
        service_config: ServiceConfig,
        package_config: PackageConfig,
        project: GitProject,
        metadata: EventData,
        db_trigger: AbstractTriggerDbType,
        job_config: JobConfig,
        targets_override: Optional[Set[str]] = None,
        pushgateway: Optional[Pushgateway] = None,
    ):
        super().__init__(
            service_config=service_config,
            package_config=package_config,
            project=project,
            metadata=metadata,
            db_trigger=db_trigger,
            job_config=job_config,
            targets_override=targets_override,
            pushgateway=pushgateway,
        )

        self.msg_retrigger: str = MSG_RETRIGGER.format(
            job="build",
            command="copr-build" if self.job_build else "build",
            place="pull request",
        )

    @property
    def default_project_name(self) -> str:
        """
        Project name for copr.

        * use hostname prefix for non-github service
        * replace slash in namespace with dash
        * add `-stg` suffix for the stg app
        """

        service_hostname = parse_git_repo(
            self.project.service.instance_url).hostname
        service_prefix = ("" if isinstance(self.project, GithubProject) else
                          f"{service_hostname}-")

        namespace = self.project.namespace.replace("/", "-")
        stg = "-stg" if self.service_config.deployment == Deployment.stg else ""
        # We want to share project between all releases.
        # More details: https://github.com/packit/packit-service/issues/1044
        identifier = "releases" if self.metadata.tag_name else self.metadata.identifier

        return f"{service_prefix}{namespace}-{self.project.repo}-{identifier}{stg}"

    @property
    def job_project(self) -> Optional[str]:
        """
        The job definition from the config file.
        """
        if self.job_build and self.job_build.metadata.project:
            return self.job_build.metadata.project

        if self.job_tests and self.job_tests.metadata.project:
            return self.job_tests.metadata.project

        return self.default_project_name

    @property
    def job_owner(self) -> Optional[str]:
        """
        Owner used for the copr build -- search the config or use the copr's config.
        """
        if self.job_build and self.job_build.metadata.owner:
            return self.job_build.metadata.owner

        if self.job_tests and self.job_tests.metadata.owner:
            return self.job_tests.metadata.owner

        return self.api.copr_helper.copr_client.config.get("username")

    @property
    def preserve_project(self) -> Optional[bool]:
        """
        If the project will be preserved or can be removed after 60 days.
        """
        return self.job_build.metadata.preserve_project if self.job_build else None

    @property
    def list_on_homepage(self) -> Optional[bool]:
        """
        If the project will be shown on the copr home page.
        """
        return self.job_build.metadata.list_on_homepage if self.job_build else None

    @property
    def additional_repos(self) -> Optional[List[str]]:
        """
        Additional repos that will be enable for copr build.
        """
        return self.job_build.metadata.additional_repos if self.job_build else None

    @property
    def build_targets_all(self) -> Set[str]:
        """
        Return all valid Copr build targets/chroots from config.
        """
        return get_valid_build_targets(*self.configured_build_targets,
                                       default=None)

    @property
    def tests_targets_all(self) -> Set[str]:
        """
        Return all valid test targets/chroots from config.
        """
        return get_valid_build_targets(*self.configured_tests_targets,
                                       default=None)

    @property
    def available_chroots(self) -> Set[str]:
        """
        Returns set of available COPR targets.
        """
        return {
            *filter(
                lambda chroot: not chroot.startswith("_"),
                self.api.copr_helper.get_copr_client().mock_chroot_proxy.
                get_list().keys(),
            )
        }

    def get_built_packages(self, build_id: int, chroot: str) -> List:
        return self.api.copr_helper.copr_client.build_chroot_proxy.get_built_packages(
            build_id, chroot).packages

    def get_build(self, build_id: int):
        return self.api.copr_helper.copr_client.build_proxy.get(build_id)

    def monitor_not_submitted_copr_builds(self, number_of_builds: int,
                                          reason: str):
        """
        Measure the time it took to set the failed status in case of event (e.g. failed SRPM)
        that prevents Copr build to be submitted.
        """
        time = measure_time(end=datetime.now(timezone.utc),
                            begin=self.metadata.task_accepted_time)
        for _ in range(number_of_builds):
            self.pushgateway.copr_build_not_submitted_time.labels(
                reason=reason).observe(time)

    def run_copr_build(self) -> TaskResults:
        self.report_status_to_all(
            description="Building SRPM ...",
            state=BaseCommitStatus.running,
            # pagure requires "valid url"
            url="",
        )
        if results := self.create_srpm_if_needed():
            return results

        if not self.srpm_model.success:
            msg = "SRPM build failed, check the logs for details."
            self.report_status_to_all(
                state=BaseCommitStatus.failure,
                description=msg,
                url=get_srpm_build_info_url(self.srpm_model.id),
            )
            self.monitor_not_submitted_copr_builds(len(self.build_targets),
                                                   "srpm_failure")
            return TaskResults(success=False, details={"msg": msg})

        try:
            build_id, web_url = self.run_build()
        except Exception as ex:
            sentry_integration.send_to_sentry(ex)
            # TODO: Where can we show more info about failure?
            # TODO: Retry
            self.report_status_to_all(
                state=BaseCommitStatus.error,
                description=f"Submit of the build failed: {ex}",
            )
            self.monitor_not_submitted_copr_builds(len(self.build_targets),
                                                   "submit_failure")
            return TaskResults(
                success=False,
                details={
                    "msg": "Submit of the Copr build failed.",
                    "error": str(ex)
                },
            )

        unprocessed_chroots = []
        for chroot in self.build_targets:
            if chroot not in self.available_chroots:
                self.report_status_to_all_for_chroot(
                    state=BaseCommitStatus.error,
                    description=f"Not supported target: {chroot}",
                    url=get_srpm_build_info_url(self.srpm_model.id),
                    chroot=chroot,
                )
                self.monitor_not_submitted_copr_builds(1,
                                                       "not_supported_target")
                unprocessed_chroots.append(chroot)
                continue

            copr_build = CoprBuildModel.create(
                build_id=str(build_id),
                commit_sha=self.metadata.commit_sha,
                project_name=self.job_project,
                owner=self.job_owner,
                web_url=web_url,
                target=chroot,
                status="pending",
                run_model=self.run_model,
                task_accepted_time=self.metadata.task_accepted_time,
            )
            url = get_copr_build_info_url(id_=copr_build.id)
            self.report_status_to_all_for_chroot(
                state=BaseCommitStatus.running,
                description="Starting RPM build...",
                url=url,
                chroot=chroot,
            )

        if unprocessed_chroots:
            unprocessed = "\n".join(sorted(unprocessed_chroots))
            available = "\n".join(sorted(self.available_chroots))
            self.status_reporter.comment(
                body="There are build targets that are not supported by COPR.\n"
                "<details>\n<summary>Unprocessed build targets</summary>\n\n"
                f"```\n{unprocessed}\n```\n</details>\n"
                "<details>\n<summary>Available build targets</summary>\n\n"
                f"```\n{available}\n```\n</details>", )

        # release the hounds!
        celery_app.send_task(
            "task.babysit_copr_build",
            args=(build_id, ),
            countdown=120,  # do the first check in 120s
        )

        return TaskResults(success=True, details={})