Fix reject clauses in the absence of approvals

This change fixes a behavior that might be surprising to a
user: If a reject clause is configured for a pipeline, the reject clause
is always true even if no approval is set. If, however, an unrelated
approval is added to the change, the reject clause is evaluated as
expected.

The root cause was a check that assumed that the absence of approvals
will lead to a negative filter result. However, this is only true for
requirements.

Change-Id: I220bbed931ced7e807febefbf2b1b33af53a8da0
This commit is contained in:
Markus Hosch 2018-08-08 10:32:52 +02:00
parent cfa62e7782
commit 89359b161b
6 changed files with 64 additions and 2 deletions

View File

@ -0,0 +1,2 @@
- hosts: all
tasks: []

View File

@ -24,6 +24,25 @@
gerrit: gerrit:
Verified: -1 Verified: -1
- pipeline:
name: rejectline
manager: independent
reject:
gerrit:
approval:
- Verified:
- -1
- -2
trigger:
gerrit:
- event: comment-added
success:
gerrit:
Verified: 1
failure:
gerrit:
Verified: -1
- pipeline: - pipeline:
name: trigger name: trigger
manager: independent manager: independent
@ -58,6 +77,10 @@
name: project2-job name: project2-job
run: playbooks/project2-job.yaml run: playbooks/project2-job.yaml
- job:
name: project3-job
run: playbooks/project3-job.yaml
- project: - project:
name: org/project1 name: org/project1
pipeline: pipeline:
@ -69,3 +92,9 @@
trigger: trigger:
jobs: jobs:
- project2-job - project2-job
- project:
name: org/project3
rejectline:
jobs:
- project3-job

View File

@ -0,0 +1 @@
test

View File

@ -7,3 +7,4 @@
untrusted-projects: untrusted-projects:
- org/project1 - org/project1
- org/project2 - org/project2
- org/project3

View File

@ -411,3 +411,33 @@ class TestRequirementsReject(ZuulTestCase):
def test_trigger_require_reject(self): def test_trigger_require_reject(self):
"Test trigger requirement: rejections absent" "Test trigger requirement: rejections absent"
return self._test_require_reject('org/project2', 'project2-job') return self._test_require_reject('org/project2', 'project2-job')
def test_pipeline_requirement_reject_unrelated(self):
"Test if reject is obeyed if another unrelated approval is present"
# Having no approvals whatsoever shall not reject the change
A = self.fake_gerrit.addFakeChange('org/project3', 'master', 'A')
self.fake_gerrit.addEvent(A.getChangeCommentEvent(1))
self.waitUntilSettled()
self.assertEqual(len(self.history), 1)
# Setting another unrelated approval shall not change the behavior of
# the configured reject.
comment = A.addApproval('Approved', 1, username='reviewer_e')
self.fake_gerrit.addEvent(comment)
self.waitUntilSettled()
self.assertEqual(len(self.history), 2)
# Setting the approval 'Verified' to a rejected value shall not lead to
# a build.
comment = A.addApproval('Verified', -1, username='jenkins')
self.fake_gerrit.addEvent(comment)
self.waitUntilSettled()
self.assertEqual(len(self.history), 2)
# Setting the approval 'Verified' to an accepted value shall lead to
# a build.
comment = A.addApproval('Verified', 1, username='jenkins')
self.fake_gerrit.addEvent(comment)
self.waitUntilSettled()
self.assertEqual(len(self.history), 3)

View File

@ -113,8 +113,7 @@ class GerritApprovalFilter(object):
if not hasattr(change, 'number'): if not hasattr(change, 'number'):
# Not a change, no reviews # Not a change, no reviews
return False return False
if (self.required_approvals and not change.approvals if self.required_approvals and not change.approvals:
or self.reject_approvals and not change.approvals):
# A change with no approvals can not match # A change with no approvals can not match
return False return False