예제 #1
0
    def handle_pull_request(self):

        if not self.job.metadata.get("targets"):
            logger.error(
                "'targets' value is required in packit config for copr_build job"
            )

        collaborators = self.project.who_can_merge_pr()
        r = BuildStatusReporter(self.project, self.event.commit_sha)
        if self.event.github_login not in collaborators:
            msg = "Only collaborators can trigger Packit-as-a-Service"
            r.set_status("failure", msg, PRCheckName.get_build_check())
            return HandlerResults(success=False, details={"msg": msg})
        cbh = CoprBuildHandler(self.config, self.package_config, self.project,
                               self.event)
        handler_results = cbh.run_copr_build()
        if handler_results["success"]:
            # Testing farm is triggered just once copr build is finished as it uses copr builds
            # todo: utilize fedmsg for this.
            test_job_config = self.get_tests_for_build()
            if test_job_config:
                testing_farm_handler = GithubTestingFarmHandler(
                    self.config, test_job_config, self.event)
                testing_farm_handler.run()
            else:
                logger.debug("Testing farm not in the job config.")
            return HandlerResults(success=True, details={})
예제 #2
0
    def check_and_report(self, event: Optional[Any],
                         project: GitProject) -> bool:
        """
        Check if account is approved and report status back in case of PR
        :param event: PullRequest and Release TODO: handle more
        :param project: GitProject
        :return:
        """
        account_name = None
        if isinstance(event, PullRequestEvent):
            account_name = event.base_repo_namespace
        if isinstance(event, ReleaseEvent):
            account_name = event.repo_namespace

        if account_name:
            if not self.is_approved(account_name):
                logger.error(
                    f"User {account_name} is not approved on whitelist!")
                # TODO also check blacklist,
                # but for that we need to know who triggered the action
                if event.trigger == JobTriggerType.pull_request:
                    r = BuildStatusReporter(project, event.commit_sha, None)
                    msg = "Account is not whitelisted!"
                    r.report(
                        "failure",
                        msg,
                        url=FAQ_URL,
                        check_name=PRCheckName.get_build_check(),
                    )
                return False

        return True
예제 #3
0
 def build_check_names(self) -> List[str]:
     if not self._build_check_names:
         self._build_check_names = [
             PRCheckName.get_build_check(chroot)
             for chroot in self.build_chroots
         ]
     return self._build_check_names
예제 #4
0
def test_copr_build_not_comment_on_success(copr_build_end, pc_build,
                                           copr_build):
    steve = SteveJobs()
    flexmock(SteveJobs, _is_private=False)
    flexmock(CoprHelper).should_receive("get_copr_client").and_return(
        Client(
            config={
                "copr_url": "https://copr.fedorainfracloud.org",
                "username": "******",
            }))
    flexmock(CoprBuildJobHelper).should_receive("copr_build_model").and_return(
        flexmock())
    flexmock(CoprBuildEvent).should_receive("get_package_config").and_return(
        pc_build)
    flexmock(PRCheckName).should_receive("get_build_check").and_return(
        PACKIT_STG_CHECK)

    flexmock(CoprBuildEndHandler).should_receive(
        "was_last_build_successful").and_return(True)
    flexmock(GithubProject).should_receive("pr_comment").never()

    flexmock(CoprBuild).should_receive("get_by_build_id").and_return(
        copr_build)
    flexmock(CoprBuild).should_receive("set_status").with_args("success")
    flexmock(CoprBuildDB).should_receive("get_build").and_return({
        "commit_sha":
        "XXXXX",
        "pr_id":
        24,
        "repo_name":
        "hello-world",
        "repo_namespace":
        "packit-service",
        "ref":
        "XXXX",
        "https_url":
        "https://github.com/packit-service/hello-world",
    })

    url = get_log_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(BuildStatusReporter).should_receive("report").with_args(
        state="success",
        description="RPMs were built successfully.",
        url=url,
        check_names=PRCheckName.get_build_check(copr_build_end["chroot"]),
    ).once()

    # skip testing farm
    flexmock(CoprBuildJobHelper).should_receive("job_tests").and_return(None)

    steve.process_message(copr_build_end)
예제 #5
0
 def report_status_to_build_for_chroot(self,
                                       description,
                                       state,
                                       url: str = "",
                                       chroot: str = ""):
     if self.job_copr_build and chroot in self.build_chroots:
         cs = PRCheckName.get_build_check(chroot)
         self.status_reporter.report(
             description=description,
             state=state,
             url=url,
             check_names=cs,
         )
예제 #6
0
    def run(self):
        build = CoprBuildDB().get_build(self.event.build_id)
        if not build:
            # TODO: how could this happen?
            msg = f"Copr build {self.event.build_id} not in CoprBuildDB"
            logger.warning(msg)
            return HandlerResults(success=False, details={"msg": msg})

        r = BuildStatusReporter(self.event.get_project(), build["commit_sha"])

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

        r.report(
            state="pending",
            description="RPM build has started...",
            url=copr_url_from_event(self.event),
            check_names=PRCheckName.get_build_check(self.event.chroot),
        )
예제 #7
0
    def run_copr_build(self) -> HandlerResults:

        if not (self.job_copr_build or self.job_tests):
            msg = "No copr_build or tests job defined."
            # we can't report it to end-user at this stage
            return HandlerResults(success=False, details={"msg": msg})

        try:
            self.report_status_to_all(description="Building SRPM ...",
                                      state="pending")

            # we want to get packit logs from the SRPM creation process
            # so we stuff them into a StringIO buffer
            stream = StringIO()
            handler = logging.StreamHandler(stream)
            packit_logger = logging.getLogger("packit")
            packit_logger.setLevel(logging.DEBUG)
            packit_logger.addHandler(handler)
            formatter = PackitFormatter(None, "%H:%M:%S")
            handler.setFormatter(formatter)

            build_id, _ = self.api.run_copr_build(
                project=self.job_project,
                chroots=self.build_chroots,
                owner=self.job_owner,
            )

            packit_logger.removeHandler(handler)
            stream.seek(0)
            logs = stream.read()
            web_url = get_copr_build_url_for_values(self.job_owner,
                                                    self.job_project, build_id)

            srpm_build = SRPMBuild.create(logs)

            status = "pending"
            description = "Building RPM ..."
            for chroot in self.build_chroots:
                copr_build = CoprBuild.get_or_create(
                    pr_id=self.event.pr_id,
                    build_id=str(build_id),
                    commit_sha=self.event.commit_sha,
                    repo_name=self.event.base_repo_name,
                    namespace=self.event.base_repo_namespace,
                    web_url=web_url,
                    target=chroot,
                    status=status,
                    srpm_build=srpm_build,
                )
                url = get_log_url(id_=copr_build.id)
                self.status_reporter.report(
                    state=status,
                    description=description,
                    url=url,
                    check_names=PRCheckName.get_build_check(chroot),
                )
                if chroot in self.tests_chroots:
                    self.status_reporter.report(
                        state=status,
                        description=description,
                        url=url,
                        check_names=PRCheckName.get_testing_farm_check(chroot),
                    )

        except SandcastleTimeoutReached:
            return self._process_timeout()

        except SandcastleCommandFailed as ex:
            return self._process_failed_command(ex)

        except ApiException as ex:
            return self._process_openshift_error(ex)

        except PackitSRPMException as ex:
            return self._process_failed_srpm_build(ex)

        except PackitCoprProjectException as ex:
            return self._process_copr_submit_exception(ex)

        except PackitCoprException as ex:
            return self._process_general_exception(ex)

        except Exception as ex:
            return self._process_general_exception(ex)

        self.copr_build_model.build_id = build_id
        self.copr_build_model.save()

        return HandlerResults(success=True, details={})
예제 #8
0
    def run_copr_build(self) -> HandlerResults:
        check_name = PRCheckName.get_build_check()
        # add suffix stg when using stg app
        stg = "-stg" if self.config.deployment == Deployment.stg else ""
        default_project_name = (
            f"{self.project.namespace}-{self.project.repo}-{self.event.pr_id}{stg}"
        )
        job = self.get_job_copr_build_metadata()
        if not job.metadata.get("targets"):
            logger.error(
                "'targets' value is required in packit config for copr_build job"
            )

        self.job_project = job.metadata.get("project") or default_project_name
        self.job_owner = job.metadata.get("owner") or self.api.copr.config.get(
            "username")
        self.job_chroots = job.metadata.get("targets")
        r = BuildStatusReporter(self.project, self.event.commit_sha,
                                self.copr_build_model)
        msg_retrigger = (
            f"You can re-trigger copr build by adding a comment (`/packit copr-build`) "
            f"into this pull request.")
        try:
            r.report("pending",
                     "RPM build has just started...",
                     check_name=check_name)
            build_id, repo_url = self.api.run_copr_build(
                project=self.job_project,
                chroots=self.job_chroots,
                owner=self.job_owner)
        except SandcastleTimeoutReached:
            msg = f"You have reached 10-minute timeout while creating the SRPM. {msg_retrigger}"
            self.project.pr_comment(self.event.pr_id, msg)
            msg = "Timeout reached while creating a SRPM."
            r.report("failure", msg, check_name=check_name)
            return HandlerResults(success=False, details={"msg": msg})

        except SandcastleCommandFailed as ex:
            max_log_size = 1024 * 16  # is 16KB enough?
            if len(ex.output) > max_log_size:
                output = "Earlier output was truncated\n\n" + ex.output[
                    -max_log_size:]
            else:
                output = ex.output
            msg = (
                f"There was an error while creating a SRPM. {msg_retrigger}\n"
                "\nOutput:"
                "\n```\n"
                f"{output}"
                "\n```"
                f"\nReturn code: {ex.rc}")
            self.project.pr_comment(self.event.pr_id, msg)
            msg = "Failed to create a SRPM."
            r.report("failure", msg, check_name=check_name)
            return HandlerResults(success=False, details={"msg": msg})

        except FailedCreateSRPM:
            msg = "Failed to create a SRPM."
            r.report("failure", msg, check_name=check_name)
            return HandlerResults(success=False, details={"msg": msg})

        except Exception as ex:
            msg = f"There was an error while running a copr build:\n```\n{ex}\n```\n"
            logger.error(msg)
            self.project.pr_comment(self.event.pr_id,
                                    f"{msg}\n{msg_retrigger}")
            r.report(
                "failure",
                "Build failed, check latest comment for details.",
                check_name=check_name,
            )
            return HandlerResults(success=False, details={"msg": msg})

        self.copr_build_model.build_id = build_id
        self.copr_build_model.save()

        timeout_config = job.metadata.get("timeout")
        timeout = int(timeout_config) if timeout_config else 60 * 60 * 2
        build_state = self.api.watch_copr_build(build_id,
                                                timeout,
                                                report_func=r.report)
        if build_state == "succeeded":
            msg = (
                f"Congratulations! The build [has finished]({repo_url})"
                " successfully. :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.job_owner}/{self.job_project}`\n"
                "* And now you can install the packages.\n"
                "\nPlease note that the RPMs should be used only in a testing environment."
            )
            self.project.pr_comment(self.event.pr_id, msg)
            return HandlerResults(success=True, details={})
        else:
            return HandlerResults(
                success=False,
                details={
                    "msg":
                    (f"Copr build {build_id} failed {build_state}."
                     f"Copr build URL is {repo_url}."
                     f"Handler used by Copr build is {str(self.event.trigger)}"
                     )
                },
            )
예제 #9
0
    def run(self):
        build = CoprBuildDB().get_build(self.event.build_id)
        if not build:
            # TODO: how could this happen?
            msg = f"Copr build {self.event.build_id} not in CoprBuildDB"
            logger.warning(msg)
            return HandlerResults(success=False, details={"msg": msg})

        r = BuildStatusReporter(self.event.get_project(), build["commit_sha"])
        url = copr_url_from_event(self.event)
        build_url = get_copr_build_url(self.event)

        msg = "RPMs failed to be built."
        gh_state = "failure"

        # https://pagure.io/copr/copr/blob/master/f/common/copr_common/enums.py#_42
        if self.event.status == 1:

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

            check_msg = "RPMs were built successfully."
            gh_state = "success"

            if not self.was_last_build_successful():
                msg = (
                    f"Congratulations! The build [has finished]({build_url})"
                    " successfully. :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.event.owner}/{self.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.pr_comment(pr_id=self.event.pr_id, body=msg)
            r.report(
                state=gh_state,
                description=check_msg,
                url=url,
                check_names=PRCheckName.get_build_check(self.event.chroot),
            )

            test_job_config = self.get_tests_for_build()
            if test_job_config:
                testing_farm_handler = GithubTestingFarmHandler(
                    self.config, test_job_config, self.event
                )
                testing_farm_handler.run()
            else:
                logger.debug("Testing farm not in the job config.")

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

        r.report(
            gh_state,
            msg,
            url=url,
            check_names=PRCheckName.get_build_check(self.event.chroot),
        )
        return HandlerResults(success=False, details={"msg": msg})