Add option to ignore ref-updated events emitted by branch deletions

When a branch is deleted, gerrit emits a ref-updated event with a newrev
value of all zeros. This adds a boolean field to optionally not trigger
on these ref-updated events.

Change-Id: Iea75d05ddcb49b0bf748b72b9d2d5472d077f0c6
This commit is contained in:
K Jonathan Harker 2015-04-29 13:33:16 -07:00 committed by Monty Taylor
parent 135a9358c1
commit f95e7232ac
8 changed files with 87 additions and 2 deletions

View File

@ -422,6 +422,12 @@ explanation of each of the parameters::
provides. This field is treated as a regular expression, and
multiple refs may be listed.
*ignore-deletes*
When a branch is deleted, a ref-updated event is emitted with a newrev
of all zeros specified. The ``ignore-deletes`` field is a boolean value
that describes whether or not these newrevs trigger ref-updated events.
The default is True, which will not trigger ref-updated events.
*approval*
This is only used for ``comment-added`` events. It only matches if
the event has a matching approval associated with it. Example:

View File

@ -30,6 +30,7 @@ pipelines:
gerrit:
- event: ref-updated
ref: ^(?!refs/).*$
ignore-deletes: False
- name: gate
manager: DependentPipelineManager

View File

@ -0,0 +1,16 @@
includes:
- python-file: custom_functions.py
pipelines:
- name: post
manager: IndependentPipelineManager
trigger:
gerrit:
- event: ref-updated
ref: ^(?!refs/).*$
ignore-deletes: False
projects:
- name: org/project
post:
- project-post

View File

@ -20,6 +20,7 @@ pipelines:
gerrit:
- event: ref-updated
ref: ^(?!refs/).*$
ignore-deletes: True
- name: gate
manager: DependentPipelineManager

View File

@ -891,6 +891,54 @@ class TestScheduler(ZuulTestCase):
self.assertEqual(len(self.history), 1)
self.assertIn('project-post', job_names)
def test_post_ignore_deletes(self):
"Test that deleting refs does not trigger post jobs"
e = {
"type": "ref-updated",
"submitter": {
"name": "User Name",
},
"refUpdate": {
"oldRev": "90f173846e3af9154517b88543ffbd1691f31366",
"newRev": "0000000000000000000000000000000000000000",
"refName": "master",
"project": "org/project",
}
}
self.fake_gerrit.addEvent(e)
self.waitUntilSettled()
job_names = [x.name for x in self.history]
self.assertEqual(len(self.history), 0)
self.assertNotIn('project-post', job_names)
def test_post_ignore_deletes_negative(self):
"Test that deleting refs does trigger post jobs"
self.config.set('zuul', 'layout_config',
'tests/fixtures/layout-dont-ignore-deletes.yaml')
self.sched.reconfigure(self.config)
e = {
"type": "ref-updated",
"submitter": {
"name": "User Name",
},
"refUpdate": {
"oldRev": "90f173846e3af9154517b88543ffbd1691f31366",
"newRev": "0000000000000000000000000000000000000000",
"refName": "master",
"project": "org/project",
}
}
self.fake_gerrit.addEvent(e)
self.waitUntilSettled()
job_names = [x.name for x in self.history]
self.assertEqual(len(self.history), 1)
self.assertIn('project-post', job_names)
def test_build_configuration_branch(self):
"Test that the right commits are on alternate branches"

View File

@ -61,6 +61,7 @@ class LayoutSchema(object):
'username': toList(str),
'branch': toList(str),
'ref': toList(str),
'ignore-deletes': bool,
'approval': toList(variable_dict),
'require-approval': toList(require_approval),
}

View File

@ -22,6 +22,8 @@ OrderedDict = extras.try_imports(['collections.OrderedDict',
'ordereddict.OrderedDict'])
EMPTY_GIT_REF = '0' * 40 # git sha of all zeros, used during creates/deletes
MERGER_MERGE = 1 # "git merge"
MERGER_MERGE_RESOLVE = 2 # "git merge -s resolve"
MERGER_CHERRY_PICK = 3 # "git cherry-pick"
@ -1077,7 +1079,8 @@ class BaseFilter(object):
class EventFilter(BaseFilter):
def __init__(self, trigger, types=[], branches=[], refs=[],
event_approvals={}, comments=[], emails=[], usernames=[],
timespecs=[], required_approvals=[], pipelines=[]):
timespecs=[], required_approvals=[], pipelines=[],
ignore_deletes=True):
super(EventFilter, self).__init__(
required_approvals=required_approvals)
self.trigger = trigger
@ -1097,6 +1100,7 @@ class EventFilter(BaseFilter):
self.pipelines = [re.compile(x) for x in pipelines]
self.event_approvals = event_approvals
self.timespecs = timespecs
self.ignore_deletes = ignore_deletes
def __repr__(self):
ret = '<EventFilter'
@ -1109,6 +1113,8 @@ class EventFilter(BaseFilter):
ret += ' branches: %s' % ', '.join(self._branches)
if self._refs:
ret += ' refs: %s' % ', '.join(self._refs)
if self.ignore_deletes:
ret += ' ignore_deletes: %s' % self.ignore_deletes
if self.event_approvals:
ret += ' event_approvals: %s' % ', '.join(
['%s:%s' % a for a in self.event_approvals.items()])
@ -1160,6 +1166,10 @@ class EventFilter(BaseFilter):
matches_ref = True
if self.refs and not matches_ref:
return False
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 False
# comments are ORed
matches_comment_re = False

View File

@ -347,6 +347,7 @@ class Scheduler(threading.Thread):
usernames = toList(trigger.get('username'))
if not usernames:
usernames = toList(trigger.get('username_filter'))
ignore_deletes = trigger.get('ignore-deletes', True)
f = EventFilter(
trigger=self.triggers['gerrit'],
types=toList(trigger['event']),
@ -358,7 +359,8 @@ class Scheduler(threading.Thread):
usernames=usernames,
required_approvals=toList(
trigger.get('require-approval')
)
),
ignore_deletes=ignore_deletes
)
manager.event_filters.append(f)
if 'timer' in conf_pipeline['trigger']: