Merge pull request #2443 from coreos-inc/build-webhook-tests

Add tests for build web hooks endpoint
This commit is contained in:
josephschorr 2017-03-20 16:26:57 -04:00 committed by GitHub
commit 4bee4dbfff
7 changed files with 64 additions and 12 deletions

View file

@ -517,6 +517,9 @@ class BitbucketBuildTrigger(BuildTriggerHandler):
def handle_trigger_request(self, request): def handle_trigger_request(self, request):
payload = request.get_json() payload = request.get_json()
if payload is None:
raise InvalidPayloadException('Missing payload')
logger.debug('Got BitBucket request: %s', payload) logger.debug('Got BitBucket request: %s', payload)
repository = self._get_repository_client() repository = self._get_repository_client()

View file

@ -530,6 +530,8 @@ class GithubBuildTrigger(BuildTriggerHandler):
def handle_trigger_request(self, request): def handle_trigger_request(self, request):
# Check the payload to see if we should skip it based on the lack of a head_commit. # Check the payload to see if we should skip it based on the lack of a head_commit.
payload = request.get_json() payload = request.get_json()
if payload is None:
raise InvalidPayloadException('Missing payload')
# This is for GitHub's probing/testing. # This is for GitHub's probing/testing.
if 'zen' in payload: if 'zen' in payload:
@ -537,16 +539,16 @@ class GithubBuildTrigger(BuildTriggerHandler):
# Lookup the default branch for the repository. # Lookup the default branch for the repository.
if 'repository' not in payload: if 'repository' not in payload:
raise ValidationRequestException("Missing 'repository' on request") raise InvalidPayloadException("Missing 'repository' on request")
if 'owner' not in payload['repository']: if 'owner' not in payload['repository']:
raise ValidationRequestException("Missing 'owner' on repository") raise InvalidPayloadException("Missing 'owner' on repository")
if 'name' not in payload['repository']['owner']: if 'name' not in payload['repository']['owner']:
raise ValidationRequestException("Missing owner 'name' on repository") raise InvalidPayloadException("Missing owner 'name' on repository")
if 'name' not in payload['repository']: if 'name' not in payload['repository']:
raise ValidationRequestException("Missing 'name' on repository") raise InvalidPayloadException("Missing 'name' on repository")
default_branch = None default_branch = None
lookup_user = None lookup_user = None

View file

@ -514,7 +514,7 @@ class GitLabBuildTrigger(BuildTriggerHandler):
def handle_trigger_request(self, request): def handle_trigger_request(self, request):
payload = request.get_json() payload = request.get_json()
if not payload: if not payload:
raise SkipRequestException() raise InvalidPayloadException()
logger.debug('GitLab trigger payload %s', payload) logger.debug('GitLab trigger payload %s', payload)
@ -523,7 +523,7 @@ class GitLabBuildTrigger(BuildTriggerHandler):
repo = gl_client.getproject(self.config['build_source']) repo = gl_client.getproject(self.config['build_source'])
if repo is False: if repo is False:
logger.debug('Skipping GitLab build; project %s not found', self.config['build_source']) logger.debug('Skipping GitLab build; project %s not found', self.config['build_source'])
raise SkipRequestException() raise InvalidPayloadException()
default_branch = repo['default_branch'] default_branch = repo['default_branch']
metadata = get_transformed_webhook_payload(payload, default_branch=default_branch, metadata = get_transformed_webhook_payload(payload, default_branch=default_branch,

View file

@ -2,7 +2,8 @@ import json
import pytest import pytest
from buildtrigger.test.githubmock import get_github_trigger from buildtrigger.test.githubmock import get_github_trigger
from buildtrigger.triggerutil import SkipRequestException, ValidationRequestException from buildtrigger.triggerutil import (SkipRequestException, ValidationRequestException,
InvalidPayloadException)
from endpoints.building import PreparedBuild from endpoints.building import PreparedBuild
from util.morecollections import AttrDict from util.morecollections import AttrDict
@ -14,8 +15,8 @@ def github_trigger():
@pytest.mark.parametrize('payload, expected_error, expected_message', [ @pytest.mark.parametrize('payload, expected_error, expected_message', [
('{"zen": true}', SkipRequestException, ""), ('{"zen": true}', SkipRequestException, ""),
('{}', ValidationRequestException, "Missing 'repository' on request"), ('{}', InvalidPayloadException, "Missing 'repository' on request"),
('{"repository": "foo"}', ValidationRequestException, "Missing 'owner' on repository"), ('{"repository": "foo"}', InvalidPayloadException, "Missing 'owner' on repository"),
# Valid payload: # Valid payload:
('''{ ('''{

View file

@ -36,7 +36,7 @@ def test_lookup_user(email, expected_response, gitlab_trigger):
@pytest.mark.parametrize('payload, expected_error, expected_message', [ @pytest.mark.parametrize('payload, expected_error, expected_message', [
('{}', SkipRequestException, ''), ('{}', InvalidPayloadException, ''),
# Valid payload: # Valid payload:
('''{ ('''{

View file

@ -83,6 +83,7 @@ def build_trigger_webhook(trigger_uuid, **kwargs):
namespace = trigger.repository.namespace_user.username namespace = trigger.repository.namespace_user.username
repository = trigger.repository.name repository = trigger.repository.name
permission = ModifyRepositoryPermission(namespace, repository) permission = ModifyRepositoryPermission(namespace, repository)
if permission.can(): if permission.can():
handler = BuildTriggerHandler.get_handler(trigger) handler = BuildTriggerHandler.get_handler(trigger)

View file

@ -24,6 +24,7 @@ from endpoints.api.user import Signin
from endpoints.keyserver import jwk_with_kid from endpoints.keyserver import jwk_with_kid
from endpoints.csrf import OAUTH_CSRF_TOKEN_NAME from endpoints.csrf import OAUTH_CSRF_TOKEN_NAME
from endpoints.web import web as web_bp from endpoints.web import web as web_bp
from endpoints.webhooks import webhooks as webhooks_bp
from initdb import setup_database_for_testing, finished_database_for_testing from initdb import setup_database_for_testing, finished_database_for_testing
from test.helpers import assert_action_logged from test.helpers import assert_action_logged
@ -33,6 +34,12 @@ except ValueError:
# This blueprint was already registered # This blueprint was already registered
pass pass
try:
app.register_blueprint(webhooks_bp, url_prefix='/webhooks')
except ValueError:
# This blueprint was already registered
pass
try: try:
app.register_blueprint(keyserver.key_server, url_prefix='') app.register_blueprint(keyserver.key_server, url_prefix='')
except ValueError: except ValueError:
@ -101,14 +108,20 @@ class EndpointTestCase(unittest.TestCase):
self.assertEquals(rv.status_code, expected_code) self.assertEquals(rv.status_code, expected_code)
return rv.data return rv.data
def postResponse(self, resource_name, headers=None, form=None, with_csrf=True, expected_code=200, **kwargs): def postResponse(self, resource_name, headers=None, data=None, form=None, with_csrf=True, expected_code=200, **kwargs):
headers = headers or {} headers = headers or {}
form = form or {} form = form or {}
url = url_for(resource_name, **kwargs) url = url_for(resource_name, **kwargs)
if with_csrf: if with_csrf:
url = EndpointTestCase._add_csrf(url) url = EndpointTestCase._add_csrf(url)
rv = self.app.post(url, headers=headers, data=form) post_data = None
if form:
post_data = form
elif data:
post_data = py_json.dumps(data)
rv = self.app.post(url, headers=headers, data=post_data)
if expected_code is not None: if expected_code is not None:
self.assertEquals(rv.status_code, expected_code) self.assertEquals(rv.status_code, expected_code)
@ -121,6 +134,38 @@ class EndpointTestCase(unittest.TestCase):
self.assertEquals(rv.status_code, 200) self.assertEquals(rv.status_code, 200)
class WebhookEndpointTestCase(EndpointTestCase):
def test_invalid_build_trigger_webhook(self):
self.postResponse('webhooks.build_trigger_webhook', trigger_uuid='invalidtrigger',
expected_code=404)
def test_valid_build_trigger_webhook_invalid_auth(self):
trigger = list(model.build.list_build_triggers('devtable', 'building'))[0]
self.postResponse('webhooks.build_trigger_webhook', trigger_uuid=trigger.uuid,
expected_code=403)
def test_valid_build_trigger_webhook_cookie_auth(self):
self.login('devtable', 'password')
# Cookie auth is not supported, so this should 403
trigger = list(model.build.list_build_triggers('devtable', 'building'))[0]
self.postResponse('webhooks.build_trigger_webhook', trigger_uuid=trigger.uuid,
expected_code=403)
def test_valid_build_trigger_webhook_missing_payload(self):
auth_header = 'Basic %s' % (base64.b64encode('devtable:password'))
trigger = list(model.build.list_build_triggers('devtable', 'building'))[0]
self.postResponse('webhooks.build_trigger_webhook', trigger_uuid=trigger.uuid,
expected_code=400, headers={'Authorization': auth_header})
def test_valid_build_trigger_webhook_invalid_payload(self):
auth_header = 'Basic %s' % (base64.b64encode('devtable:password'))
trigger = list(model.build.list_build_triggers('devtable', 'building'))[0]
self.postResponse('webhooks.build_trigger_webhook', trigger_uuid=trigger.uuid,
expected_code=400,
headers={'Authorization': auth_header, 'Content-Type': 'application/json'},
data={'invalid': 'payload'})
class WebEndpointTestCase(EndpointTestCase): class WebEndpointTestCase(EndpointTestCase):
def test_index(self): def test_index(self):
self.getResponse('web.index') self.getResponse('web.index')