def run(self) -> HandlerResults:
        """
        Discover information about organization/user which wants to install packit on his repository
        Try to whitelist automatically if mapping from github username to FAS account can prove that
        user is a packager.
        :return: HandlerResults
        """
        InstallationModel.create(event=self.event)
        # try to add user to whitelist
        whitelist = Whitelist(
            fas_user=self.config.fas_user,
            fas_password=self.config.fas_password,
        )
        account_login = self.event.account_login
        account_type = self.event.account_type
        if not whitelist.add_account(self.event):
            # Create an issue in our repository, so we are notified when someone install the app
            self.project.create_issue(
                title=f"{account_type} {account_login} needs to be approved.",
                body=
                (f"Hi @{self.event.sender_login}, we need to approve you in "
                 "order to start using Packit-as-a-Service. Someone from our team will "
                 "get back to you shortly.\n\n"
                 "For more info, please check out the documentation: "
                 "http://packit.dev/packit-as-a-service/"),
            )
            msg = f"{account_type} {account_login} needs to be approved manually!"
        else:
            msg = f"{account_type} {account_login} whitelisted!"

        logger.info(msg)
        return HandlerResults(success=True, details={"msg": msg})
Example #2
0
    def process_comment_jobs(
        self, event: Union[PullRequestCommentEvent, IssueCommentEvent]
    ) -> HandlerResults:
        # packit_command can be `/packit propose-update`
        msg = f"PR comment '{event.comment[:35]}'"
        try:
            (packit_mark, *packit_command) = event.comment.split(maxsplit=3)
        except ValueError:
            return HandlerResults(success=False,
                                  details={"msg": f"{msg} is empty."})

        if REQUESTED_PULL_REQUEST_COMMENT != packit_mark:
            return HandlerResults(
                success=False,
                details={"msg": f"{msg} is not handled by packit-service."},
            )

        if not packit_command:
            return HandlerResults(
                success=False,
                details={
                    "msg": f"{msg} does not contain a packit-service command."
                },
            )

        # packit has command `copr-build`. But PullRequestCommentAction has enum `copr_build`.
        try:
            packit_action = CommentAction[packit_command[0].replace("-", "_")]
        except KeyError:
            return HandlerResults(
                success=False,
                details={
                    "msg":
                    f"{msg} does not contain a valid packit-service command."
                },
            )
        handler_kls: Type[
            CommentActionHandler] = COMMENT_ACTION_HANDLER_MAPPING.get(
                packit_action, None)
        if not handler_kls:
            return HandlerResults(
                success=False,
                details={"msg": f"{msg} is not a packit-service command."},
            )

        handler = handler_kls(self.config, event)

        try:
            # check whitelist approval for every job to be able to track down which jobs
            # failed because of missing whitelist approval
            whitelist = Whitelist()
            if not whitelist.check_and_report(event, event.get_project()):
                handlers_results = HandlerResults(
                    success=False,
                    details={"msg": "Account is not whitelisted!"})
                return handlers_results
            handlers_results = handler.run()
        finally:
            handler.clean()
        return handlers_results
Example #3
0
    def run(self) -> HandlerResults:
        """
        Discover information about organization/user which wants to install packit on his repository
        Try to whitelist automatically if mapping from github username to FAS account can prove that
        user is a packager.
        :return:
        """

        # try to add user to whitelist
        whitelist = Whitelist()
        if not whitelist.add_account(self.github_app):

            # Create an issue in our repository, so we are notified when someone install the app
            gh_proj = get_github_project(
                self.config, repo="notifications", namespace="packit-service"
            )
            gh_proj.create_issue(
                title=f"Account: {self.github_app.account_login} needs to be approved.",
                body=(
                    f"Hi @{self.github_app.account_login}, we need to approve you in "
                    "order to start using Packit-as-a-Service. Someone from our team will "
                    "get back to you shortly."
                ),
            )

            msg = f"Account: {self.github_app.account_login} needs to be approved manually!"
            logger.info(msg)
            return HandlerResults(success=True, details={"msg": msg})

        msg = (
            f"Account: {self.github_app.account_login} approved automatically,"
            f" because user: {self.github_app.sender_login}, who installed Packit-as-a-service,"
            f" is a packager in Fedora."
        )
        return HandlerResults(success=True, details={"msg": msg})
    def run(self) -> HandlerResults:
        """
        Discover information about organization/user which wants to install packit on his repository
        Try to whitelist automatically if mapping from github username to FAS account can prove that
        user is a packager.
        :return: HandlerResults
        """

        # try to add user to whitelist
        whitelist = Whitelist()
        Installation.create(
            installation_id=self.installation_event.installation_id,
            event=self.installation_event,
        )
        if not whitelist.add_account(self.installation_event):
            # Create an issue in our repository, so we are notified when someone install the app
            self.project.create_issue(
                title=
                f"Account: {self.installation_event.account_login} needs to be approved.",
                body=
                (f"Hi @{self.installation_event.account_login}, we need to approve you in "
                 "order to start using Packit-as-a-Service. Someone from our team will "
                 "get back to you shortly."),
            )

            msg = f"Account: {self.installation_event.account_login} needs to be approved manually!"
            logger.info(msg)
            return HandlerResults(success=True, details={"msg": msg})
        return HandlerResults(
            success=True,
            details={
                "msg":
                f"Account {self.installation_event.account_login} whitelisted!"
            },
        )
Example #5
0
def waiting():
    """
    Show accounts waiting for approval.
    """
    whitelist = Whitelist()

    print(f"Accounts waiting for approval:")
    for account in whitelist.accounts_waiting():
        print(f"{account}")
Example #6
0
    def process_comment_jobs(
        self, event: Union[PullRequestCommentEvent, IssueCommentEvent]
    ) -> HandlerResults:
        # packit_command can be `/packit propose-update`
        msg = f"comment '{event.comment[:35]}'"
        try:
            (packit_mark, *packit_command) = event.comment.split(maxsplit=3)
        except ValueError:
            return HandlerResults(success=True,
                                  details={"msg": f"{msg} is empty."})

        if packit_mark != REQUESTED_PULL_REQUEST_COMMENT:
            return HandlerResults(
                success=True,
                details={"msg": f"{msg} is not handled by packit-service."},
            )

        if not packit_command:
            return HandlerResults(
                success=True,
                details={
                    "msg": f"{msg} does not contain a packit-service command."
                },
            )

        # packit has command `copr-build`. But PullRequestCommentAction has enum `copr_build`.
        try:
            packit_action = CommentAction[packit_command[0].replace("-", "_")]
        except KeyError:
            return HandlerResults(
                success=True,
                details={
                    "msg":
                    f"{msg} does not contain a valid packit-service command."
                },
            )
        handler_kls: Type[
            CommentActionHandler] = COMMENT_ACTION_HANDLER_MAPPING.get(
                packit_action, None)
        if not handler_kls:
            return HandlerResults(
                success=True,
                details={"msg": f"{msg} is not a packit-service command."})

        # check whitelist approval for every job to be able to track down which jobs
        # failed because of missing whitelist approval
        whitelist = Whitelist()
        github_login = getattr(event, "github_login", None)
        if github_login and github_login in self.config.admins:
            logger.info(f"{github_login} is admin, you shall pass")
        elif not whitelist.check_and_report(
                event, event.get_project(), config=self.config):
            return HandlerResults(
                success=True, details={"msg": "Account is not whitelisted!"})

        return handler_kls(self.config, event).run_n_clean()
Example #7
0
    def process_jobs(self, event: Event) -> Dict[str, HandlerResults]:
        """
        Run a job handler (if trigger matches) for every job defined in config.
        """

        handlers_results = {}

        if not event.package_config:
            # this happens when service receives events for repos which
            # don't have packit config, this is not an error
            # success=True - it's not an error that people don't have packit.yaml in their repo
            handlers_results[event.trigger.value] = HandlerResults(
                success=True, details={"msg": "No packit config in repo"}
            )
            return handlers_results

        handler_classes = get_handlers_for_event(event, event.package_config)

        if not handler_classes:
            logger.warning(f"There is no handler for {event.trigger} event.")
            return handlers_results

        for handler_kls in handler_classes:
            job_configs = get_config_for_handler_kls(
                handler_kls=handler_kls,
                event=event,
                package_config=event.package_config,
            )
            # check whitelist approval for every job to be able to track down which jobs
            # failed because of missing whitelist approval
            whitelist = Whitelist()
            user_login = getattr(event, "user_login", None)
            if user_login and user_login in self.config.admins:
                logger.info(f"{user_login} is admin, you shall pass.")
            elif not whitelist.check_and_report(
                event, event.project, config=self.config
            ):
                for job_config in job_configs:
                    handlers_results[job_config.type.value] = HandlerResults(
                        success=False, details={"msg": "Account is not whitelisted!"}
                    )
                return handlers_results

            # we want to run handlers for all possible jobs, not just the first one
            for job_config in job_configs:
                logger.debug(f"Running handler: {str(handler_kls)} for {job_config}")
                handler = handler_kls(
                    config=self.config, job_config=job_config, event=event
                )
                if handler.pre_check():
                    current_time = datetime.datetime.now().strftime(DATETIME_FORMAT)
                    result_key = f"{job_config.type.value}-{current_time}"
                    handlers_results[result_key] = handler.run_n_clean()

        return handlers_results
Example #8
0
    def process_jobs(
        self,
        trigger: JobTriggerType,
        package_config: PackageConfig,
        event: dict,
        project: GitProject,
    ) -> Dict[str, HandlerResults]:
        """
        Run a job handler (if trigger matches) for every job defined in config.
        """
        handlers_results = {}

        for job in package_config.jobs:
            if trigger == job.trigger:
                handler_kls = JOB_NAME_HANDLER_MAPPING.get(job.job, None)
                if not handler_kls:
                    logger.warning(f"There is no handler for job {job}")
                    continue
                handler = handler_kls(
                    self.config,
                    package_config,
                    event,
                    project,
                    self.pagure_service,
                    project.service,
                    job,
                    trigger,
                )
                try:
                    # check whitelist approval for every job to be able to track down which jobs
                    # failed because of missing whitelist approval
                    whitelist = Whitelist()
                    if not whitelist.is_approved(project.namespace):
                        logger.error(
                            f"User {project.namespace} is not approved on whitelist!"
                        )
                        # TODO also check blacklist,
                        # but for that we need to know who triggered the action

                        commit_sha = nested_get(event, "pull_request", "head", "sha")
                        r = BuildStatusReporter(project, commit_sha)
                        msg = "Account is not whitelisted!"
                        r.report("failure", msg, url=FAQ_URL)

                        handlers_results[job.job.value] = HandlerResults(
                            success=False, details={"msg": msg}
                        )
                        return handlers_results

                    handlers_results[job.job.value] = handler.run()
                    # don't break here, other handlers may react to the same event
                finally:
                    handler.clean()
        return handlers_results
Example #9
0
def remove(account_name):
    """
    Remove account from whitelist
    :param account_name: github namespace
    :return:
    """
    whitelist = Whitelist()

    if whitelist.remove_account(account_name):
        print(f"Account: {account_name} removed from whitelist!")
    else:
        print(f"Account: {account_name} does not exists!")
Example #10
0
    def process_jobs(self, event: Event) -> Dict[str, TaskResults]:
        """
        Create a Celery task for a job handler (if trigger matches) for every job defined in config.
        """

        processing_results = {}

        if not event.package_config:
            # this happens when service receives events for repos which don't have packit config
            # success=True - it's not an error that people don't have packit.yaml in their repo
            processing_results[event.trigger.value] = TaskResults(
                success=True, details={"msg": "No packit config in repo"})
            return processing_results

        handler_classes = get_handlers_for_event(event, event.package_config)

        if not handler_classes:
            logger.warning(f"There is no handler for {event.trigger} event.")
            return processing_results

        job_configs = []
        for handler_kls in handler_classes:
            job_configs = get_config_for_handler_kls(
                handler_kls=handler_kls,
                event=event,
                package_config=event.package_config,
            )
            # check whitelist approval for every job to be able to track down which jobs
            # failed because of missing whitelist approval
            whitelist = Whitelist()
            user_login = getattr(event, "user_login", None)
            if user_login and user_login in self.service_config.admins:
                logger.info(f"{user_login} is admin, you shall pass.")
            elif not whitelist.check_and_report(
                    event,
                    event.project,
                    service_config=self.service_config,
                    job_configs=job_configs,
            ):
                for job_config in job_configs:
                    processing_results[job_config.type.value] = TaskResults(
                        success=False,
                        details={"msg": "Account is not whitelisted!"})
                return processing_results

            # we want to run handlers for all possible jobs, not just the first one
            signatures = [
                handler_kls.get_signature(event=event, job=job_config)
                for job_config in job_configs
            ]
            # https://docs.celeryproject.org/en/stable/userguide/canvas.html#groups
            group(signatures).apply_async()
        return get_processing_results(event=event, jobs=job_configs)
Example #11
0
def approve(account_name):
    """
    Approve user who is waiting on whitelist.
    :param account_name: github namespace
    :return:
    """
    whitelist = Whitelist()
    if whitelist.approve_account(account_name):
        print(f"Account: {account_name} approved successfully")
    else:
        print(
            f"Account: {account_name} does not exists or it is already approved"
        )
Example #12
0
    def process_jobs(self, event: Event) -> Dict[str, HandlerResults]:
        """
        Run a job handler (if trigger matches) for every job defined in config.
        """

        handlers_results = {}
        package_config = event.get_package_config()

        if not package_config:
            # this happens when service receives events for repos which
            # don't have packit config, this is not an error
            # success=True - it's not an error that people don't have packit.yaml in their repo
            handlers_results[event.trigger.value] = HandlerResults(
                success=True, details={"msg": "No packit config in repo"}
            )
            return handlers_results

        handler_classes = get_handlers_for_event(event, package_config)

        if not handler_classes:
            logger.warning(f"There is no handler for {event.trigger} event.")
            return handlers_results

        for handler_kls in handler_classes:
            job = get_config_for_handler_kls(
                handler_kls=handler_kls, event=event, package_config=package_config
            )
            # check whitelist approval for every job to be able to track down which jobs
            # failed because of missing whitelist approval
            whitelist = Whitelist()
            github_login = getattr(event, "github_login", None)
            if github_login and github_login in self.config.admins:
                logger.info(f"{github_login} is admin, you shall pass")
            elif not whitelist.check_and_report(
                event, event.get_project(), config=self.config
            ):
                handlers_results[job.type.value] = HandlerResults(
                    success=False, details={"msg": "Account is not whitelisted!"}
                )
                return handlers_results

            logger.debug(f"Running handler: {str(handler_kls)}")
            handler = handler_kls(config=self.config, job_config=job, event=event)
            if handler.pre_check():
                handlers_results[job.type.value] = handler.run_n_clean()
            # don't break here, other handlers may react to the same event

        return handlers_results
Example #13
0
    def process_comment_jobs(
        self, event: Union[PullRequestCommentEvent, IssueCommentEvent]
    ) -> HandlerResults:

        msg = f"comment '{event.comment}'"
        packit_command, pr_comment_error_msg = self.find_packit_command(
            str(event.comment))

        if pr_comment_error_msg:
            return HandlerResults(
                success=True,
                details={"msg": pr_comment_error_msg},
            )

        # packit has command `copr-build`. But PullRequestCommentAction has enum `copr_build`.
        try:
            packit_action = CommentAction[packit_command[0].replace("-", "_")]
        except KeyError:
            return HandlerResults(
                success=True,
                details={
                    "msg":
                    f"{msg} does not contain a valid packit-service command."
                },
            )
        handler_kls: Type[
            CommentActionHandler] = MAP_COMMENT_ACTION_TO_HANDLER.get(
                packit_action, None)
        if not handler_kls:
            return HandlerResults(
                success=True,
                details={"msg": f"{msg} is not a packit-service command."})

        # check whitelist approval for every job to be able to track down which jobs
        # failed because of missing whitelist approval
        whitelist = Whitelist()
        github_login = getattr(event, "github_login", None)
        if github_login and github_login in self.config.admins:
            logger.info(f"{github_login} is admin, you shall pass")
        elif not whitelist.check_and_report(
                event, event.get_project(), config=self.config):
            return HandlerResults(
                success=True, details={"msg": "Account is not whitelisted!"})

        handler_instance: Handler = handler_kls(config=self.config,
                                                event=event)
        return handler_instance.run_n_clean()
Example #14
0
def approve(account_name):
    """
    Approve user who is waiting on whitelist.

    :param account_name: github namespace
    :return:
    """
    Whitelist().approve_account(account_name)
Example #15
0
def remove(account_name):
    """
    Remove account from whitelist

    :param account_name: github namespace
    :return:
    """
    Whitelist().remove_account(account_name)
Example #16
0
    def process_jobs(self, event: Event) -> Dict[str, HandlerResults]:
        """
        Run a job handler (if trigger matches) for every job defined in config.
        """
        handlers_results = {}
        package_config = event.get_package_config()

        if not package_config:
            # this happens when service receives events for repos which
            # don't have packit config, this is not an error
            msg = "Failed to obtain package config!"
            logger.info(msg)
            handlers_results[event.trigger.value] = HandlerResults(
                success=False, details={"msg": msg})
            return handlers_results

        for job in package_config.jobs:
            if event.trigger == job.trigger:
                handler_kls: Type[JobHandler] = JOB_NAME_HANDLER_MAPPING.get(
                    job.job, None)
                if not handler_kls:
                    logger.warning(f"There is no handler for job {job}")
                    continue

                handler = handler_kls(self.config, job, event)
                try:
                    # check whitelist approval for every job to be able to track down which jobs
                    # failed because of missing whitelist approval
                    whitelist = Whitelist()
                    if not whitelist.check_and_report(event,
                                                      event.get_project()):
                        handlers_results[job.job.value] = HandlerResults(
                            success=False,
                            details={"msg": "Account is not whitelisted!"},
                        )
                        return handlers_results

                    logger.debug(f"Running handler: {str(handler_kls)}")
                    handlers_results[job.job.value] = handler.run()
                    # don't break here, other handlers may react to the same event
                finally:
                    handler.clean()
        return handlers_results
Example #17
0
def test_check_and_report(event, should_pass):
    w = Whitelist()
    w.db = {
        "anakin": {
            "status": "approved_manually"
        },
        "yoda": {
            "status": "approved_manually"
        },
        "naboo": {
            "status": "approved_manually"
        },
    }

    flexmock(
        GithubProject,
        pr_comment=lambda *args, **kwargs: None,
        set_commit_status=lambda *args, **kwargs: None,
        issue_comment=lambda *args, **kwargs: None,
    )
    git_project = GithubProject("", GithubService(), "")
    assert w.check_and_report(event, git_project) == should_pass
Example #18
0
def test_check_and_report(whitelist: Whitelist,
                          events: List[Tuple[AbstractGithubEvent, bool]]):
    """
    :param whitelist: fixture
    :param events: fixture: [(Event, should-be-approved)]
    """
    flexmock(
        GithubProject,
        pr_comment=lambda *args, **kwargs: None,
        set_commit_status=lambda *args, **kwargs: None,
        issue_comment=lambda *args, **kwargs: None,
    )
    flexmock(PullRequestEvent).should_receive("get_package_config").and_return(
        flexmock(jobs=[
            JobConfig(
                job=JobType.tests,
                trigger=JobTriggerType.pull_request,
                metadata={"targets": ["fedora-rawhide"]},
            )
        ], ))

    git_project = GithubProject("", GithubService(), "")
    for event, is_valid in events:
        if isinstance(event, PullRequestEvent) and not is_valid:
            # Report the status
            flexmock(CoprHelper).should_receive("get_copr_client").and_return(
                Client(
                    config={
                        "copr_url": "https://copr.fedorainfracloud.org",
                        "username": "******",
                    }))
            flexmock(LocalProject).should_receive(
                "refresh_the_arguments").and_return(None)
            flexmock(LocalProject).should_receive("checkout_pr").and_return(
                None)
            flexmock(Model).should_receive("save").and_return(None)
            flexmock(StatusReporter).should_receive("report").with_args(
                description="Account is not whitelisted!",
                state="error",
                url=FAQ_URL,
                check_names=[EXPECTED_TESTING_FARM_CHECK_NAME],
            ).once()
        assert (whitelist.check_and_report(
            event,
            git_project,
            config=flexmock(deployment=Deployment.stg,
                            command_handler_work_dir=""),
        ) is is_valid)
def test_check_and_report(whitelist: Whitelist,
                          events: List[Tuple[AbstractGithubEvent, bool]]):
    """
    :param whitelist: fixture
    :param events: fixture: [(Event, should-be-approved)]
    """
    flexmock(
        GithubProject,
        pr_comment=lambda *args, **kwargs: None,
        set_commit_status=lambda *args, **kwargs: None,
        issue_comment=lambda *args, **kwargs: None,
    )
    flexmock(PullRequestEvent).should_receive("get_package_config").and_return(
        flexmock(jobs=[
            JobConfig(job=JobType.tests,
                      trigger=JobTriggerType.pull_request,
                      metadata={})
        ]))
    git_project = GithubProject("", GithubService(), "")
    for event in events:
        assert (whitelist.check_and_report(
            event[0], git_project, config=flexmock(deployment=Deployment.stg))
                is event[1])
Example #20
0
    def process_comment_jobs(
        self,
        event: Union[
            PullRequestCommentGithubEvent,
            PullRequestCommentPagureEvent,
            IssueCommentEvent,
        ],
    ) -> Dict[str, HandlerResults]:

        msg = f"comment '{event.comment}'"
        packit_command, pr_comment_error_msg = self.find_packit_command(
            str(event.comment)
        )

        if pr_comment_error_msg:
            return {
                event.trigger.value: HandlerResults(
                    success=True, details={"msg": pr_comment_error_msg},
                )
            }

        # packit has command `copr-build`. But PullRequestCommentAction has enum `copr_build`.
        try:
            packit_action = CommentAction[packit_command[0].replace("-", "_")]
        except KeyError:
            return {
                event.trigger.value: HandlerResults(
                    success=True,
                    details={
                        "msg": f"{msg} does not contain a valid packit-service command."
                    },
                )
            }

        if packit_action == CommentAction.test and isinstance(
            event.db_trigger, PullRequestModel
        ):
            if not event.db_trigger.get_copr_builds():
                packit_action = CommentAction.build

        handler_kls: Type[CommentActionHandler] = MAP_COMMENT_ACTION_TO_HANDLER.get(
            packit_action, None
        )
        if not handler_kls:
            return {
                event.trigger.value: HandlerResults(
                    success=True,
                    details={"msg": f"{msg} is not a packit-service command."},
                )
            }

        # check whitelist approval for every job to be able to track down which jobs
        # failed because of missing whitelist approval
        whitelist = Whitelist()
        user_login = getattr(event, "user_login", None)
        if user_login and user_login in self.config.admins:
            logger.info(f"{user_login} is admin, you shall pass.")
        elif not whitelist.check_and_report(event, event.project, config=self.config):
            return {
                event.trigger.value: HandlerResults(
                    success=True, details={"msg": f"Account is not whitelisted!"}
                )
            }

        # VERY UGLY
        # TODO: REFACTOR !!!
        if handler_kls == GitHubPullRequestCommentCoprBuildHandler and isinstance(
            event, PullRequestCommentPagureEvent
        ):
            handler_kls = PagurePullRequestCommentCoprBuildHandler

        handlers_results: Dict[str, HandlerResults] = {}
        jobs = get_config_for_handler_kls(
            handler_kls=handler_kls, event=event, package_config=event.package_config,
        )
        for job in jobs:
            handler_instance: Handler = handler_kls(
                config=self.config, event=event, job=job
            )
            result_key = (
                f"{job.type.value}-{datetime.datetime.now().strftime(DATETIME_FORMAT)}"
            )
            handlers_results[result_key] = handler_instance.run_n_clean()
        return handlers_results
Example #21
0
def whitelist(db):
    w = Whitelist()
    w.db = db
    return w
Example #22
0
    def process_jobs(self, event: Event) -> List[TaskResults]:
        """
        Create a Celery task for a job handler (if trigger matches) for every job defined in config.
        """

        if isinstance(
                event,
            (PushGitHubEvent, PushGitlabEvent,
             PushPagureEvent)) and event.commit_sha.startswith("0000000"):
            return [
                TaskResults.create_from(
                    success=True,
                    msg="Triggered by deleting a branch",
                    job_config=None,
                    event=event,
                )
            ]

        if not event.package_config:
            # this happens when service receives events for repos which don't have packit config
            # success=True - it's not an error that people don't have packit.yaml in their repo
            return [
                TaskResults.create_from(
                    success=True,
                    msg="No packit config found in the repository.",
                    job_config=None,
                    event=event,
                )
            ]

        if isinstance(
                event,
            (
                PullRequestCommentGithubEvent,
                PullRequestCommentPagureEvent,
                IssueCommentEvent,
                MergeRequestCommentGitlabEvent,
                IssueCommentGitlabEvent,
            ),
        ):
            if not event.project.can_merge_pr(event.user_login):
                logger.debug(
                    f"User {event.user_login} not allowed to trigger packit via comments."
                )
                return [
                    TaskResults.create_from(
                        success=True,
                        msg=
                        f"User {event.user_login} not allowed to trigger packit via comments.",
                        job_config=None,
                        event=event,
                    )
                ]

        handler_classes = get_handlers_for_event(event, event.package_config)

        if not handler_classes:
            logger.debug(
                f"There is no handler for {event} event suitable for the configuration."
            )
            return []

        job_configs = []
        for handler_kls in handler_classes:
            # TODO: merge to to get_handlers_for_event so
            # so we don't need to go through the similar process twice.
            job_configs = get_config_for_handler_kls(
                handler_kls=handler_kls,
                event=event,
                package_config=event.package_config,
            )
            # check whitelist approval for every job to be able to track down which jobs
            # failed because of missing whitelist approval
            whitelist = Whitelist()
            user_login = getattr(event, "user_login", None)
            if user_login and user_login in self.service_config.admins:
                logger.info(f"{user_login} is admin, you shall pass.")
            elif not whitelist.check_and_report(
                    event,
                    event.project,
                    service_config=self.service_config,
                    job_configs=job_configs,
            ):
                processing_results = []
                for job_config in job_configs:
                    processing_results.append(
                        TaskResults.create_from(
                            success=False,
                            msg="Account is not whitelisted!",
                            job_config=job_config,
                            event=event,
                        ))
                return processing_results

            # we want to run handlers for all possible jobs, not just the first one
            signatures = [
                handler_kls.get_signature(event=event, job=job_config)
                for job_config in job_configs
            ]
            # https://docs.celeryproject.org/en/stable/userguide/canvas.html#groups
            group(signatures).apply_async()

        processing_results = []
        for job_config in job_configs:
            processing_results.append(
                TaskResults.create_from(
                    success=True,
                    msg="Job created.",
                    job_config=job_config,
                    event=event,
                ))
        return processing_results
Example #23
0
def test_check_and_report(whitelist: Whitelist,
                          events: List[Tuple[AbstractGithubEvent, bool]]):
    """
    :param whitelist: fixture
    :param events: fixture: [(Event, should-be-approved)]
    """
    flexmock(
        GithubProject,
        pr_comment=lambda *args, **kwargs: None,
        set_commit_status=lambda *args, **kwargs: None,
        issue_comment=lambda *args, **kwargs: None,
    )
    flexmock(PullRequestGithubEvent).should_receive(
        "get_package_config").and_return(
            flexmock(jobs=[
                JobConfig(
                    type=JobType.tests,
                    trigger=JobConfigTriggerType.pull_request,
                    metadata=JobMetadataConfig(targets=["fedora-rawhide"]),
                )
            ], ))

    git_project = GithubProject("", GithubService(), "")
    for event, is_valid in events:
        if isinstance(event, PullRequestGithubEvent) and not is_valid:
            # Report the status
            flexmock(CoprHelper).should_receive("get_copr_client").and_return(
                Client(
                    config={
                        "copr_url": "https://copr.fedorainfracloud.org",
                        "username": "******",
                    }))
            flexmock(LocalProject).should_receive(
                "refresh_the_arguments").and_return(None)
            flexmock(LocalProject).should_receive("checkout_pr").and_return(
                None)
            flexmock(StatusReporter).should_receive("report").with_args(
                description="Account is not whitelisted!",
                state=CommitStatus.error,
                url=FAQ_URL,
                check_names=[EXPECTED_TESTING_FARM_CHECK_NAME],
            ).once()

        # get_account returns the whitelist object if it exists
        # returns nothing if it isn't whitelisted
        # then inside the whitelist.py file, a function checks if the status is
        # one of the approved statuses

        # this exact code is used twice above but mypy has an issue with this one only
        whitelist_mock = flexmock(DBWhitelist).should_receive("get_account")
        if not TYPE_CHECKING:
            if is_valid:
                whitelist_mock.and_return(
                    DBWhitelist(status="approved_manually"))
            else:
                whitelist_mock.and_return(None)

        assert (whitelist.check_and_report(
            event,
            git_project,
            config=flexmock(deployment=Deployment.stg,
                            command_handler_work_dir=""),
        ) is is_valid)
Example #24
0
def whitelist():
    w = Whitelist()
    return w
Example #25
0
    def process_comment_jobs(
        self,
        event: Union[PullRequestCommentGithubEvent,
                     PullRequestCommentPagureEvent, IssueCommentEvent,
                     MergeRequestCommentGitlabEvent,
                     IssueCommentGitlabEvent, ],
    ) -> Dict[str, TaskResults]:

        msg = f"comment '{event.comment}'"
        packit_command, pr_comment_error_msg = self.find_packit_command(
            str(event.comment))

        if pr_comment_error_msg:
            return {
                event.trigger.value:
                TaskResults(
                    success=True,
                    details={"msg": pr_comment_error_msg},
                )
            }

        # packit has command `copr-build`. But PullRequestCommentAction has enum `copr_build`.
        try:
            packit_action = CommentAction[packit_command[0].replace("-", "_")]
        except KeyError:
            return {
                event.trigger.value:
                TaskResults(
                    success=True,
                    details={
                        "msg":
                        f"{msg} does not contain a valid packit-service command."
                    },
                )
            }

        if (packit_action == CommentAction.test
                and isinstance(event.db_trigger, PullRequestModel)
                and not event.db_trigger.get_copr_builds()):
            packit_action = CommentAction.build

        handler_kls: Type[
            CommentActionHandler] = MAP_COMMENT_ACTION_TO_HANDLER.get(
                packit_action, None)
        if not handler_kls:
            return {
                event.trigger.value:
                TaskResults(
                    success=True,
                    details={"msg": f"{msg} is not a packit-service command."},
                )
            }

        # check whitelist approval for every job to be able to track down which jobs
        # failed because of missing whitelist approval
        whitelist = Whitelist()
        user_login = getattr(event, "user_login", None)
        jobs = get_config_for_handler_kls(
            handler_kls=handler_kls,
            event=event,
            package_config=event.package_config,
        )
        if user_login and user_login in self.service_config.admins:
            logger.info(f"{user_login} is admin, you shall pass.")
        elif not whitelist.check_and_report(event,
                                            event.project,
                                            service_config=self.service_config,
                                            job_configs=jobs):
            return {
                event.trigger.value:
                TaskResults(success=True,
                            details={"msg": "Account is not whitelisted!"})
            }

        # VERY UGLY
        # TODO: REFACTOR !!!
        if handler_kls == GitHubPullRequestCommentCoprBuildHandler and isinstance(
                event, PullRequestCommentPagureEvent):
            handler_kls = PagurePullRequestCommentCoprBuildHandler

        signatures = [
            handler_kls.get_signature(event=event, job=job) for job in jobs
        ]
        # https://docs.celeryproject.org/en/stable/userguide/canvas.html#groups
        group(signatures).apply_async()
        return get_processing_results(event=event, jobs=jobs)