diff --git a/doc/source/zuul.rst b/doc/source/zuul.rst index 6c77477acd..9381c9dc90 100644 --- a/doc/source/zuul.rst +++ b/doc/source/zuul.rst @@ -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: diff --git a/etc/layout.yaml-sample b/etc/layout.yaml-sample index 30a335216c..53f6ba19ad 100644 --- a/etc/layout.yaml-sample +++ b/etc/layout.yaml-sample @@ -30,6 +30,7 @@ pipelines: gerrit: - event: ref-updated ref: ^(?!refs/).*$ + ignore-deletes: False - name: gate manager: DependentPipelineManager diff --git a/tests/fixtures/layout-dont-ignore-deletes.yaml b/tests/fixtures/layout-dont-ignore-deletes.yaml new file mode 100644 index 0000000000..1cf3c71067 --- /dev/null +++ b/tests/fixtures/layout-dont-ignore-deletes.yaml @@ -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 diff --git a/tests/fixtures/layouts/good_layout.yaml b/tests/fixtures/layouts/good_layout.yaml index fc2effd668..9ba1806134 100644 --- a/tests/fixtures/layouts/good_layout.yaml +++ b/tests/fixtures/layouts/good_layout.yaml @@ -20,6 +20,7 @@ pipelines: gerrit: - event: ref-updated ref: ^(?!refs/).*$ + ignore-deletes: True - name: gate manager: DependentPipelineManager diff --git a/tests/test_scheduler.py b/tests/test_scheduler.py index 0779bfa2de..19acc9b59c 100755 --- a/tests/test_scheduler.py +++ b/tests/test_scheduler.py @@ -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" diff --git a/zuul/layoutvalidator.py b/zuul/layoutvalidator.py index 88d10e25bf..0a604547eb 100644 --- a/zuul/layoutvalidator.py +++ b/zuul/layoutvalidator.py @@ -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), } diff --git a/zuul/model.py b/zuul/model.py index 8dc28dfbeb..888b868aa6 100644 --- a/zuul/model.py +++ b/zuul/model.py @@ -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 = '