Support all schemas in the custom trigger

Fixes #266
This commit is contained in:
Joseph Schorr 2015-09-22 14:17:20 -04:00
parent 8afb4691a5
commit f99e74f0a1
3 changed files with 165 additions and 9 deletions

View file

@ -1,7 +1,7 @@
import logging import logging
import json import json
from jsonschema import validate from jsonschema import validate, ValidationError
from buildtrigger.triggerutil import (RepositoryReadException, TriggerActivationException, from buildtrigger.triggerutil import (RepositoryReadException, TriggerActivationException,
TriggerStartException, ValidationRequestException, TriggerStartException, ValidationRequestException,
InvalidPayloadException, InvalidPayloadException,
@ -10,11 +10,60 @@ from buildtrigger.triggerutil import (RepositoryReadException, TriggerActivation
from buildtrigger.basehandler import BuildTriggerHandler from buildtrigger.basehandler import BuildTriggerHandler
from buildtrigger.bitbuckethandler import (BITBUCKET_WEBHOOK_PAYLOAD_SCHEMA as bb_schema,
get_transformed_webhook_payload as bb_payload)
from buildtrigger.githubhandler import (GITHUB_WEBHOOK_PAYLOAD_SCHEMA as gh_schema,
get_transformed_webhook_payload as gh_payload)
from buildtrigger.bitbuckethandler import (BITBUCKET_WEBHOOK_PAYLOAD_SCHEMA as bb_schema,
get_transformed_webhook_payload as bb_payload)
from buildtrigger.gitlabhandler import (GITLAB_WEBHOOK_PAYLOAD_SCHEMA as gl_schema,
get_transformed_webhook_payload as gl_payload)
from util.security.ssh import generate_ssh_keypair from util.security.ssh import generate_ssh_keypair
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
# Defines an ordered set of tuples of the schemas and associated transformation functions
# for incoming webhook payloads.
SCHEMA_AND_HANDLERS = [
(gh_schema, gh_payload),
(bb_schema, bb_payload),
(gl_schema, gl_payload),
]
def custom_trigger_payload(metadata, git_url):
# First try the customhandler schema. If it matches, nothing more to do.
custom_handler_validation_error = None
try:
validate(metadata, CustomBuildTrigger.payload_schema)
except ValidationError as vex:
custom_handler_validation_error = vex
# Otherwise, try the defined schemas, in order, until we find a match.
for schema, handler in SCHEMA_AND_HANDLERS:
try:
validate(metadata, schema)
except ValidationError:
continue
result = handler(metadata)
result['git_url'] = git_url
return result
# If we have reached this point and no other schemas validated, then raise the error for the
# custom schema.
if custom_handler_validation_error is not None:
raise InvalidPayloadException(custom_handler_validation_error.message)
metadata['git_url'] = git_url
return metadata
class CustomBuildTrigger(BuildTriggerHandler): class CustomBuildTrigger(BuildTriggerHandler):
payload_schema = { payload_schema = {
'type': 'object', 'type': 'object',
@ -101,13 +150,14 @@ class CustomBuildTrigger(BuildTriggerHandler):
def is_active(self): def is_active(self):
return self.config.has_key('credentials') return self.config.has_key('credentials')
def _metadata_from_payload(self, payload): def _metadata_from_payload(self, payload, git_url):
# Parse the JSON payload.
try: try:
metadata = json.loads(payload) metadata = json.loads(payload)
validate(metadata, self.payload_schema) except ValueError as vex:
except Exception as e: raise InvalidPayloadException(vex.message)
raise InvalidPayloadException(e.message)
return metadata return custom_trigger_payload(metadata, git_url)
def handle_trigger_request(self, request): def handle_trigger_request(self, request):
payload = request.data payload = request.data
@ -116,9 +166,7 @@ class CustomBuildTrigger(BuildTriggerHandler):
logger.debug('Payload %s', payload) logger.debug('Payload %s', payload)
metadata = self._metadata_from_payload(payload) metadata = self._metadata_from_payload(payload, self.config['build_source'])
metadata['git_url'] = self.config['build_source']
prepared = self.prepare_build(metadata) prepared = self.prepare_build(metadata)
# Check if we should skip this build. # Check if we should skip this build.

View file

@ -2,6 +2,7 @@ import unittest
import json import json
from jsonschema import validate, ValidationError from jsonschema import validate, ValidationError
from buildtrigger.customhandler import custom_trigger_payload
from buildtrigger.basehandler import METADATA_SCHEMA from buildtrigger.basehandler import METADATA_SCHEMA
from buildtrigger.bitbuckethandler import get_transformed_webhook_payload as bb_webhook from buildtrigger.bitbuckethandler import get_transformed_webhook_payload as bb_webhook
from buildtrigger.bitbuckethandler import get_transformed_commit_info as bb_commit from buildtrigger.bitbuckethandler import get_transformed_commit_info as bb_commit
@ -21,6 +22,93 @@ class TestPrepareTrigger(unittest.TestCase):
validate(created, METADATA_SCHEMA) validate(created, METADATA_SCHEMA)
def test_custom_custom(self):
expected = {
u'commit':u'1c002dd',
u'commit_info': {
u'url': u'gitsoftware.com/repository/commits/1234567',
u'date': u'timestamp',
u'message': u'initial commit',
u'committer': {
u'username': u'user',
u'url': u'gitsoftware.com/users/user',
u'avatar_url': u'gravatar.com/user.png'
},
u'author': {
u'username': u'user',
u'url': u'gitsoftware.com/users/user',
u'avatar_url': u'gravatar.com/user.png'
}
},
u'ref': u'refs/heads/master',
u'default_branch': u'master',
u'git_url': u'foobar',
}
self.assertSchema('custom_webhook', expected, custom_trigger_payload, git_url='foobar')
def test_custom_gitlab(self):
expected = {
'commit': u'fb88379ee45de28a0a4590fddcbd8eff8b36026e',
'ref': u'refs/heads/master',
'git_url': u'git@gitlab.com:jzelinskie/www-gitlab-com.git',
'commit_info': {
'url': u'https://gitlab.com/jzelinskie/www-gitlab-com/commit/fb88379ee45de28a0a4590fddcbd8eff8b36026e',
'date': u'2015-08-13T19:33:18+00:00',
'message': u'Fix link\n',
},
}
self.assertSchema('gitlab_webhook', expected, custom_trigger_payload, git_url='git@gitlab.com:jzelinskie/www-gitlab-com.git')
def test_custom_github(self):
expected = {
'commit': u'410f4cdf8ff09b87f245b13845e8497f90b90a4c',
'ref': u'refs/heads/master',
'git_url': u'git@github.com:josephschorr/anothertest.git',
'commit_info': {
'url': u'https://github.com/josephschorr/anothertest/commit/410f4cdf8ff09b87f245b13845e8497f90b90a4c',
'date': u'2015-09-11T14:26:16-04:00',
'message': u'Update Dockerfile',
'committer': {
'username': u'josephschorr',
},
'author': {
'username': u'josephschorr',
},
},
}
self.assertSchema('github_webhook', expected, custom_trigger_payload, git_url='git@github.com:josephschorr/anothertest.git')
def test_custom_bitbucket(self):
expected = {
"commit": u"af64ae7188685f8424040b4735ad12941b980d75",
"ref": u"refs/heads/master",
"git_url": u"git@bitbucket.org:jscoreos/another-repo.git",
"commit_info": {
"url": u"https://bitbucket.org/jscoreos/another-repo/commits/af64ae7188685f8424040b4735ad12941b980d75",
"date": u"2015-09-10T20:40:54+00:00",
"message": u"Dockerfile edited online with Bitbucket",
"author": {
"username": u"jscoreos",
"url": u"https://bitbucket.org/jscoreos/",
"avatar_url": u"https://bitbucket.org/account/jscoreos/avatar/32/",
},
"committer": {
"username": u"jscoreos",
"url": u"https://bitbucket.org/jscoreos/",
"avatar_url": u"https://bitbucket.org/account/jscoreos/avatar/32/",
},
},
}
self.assertSchema('bitbucket_webhook', expected, custom_trigger_payload, git_url='git@bitbucket.org:jscoreos/another-repo.git')
def test_bitbucket_customer_payload_noauthor(self): def test_bitbucket_customer_payload_noauthor(self):
expected = { expected = {
"commit": "a0ec139843b2bb281ab21a433266ddc498e605dc", "commit": "a0ec139843b2bb281ab21a433266ddc498e605dc",

View file

@ -0,0 +1,20 @@
{
"commit": "1c002dd",
"ref": "refs/heads/master",
"default_branch": "master",
"commit_info": {
"url": "gitsoftware.com/repository/commits/1234567",
"message": "initial commit",
"date": "timestamp",
"author": {
"username": "user",
"avatar_url": "gravatar.com/user.png",
"url": "gitsoftware.com/users/user"
},
"committer": {
"username": "user",
"avatar_url": "gravatar.com/user.png",
"url": "gitsoftware.com/users/user"
}
}
}