# Copyright 2017 Red Hat, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import copy import re import time from zuul.model import EventFilter, RefFilter from zuul.model import Change, TriggerEvent from zuul.driver.util import time_to_seconds EMPTY_GIT_REF = '0' * 40 # git sha of all zeros, used during creates/deletes class GerritChange(Change): def __init__(self, project): super(GerritChange, self).__init__(project) self.approvals = [] class GerritTriggerEvent(TriggerEvent): """Incoming event from an external system.""" def __init__(self): super(GerritTriggerEvent, self).__init__() self.approvals = [] def __repr__(self): ret = '= t): return False else: if not isinstance(v, list): v = [v] if (approval['description'] != k or int(approval['value']) not in v): return False return True def matchesApprovals(self, change): if self.required_approvals or self.reject_approvals: if not hasattr(change, 'number'): # Not a change, no reviews return False if (self.required_approvals and not change.approvals or self.reject_approvals and not change.approvals): # A change with no approvals can not match return False # TODO(jhesketh): If we wanted to optimise this slightly we could # analyse both the REQUIRE and REJECT filters by looping over the # approvals on the change and keeping track of what we have checked # rather than needing to loop on the change approvals twice return (self.matchesRequiredApprovals(change) and self.matchesNoRejectApprovals(change)) def matchesRequiredApprovals(self, change): # Check if any approvals match the requirements for rapproval in self.required_approvals: matches_rapproval = False for approval in change.approvals: if self._match_approval_required_approval(rapproval, approval): # We have a matching approval so this requirement is # fulfilled matches_rapproval = True break if not matches_rapproval: return False return True def matchesNoRejectApprovals(self, change): # Check to make sure no approvals match a reject criteria for rapproval in self.reject_approvals: for approval in change.approvals: if self._match_approval_required_approval(rapproval, approval): # A reject approval has been matched, so we reject # immediately return False # To get here no rejects can have been matched so we should be good to # queue return True class GerritEventFilter(EventFilter, GerritApprovalFilter): def __init__(self, trigger, types=[], branches=[], refs=[], event_approvals={}, comments=[], emails=[], usernames=[], required_approvals=[], reject_approvals=[], ignore_deletes=True): EventFilter.__init__(self, trigger) GerritApprovalFilter.__init__(self, required_approvals=required_approvals, reject_approvals=reject_approvals) self._types = types self._branches = branches self._refs = refs self._comments = comments self._emails = emails self._usernames = usernames self.types = [re.compile(x) for x in types] self.branches = [re.compile(x) for x in branches] self.refs = [re.compile(x) for x in refs] self.comments = [re.compile(x) for x in comments] self.emails = [re.compile(x) for x in emails] self.usernames = [re.compile(x) for x in usernames] self.event_approvals = event_approvals self.ignore_deletes = ignore_deletes def __repr__(self): ret = '