From fb6ff1335e882da7714ed247380025f8abbfc8de Mon Sep 17 00:00:00 2001 From: Fabien Boucher Date: Fri, 17 Jul 2020 16:07:21 +0000 Subject: [PATCH] gitlab: support the labeled event Change-Id: I7c97182e13cd9208e686e5d851cc409b30dd588b --- doc/source/reference/drivers/gitlab.rst | 10 ++++++++++ tests/base.py | 14 +++++++++++++- tests/fixtures/layouts/basic-gitlab.yaml | 18 ++++++++++++++++++ tests/unit/test_gitlab_driver.py | 15 +++++++++++++++ zuul/driver/gitlab/gitlabconnection.py | 12 +++++++++++- zuul/driver/gitlab/gitlabmodel.py | 18 +++++++++--------- zuul/driver/gitlab/gitlabtrigger.py | 4 ++-- 7 files changed, 78 insertions(+), 13 deletions(-) diff --git a/doc/source/reference/drivers/gitlab.rst b/doc/source/reference/drivers/gitlab.rst index 5b9a69b944..4349723659 100644 --- a/doc/source/reference/drivers/gitlab.rst +++ b/doc/source/reference/drivers/gitlab.rst @@ -132,6 +132,10 @@ the following options. Merge request unapproved. + .. value:: labeled + + Merge request labeled. + .. attr:: comment This is only used for ``gl_merge_request`` and ``comment`` actions. It @@ -141,6 +145,12 @@ the following options. match when comments containing 'retrigger' somewhere in the comment text are added to a merge request. + .. attr:: labels + + This is only used for ``gl_merge_request`` and ``labeled`` actions. It + accepts a string or a list of strings that are searched into the list + of labels set to the merge request. + .. attr:: ref This is only used for ``gl_push`` events. This field is treated as diff --git a/tests/base.py b/tests/base.py index c7237519c1..49ed1fb959 100644 --- a/tests/base.py +++ b/tests/base.py @@ -1810,7 +1810,7 @@ class FakeGitlabMergeRequest(object): def _updateTimeStamp(self): self.updated_at = datetime.datetime.now() - def getMergeRequestEvent(self, action): + def getMergeRequestEvent(self, action, include_labels=False): name = 'gl_merge_request' data = { 'object_kind': 'merge_request', @@ -1829,6 +1829,14 @@ class FakeGitlabMergeRequest(object): 'action': action }, } + if include_labels: + data['labels'] = [{'title': label} for label in self.labels] + data['changes'] = { + 'labels': { + 'previous': [], + 'current': data['labels'] + } + } return (name, data) def getMergeRequestOpenedEvent(self): @@ -1846,6 +1854,10 @@ class FakeGitlabMergeRequest(object): self.approved = False return self.getMergeRequestEvent(action='unapproved') + def getMergeRequestLabeledEvent(self, labels): + self.labels = labels + return self.getMergeRequestEvent(action='update', include_labels=True) + def getMergeRequestCommentedEvent(self, note): self.addNote(note) note_date = self.notes[-1]['created_at'].strftime( diff --git a/tests/fixtures/layouts/basic-gitlab.yaml b/tests/fixtures/layouts/basic-gitlab.yaml index d5874266e6..ec9f977af5 100644 --- a/tests/fixtures/layouts/basic-gitlab.yaml +++ b/tests/fixtures/layouts/basic-gitlab.yaml @@ -32,6 +32,17 @@ - approved - unapproved +- pipeline: + name: check-labeled + manager: independent + trigger: + gitlab: + - event: gl_merge_request + action: + - labeled + labels: + - gateit + - pipeline: name: post post-review: true @@ -75,6 +86,10 @@ name: project-test-approval run: playbooks/project-test-approval.yaml +- job: + name: project-test-labeled + run: playbooks/project-test-labeled.yaml + - project: name: org/project check: @@ -84,6 +99,9 @@ check-approval: jobs: - project-test-approval + check-labeled: + jobs: + - project-test-labeled post: jobs: - project-post-job diff --git a/tests/unit/test_gitlab_driver.py b/tests/unit/test_gitlab_driver.py index 5840d004df..c159bbd719 100644 --- a/tests/unit/test_gitlab_driver.py +++ b/tests/unit/test_gitlab_driver.py @@ -161,6 +161,21 @@ class TestGitlabDriver(ZuulTestCase): zuulvars = job.parameters['zuul'] self.assertEqual('check-approval', zuulvars['pipeline']) + @simple_layout('layouts/basic-gitlab.yaml', driver='gitlab') + def test_merge_request_labeled(self): + + A = self.fake_gitlab.openFakeMergeRequest('org/project', 'master', 'A') + + self.fake_gitlab.emitEvent(A.getMergeRequestLabeledEvent( + labels=('label1', 'label2'))) + self.waitUntilSettled() + self.assertEqual(0, len(self.history)) + + self.fake_gitlab.emitEvent(A.getMergeRequestLabeledEvent( + labels=('gateit', ))) + self.waitUntilSettled() + self.assertEqual(1, len(self.history)) + @simple_layout('layouts/basic-gitlab.yaml', driver='gitlab') def test_merge_request_updated_builds_aborted(self): diff --git a/zuul/driver/gitlab/gitlabconnection.py b/zuul/driver/gitlab/gitlabconnection.py index 71ff37ac71..8b528b10c7 100644 --- a/zuul/driver/gitlab/gitlabconnection.py +++ b/zuul/driver/gitlab/gitlabconnection.py @@ -130,8 +130,18 @@ class GitlabEventConnector(threading.Thread): event.change_number) if attrs['action'] == 'open': event.action = 'opened' - elif attrs['action'] == 'update': + elif attrs['action'] == 'update' and "labels" not in body: event.action = 'changed' + elif attrs['action'] == 'update' and "labels" in body: + event.action = 'labeled' + previous_labels = [ + label["title"] for + label in body["changes"]["labels"]["previous"]] + current_labels = [ + label["title"] for + label in body["changes"]["labels"]["current"]] + new_labels = set(current_labels) - set(previous_labels) + event.labels = new_labels elif attrs['action'] in ('approved', 'unapproved'): event.action = attrs['action'] else: diff --git a/zuul/driver/gitlab/gitlabmodel.py b/zuul/driver/gitlab/gitlabmodel.py index 0b4ff35763..4b8a3e3c2f 100644 --- a/zuul/driver/gitlab/gitlabmodel.py +++ b/zuul/driver/gitlab/gitlabmodel.py @@ -59,8 +59,8 @@ class GitlabTriggerEvent(TriggerEvent): self.trigger_name = 'gitlab' self.title = None self.action = None + self.labels = [] self.change_number = None - self.tags = [] def _repr(self): r = [super(GitlabTriggerEvent, self)._repr()] @@ -69,8 +69,8 @@ class GitlabTriggerEvent(TriggerEvent): r.append("project:%s" % self.canonical_project_name) if self.change_number: r.append("mr:%s" % self.change_number) - if self.tags: - r.append("tags:%s" % ', '.join(self.tags)) + if self.labels: + r.append("labels:%s" % ', '.join(self.labels)) return ' '.join(r) def isPatchsetCreated(self): @@ -82,7 +82,7 @@ class GitlabTriggerEvent(TriggerEvent): class GitlabEventFilter(EventFilter): def __init__( self, trigger, types=[], actions=[], - comments=[], refs=[], tags=[], ignore_deletes=True): + comments=[], refs=[], labels=[], ignore_deletes=True): super(GitlabEventFilter, self).__init__(self) self._types = types self.types = [re.compile(x) for x in types] @@ -91,7 +91,7 @@ class GitlabEventFilter(EventFilter): self.comments = [re.compile(x) for x in comments] self._refs = refs self.refs = [re.compile(x) for x in refs] - self.tags = tags + self.labels = labels self.ignore_deletes = ignore_deletes def __repr__(self): @@ -107,8 +107,8 @@ class GitlabEventFilter(EventFilter): ret += ' refs: %s' % ', '.join(self._refs) if self.ignore_deletes: ret += ' ignore_deletes: %s' % self.ignore_deletes - if self.tags: - ret += ' tags: %s' % ', '.join(self.tags) + if self.labels: + ret += ' labels: %s' % ', '.join(self.labels) ret += '>' return ret @@ -148,8 +148,8 @@ class GitlabEventFilter(EventFilter): if self.comments and not matches_comment_re: return False - if self.tags: - if not set(event.tags).intersection(set(self.tags)): + if self.labels: + if not set(event.labels).intersection(set(self.labels)): return False return True diff --git a/zuul/driver/gitlab/gitlabtrigger.py b/zuul/driver/gitlab/gitlabtrigger.py index cf2981ef47..994d6bb5aa 100644 --- a/zuul/driver/gitlab/gitlabtrigger.py +++ b/zuul/driver/gitlab/gitlabtrigger.py @@ -32,7 +32,7 @@ class GitlabTrigger(BaseTrigger): actions=to_list(trigger.get('action')), comments=to_list(trigger.get('comment')), refs=to_list(trigger.get('ref')), - tags=to_list(trigger.get('tag')), + labels=to_list(trigger.get('labels')), ) efilters.append(f) return efilters @@ -52,6 +52,6 @@ def getSchema(): 'action': scalar_or_list(str), 'comment': scalar_or_list(str), 'ref': scalar_or_list(str), - 'tag': scalar_or_list(str) + 'labels': scalar_or_list(str) } return gitlab_trigger