diff --git a/buildtrigger/gitlabhandler.py b/buildtrigger/gitlabhandler.py index 945e88257..66a3192fa 100644 --- a/buildtrigger/gitlabhandler.py +++ b/buildtrigger/gitlabhandler.py @@ -28,7 +28,7 @@ GITLAB_WEBHOOK_PAYLOAD_SCHEMA = { 'type': 'string', }, 'checkout_sha': { - 'type': 'string', + 'type': ['string', 'null'], }, 'repository': { 'type': 'object', @@ -65,8 +65,7 @@ GITLAB_WEBHOOK_PAYLOAD_SCHEMA = { }, 'required': ['url', 'message', 'timestamp'], }, - 'minItems': 1, - } + }, }, 'required': ['ref', 'checkout_sha', 'repository'], } @@ -94,19 +93,35 @@ def get_transformed_webhook_payload(gl_payload, default_branch=None, lookup_user payload = JSONPathDict(gl_payload) + # Check for empty commits. The commits list will be empty if the branch is deleted. + commits = payload['commits'] + if not commits: + raise SkipRequestException + config = SafeDictSetter() config['commit'] = payload['checkout_sha'] config['ref'] = payload['ref'] config['default_branch'] = default_branch config['git_url'] = payload['repository.git_ssh_url'] - config['commit_info.url'] = payload['commits[0].url'] - config['commit_info.message'] = payload['commits[0].message'] - config['commit_info.date'] = payload['commits[0].timestamp'] + # Find the commit associated with the checkout_sha. Gitlab doesn't (necessary) send this in + # any order, so we cannot simply index into the commits list. + found_commit = None + for commit in commits: + if commit['id'] == payload['checkout_sha']: + found_commit = JSONPathDict(commit) + break + + if found_commit is None: + raise SkipRequestException + + config['commit_info.url'] = found_commit['url'] + config['commit_info.message'] = found_commit['message'] + config['commit_info.date'] = found_commit['timestamp'] # Note: Gitlab does not send full user information with the payload, so we have to # (optionally) look it up. - author_email = payload['commits[0].author.email'] + author_email = found_commit['author.email'] if lookup_user and author_email: author_info = lookup_user(author_email) if author_info: diff --git a/test/test_prepare_trigger.py b/test/test_prepare_trigger.py index 79cbe98f1..30f2a510e 100644 --- a/test/test_prepare_trigger.py +++ b/test/test_prepare_trigger.py @@ -8,8 +8,20 @@ from buildtrigger.bitbuckethandler import get_transformed_webhook_payload as bb_ from buildtrigger.bitbuckethandler import get_transformed_commit_info as bb_commit from buildtrigger.githubhandler import get_transformed_webhook_payload as gh_webhook from buildtrigger.gitlabhandler import get_transformed_webhook_payload as gl_webhook +from buildtrigger.triggerutil import SkipRequestException class TestPrepareTrigger(unittest.TestCase): + def assertSkipped(self, filename, processor, *args, **kwargs): + with open('test/triggerjson/%s.json' % filename) as f: + payload = json.loads(f.read()) + + nargs = [payload] + nargs.extend(args) + + with self.assertRaises(SkipRequestException): + processor(*nargs, **kwargs) + + def assertSchema(self, filename, expected, processor, *args, **kwargs): with open('test/triggerjson/%s.json' % filename) as f: payload = json.loads(f.read()) @@ -349,6 +361,37 @@ class TestPrepareTrigger(unittest.TestCase): self.assertSchema('github_webhook_missing', expected, gh_webhook) + def test_gitlab_webhook_nocommit_payload(self): + self.assertSkipped('gitlab_webhook_nocommit', gl_webhook) + + + def test_gitlab_webhook_multiple_commits(self): + expected = { + 'commit': u'9a052a0b2fbe01d4a1a88638dd9fe31c1c56ef53', + 'ref': u'refs/heads/master', + 'git_url': u'git@gitlab.com:joseph.schorr/some-test-project.git', + 'commit_info': { + 'url': u'https://gitlab.com/joseph.schorr/some-test-project/commit/9a052a0b2fbe01d4a1a88638dd9fe31c1c56ef53', + 'date': u'2016-09-29T15:02:41+00:00', + 'message': u"Merge branch 'foobar' into 'master'\r\n\r\nAdd changelog\r\n\r\nSome merge thing\r\n\r\nSee merge request !1", + 'author': { + 'username': 'josephschorr', + 'url': 'http://gitlab.com/josephschorr', + 'avatar_url': 'http://some/avatar/url' + }, + }, + } + + def lookup_user(_): + return { + 'username': 'josephschorr', + 'html_url': 'http://gitlab.com/josephschorr', + 'avatar_url': 'http://some/avatar/url', + } + + self.assertSchema('gitlab_webhook_multicommit', expected, gl_webhook, lookup_user=lookup_user) + + def test_gitlab_webhook_payload_with_lookup(self): expected = { 'commit': u'fb88379ee45de28a0a4590fddcbd8eff8b36026e', diff --git a/test/triggerjson/gitlab_webhook_multicommit.json b/test/triggerjson/gitlab_webhook_multicommit.json new file mode 100644 index 000000000..258e1a3f4 --- /dev/null +++ b/test/triggerjson/gitlab_webhook_multicommit.json @@ -0,0 +1,100 @@ +{ + "object_kind": "push", + "event_name": "push", + "before": "0da5b5ebb397f0a8569c97f28e266c718607e8da", + "after": "9a052a0b2fbe01d4a1a88638dd9fe31c1c56ef53", + "ref": "refs\/heads\/master", + "checkout_sha": "9a052a0b2fbe01d4a1a88638dd9fe31c1c56ef53", + "message": null, + "user_id": 750047, + "user_name": "Joseph Schorr", + "user_email": "joseph.schorr@coreos.com", + "user_avatar": "https:\/\/secure.gravatar.com\/avatar\/63e4521c07d2312d8e20c3a6cad36f57?s=80&d=identicon", + "project_id": 1756744, + "project": { + "name": "some-test-project", + "description": "", + "web_url": "https:\/\/gitlab.com\/joseph.schorr\/some-test-project", + "avatar_url": null, + "git_ssh_url": "git@gitlab.com:joseph.schorr\/some-test-project.git", + "git_http_url": "https:\/\/gitlab.com\/joseph.schorr\/some-test-project.git", + "namespace": "joseph.schorr", + "visibility_level": 0, + "path_with_namespace": "joseph.schorr\/some-test-project", + "default_branch": "master", + "homepage": "https:\/\/gitlab.com\/joseph.schorr\/some-test-project", + "url": "git@gitlab.com:joseph.schorr\/some-test-project.git", + "ssh_url": "git@gitlab.com:joseph.schorr\/some-test-project.git", + "http_url": "https:\/\/gitlab.com\/joseph.schorr\/some-test-project.git" + }, + "commits": [ + { + "id": "f00a0a6a71118721ac1f586bf79650170042609f", + "message": "Add changelog", + "timestamp": "2016-09-29T14:59:23+00:00", + "url": "https:\/\/gitlab.com\/joseph.schorr\/some-test-project\/commit\/f00a0a6a71118721ac1f586bf79650170042609f", + "author": { + "name": "Joseph Schorr", + "email": "joseph.schorr@coreos.com" + }, + "added": [ + "CHANGELOG" + ], + "modified": [ + + ], + "removed": [ + + ] + }, + { + "id": "cc66287314cb154c986665a6c29377ef42edee60", + "message": "Add new file", + "timestamp": "2016-09-29T15:02:01+00:00", + "url": "https:\/\/gitlab.com\/joseph.schorr\/some-test-project\/commit\/cc66287314cb154c986665a6c29377ef42edee60", + "author": { + "name": "Joseph Schorr", + "email": "joseph.schorr@coreos.com" + }, + "added": [ + "YetAnotherFIle" + ], + "modified": [ + + ], + "removed": [ + + ] + }, + { + "id": "9a052a0b2fbe01d4a1a88638dd9fe31c1c56ef53", + "message": "Merge branch 'foobar' into 'master'\r\n\r\nAdd changelog\r\n\r\nSome merge thing\r\n\r\nSee merge request !1", + "timestamp": "2016-09-29T15:02:41+00:00", + "url": "https:\/\/gitlab.com\/joseph.schorr\/some-test-project\/commit\/9a052a0b2fbe01d4a1a88638dd9fe31c1c56ef53", + "author": { + "name": "Joseph Schorr", + "email": "joseph.schorr@coreos.com" + }, + "added": [ + "CHANGELOG", + "YetAnotherFIle" + ], + "modified": [ + + ], + "removed": [ + + ] + } + ], + "total_commits_count": 3, + "repository": { + "name": "some-test-project", + "url": "git@gitlab.com:joseph.schorr\/some-test-project.git", + "description": "", + "homepage": "https:\/\/gitlab.com\/joseph.schorr\/some-test-project", + "git_http_url": "https:\/\/gitlab.com\/joseph.schorr\/some-test-project.git", + "git_ssh_url": "git@gitlab.com:joseph.schorr\/some-test-project.git", + "visibility_level": 0 + } +} \ No newline at end of file diff --git a/test/triggerjson/gitlab_webhook_nocommit.json b/test/triggerjson/gitlab_webhook_nocommit.json new file mode 100644 index 000000000..7d345840b --- /dev/null +++ b/test/triggerjson/gitlab_webhook_nocommit.json @@ -0,0 +1,44 @@ +{ + "object_kind": "push", + "event_name": "push", + "before": "cc66287314cb154c986665a6c29377ef42edee60", + "after": "0000000000000000000000000000000000000000", + "ref": "refs\/heads\/foobar", + "checkout_sha": null, + "message": null, + "user_id": 750047, + "user_name": "Joseph Schorr", + "user_email": "joseph.schorr@coreos.com", + "user_avatar": "https:\/\/secure.gravatar.com\/avatar\/63e4521c07d2312d8e20c3a6cad36f57?s=80&d=identicon", + "project_id": 1756744, + "project": { + "name": "some-test-project", + "description": "", + "web_url": "https:\/\/gitlab.com\/joseph.schorr\/some-test-project", + "avatar_url": null, + "git_ssh_url": "git@gitlab.com:joseph.schorr\/some-test-project.git", + "git_http_url": "https:\/\/gitlab.com\/joseph.schorr\/some-test-project.git", + "namespace": "joseph.schorr", + "visibility_level": 0, + "path_with_namespace": "joseph.schorr\/some-test-project", + "default_branch": "master", + "homepage": "https:\/\/gitlab.com\/joseph.schorr\/some-test-project", + "url": "git@gitlab.com:joseph.schorr\/some-test-project.git", + "ssh_url": "git@gitlab.com:joseph.schorr\/some-test-project.git", + "http_url": "https:\/\/gitlab.com\/joseph.schorr\/some-test-project.git" + }, + "commits": [ + + ], + "total_commits_count": 0, + "repository": { + "name": "some-test-project", + "url": "git@gitlab.com:joseph.schorr\/some-test-project.git", + "description": "", + "homepage": "https:\/\/gitlab.com\/joseph.schorr\/some-test-project", + "git_http_url": "https:\/\/gitlab.com\/joseph.schorr\/some-test-project.git", + "git_ssh_url": "git@gitlab.com:joseph.schorr\/some-test-project.git", + "visibility_level": 0 + } +} +