예제 #1
0
 def matchesStatuses(self, change):
     if self.required_statuses or self.reject_statuses:
         if not hasattr(change, 'number'):
             # not a PR, no status
             return FalseWithReason("Can't match statuses without PR")
         if self.required_statuses and not change.status:
             return FalseWithReason(
                 "Required statuses %s does not match %s" % (
                     self.required_statuses, change.status))
     required_statuses_results = self.matchesRequiredStatuses(change)
     if not required_statuses_results:
         return required_statuses_results
     return self.matchesNoRejectStatuses(change)
예제 #2
0
    def matchesReviews(self, change):
        if self.required_reviews or self.reject_reviews:
            if not hasattr(change, 'number'):
                # not a PR, no reviews
                return FalseWithReason("Change is not a PR")
            if self.required_reviews and not change.reviews:
                # No reviews means no matching of required bits
                # having reject reviews but no reviews on the change is okay
                return FalseWithReason("Reviews %s does not match %s" % (
                    self.required_reviews, change.reviews))

        return (self.matchesRequiredReviews(change) and
                self.matchesNoRejectReviews(change))
예제 #3
0
 def matchesNoRejectReviews(self, change):
     for rreview in self.reject_reviews:
         for review in change.reviews:
             if self._match_review_required_review(rreview, review):
                 # A review matched, we can reject right away
                 return FalseWithReason("Reject reviews %s matches %s" % (
                     self.reject_reviews, change.reviews))
     return True
예제 #4
0
 def matchesNoRejectStatuses(self, change):
     # statuses are ANDed
     # If any of the rejected statusses are present, we return false
     for rstatus in self.reject_statuses:
         for status in change.status:
             if re2.fullmatch(rstatus, status):
                 return FalseWithReason("NoRejectStatuses %s matches %s" % (
                     self.reject_statuses, change.status))
     return True
예제 #5
0
    def matches(self, change):
        statuses_result = self.matchesStatuses(change)
        if not statuses_result:
            return statuses_result

        if self.open is not None:
            # if a "change" has no number, it's not a change, but a push
            # and cannot possibly pass this test.
            if hasattr(change, 'number'):
                if self.open != change.open:
                    return FalseWithReason("Change is not a PR")
            else:
                return FalseWithReason("Change is not a PR")

        if self.merged is not None:
            # if a "change" has no number, it's not a change, but a push
            # and cannot possibly pass this test.
            if hasattr(change, 'number'):
                if self.merged != change.is_merged:
                    return FalseWithReason("Change is not a PR")
            else:
                return FalseWithReason("Change is not a PR")

        if self.current_patchset is not None:
            # if a "change" has no number, it's not a change, but a push
            # and cannot possibly pass this test.
            if hasattr(change, 'number'):
                if self.current_patchset != change.is_current_patchset:
                    return FalseWithReason("Change is not current")
            else:
                return FalseWithReason("Change is not a PR")

        # required reviews are ANDed (reject reviews are ORed)
        reviews_result = self.matchesReviews(change)
        if not reviews_result:
            return reviews_result

        # required labels are ANDed
        for label in self.labels:
            if label not in change.labels:
                return FalseWithReason("Labels %s does not match %s" % (
                    self.labels, change.labels))

        # rejected reviews are OR'd
        for label in self.reject_labels:
            if label in change.labels:
                return FalseWithReason("RejectLabels %s matches %s" % (
                    self.reject_labels, change.labels))

        return True
예제 #6
0
 def matchesRequiredStatuses(self, change):
     # statuses are ORed
     # A PR head can have multiple statuses on it. If the change
     # statuses and the filter statuses are a null intersection, there
     # are no matches and we return false
     if self.required_statuses:
         for required_status in self.required_statuses:
             for status in change.status:
                 if re2.fullmatch(required_status, status):
                     return True
         return FalseWithReason("RequiredStatuses %s does not match %s" % (
             self.required_statuses, change.status))
     return True
예제 #7
0
 def matchesRequiredReviews(self, change):
     for rreview in self.required_reviews:
         matches_review = False
         for review in change.reviews:
             if self._match_review_required_review(rreview, review):
                 # Consider matched if any review matches
                 matches_review = True
                 break
         if not matches_review:
             return FalseWithReason(
                 "Required reviews %s does not match %s" % (
                     self.required_reviews, change.reviews))
     return True
예제 #8
0
    def matches(self, event, change):
        # event types are ORed
        matches_type = False
        for etype in self.types:
            if etype.match(event.type):
                matches_type = True
        if self.types and not matches_type:
            return FalseWithReason("Types %s doesn't match %s" % (
                self.types, event.type))

        # branches are ORed
        matches_branch = False
        for branch in self.branches:
            if branch.match(event.branch):
                matches_branch = True
        if self.branches and not matches_branch:
            return FalseWithReason("Branches %s doesn't match %s" % (
                self.branches, event.branch))

        # refs are ORed
        matches_ref = False
        if event.ref is not None:
            for ref in self.refs:
                if ref.match(event.ref):
                    matches_ref = True
        if self.refs and not matches_ref:
            return FalseWithReason(
                "Refs %s doesn't match %s" % (self.refs, event.ref))
        if self.ignore_deletes and event.newrev == EMPTY_GIT_REF:
            # If the updated ref has an empty git sha (all 0s),
            # then the ref is being deleted
            return FalseWithReason("Ref deletion are ignored")

        # comments are ORed
        matches_comment_re = False
        for comment_re in self.comments:
            if (event.comment is not None and
                comment_re.search(event.comment)):
                matches_comment_re = True
        if self.comments and not matches_comment_re:
            return FalseWithReason("Comments %s doesn't match %s" % (
                self.comments, event.comment))

        # actions are ORed
        matches_action = False
        for action in self.actions:
            if (event.action == action):
                matches_action = True
        if self.actions and not matches_action:
            return FalseWithReason("Actions %s doesn't match %s" % (
                self.actions, event.action))

        # check_runs are ORed
        if self.check_runs:
            check_run_found = False
            for check_run in self.check_runs:
                if re2.fullmatch(check_run, event.check_run):
                    check_run_found = True
                    break
            if not check_run_found:
                return FalseWithReason("Check_runs %s doesn't match %s" % (
                    self.check_runs, event.check_run))

        # labels are ORed
        if self.labels and event.label not in self.labels:
            return FalseWithReason("Labels %s doesn't match %s" % (
                self.labels, event.label))

        # unlabels are ORed
        if self.unlabels and event.unlabel not in self.unlabels:
            return FalseWithReason("Unlabels %s doesn't match %s" % (
                self.unlabels, event.unlabel))

        # states are ORed
        if self.states and event.state not in self.states:
            return FalseWithReason("States %s doesn't match %s" % (
                self.states, event.state))

        # statuses are ORed
        if self.statuses:
            status_found = False
            for status in self.statuses:
                if re2.fullmatch(status, event.status):
                    status_found = True
                    break
            if not status_found:
                return FalseWithReason("Statuses %s doesn't match %s" % (
                    self.statuses, event.status))

        return self.matchesStatuses(change)