Skip to content

Commit

Permalink
Make webhooks as separate modules with view and tests.
Browse files Browse the repository at this point in the history
Create python packege for every webhook with view.py and tests.py
  • Loading branch information
Tomasz Kolek authored and timabbott committed Jan 26, 2017
1 parent fc965eb commit 7de4595
Show file tree
Hide file tree
Showing 132 changed files with 99 additions and 58 deletions.
1 change: 1 addition & 0 deletions tools/test-backend
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ if __name__ == "__main__":

if len(args) == 0:
suites = ["zerver.tests",
"zerver.webhooks",
"analytics.tests"]
else:
suites = args
Expand Down
10 changes: 5 additions & 5 deletions zerver/lib/integrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def is_enabled(self):
return settings.EMAIL_GATEWAY_BOT != ""

class WebhookIntegration(Integration):
DEFAULT_FUNCTION_PATH = 'zerver.views.webhooks.{name}.api_{name}_webhook'
DEFAULT_FUNCTION_PATH = 'zerver.webhooks.{name}.view.api_{name}_webhook'
DEFAULT_URL = 'api/v1/external/{name}'
DEFAULT_CLIENT_NAME = 'Zulip{name}Webhook'

Expand Down Expand Up @@ -114,7 +114,7 @@ def url_object(self):
WebhookIntegration('freshdesk'),
GithubIntegration(
'github',
function='zerver.views.webhooks.github.api_github_landing',
function='zerver.webhooks.github.view.api_github_landing',
display_name='GitHub',
secondary_line_text='(deprecated)'
),
Expand All @@ -123,14 +123,14 @@ def url_object(self):
display_name='GitHub',
logo='static/images/integrations/logos/github.png',
secondary_line_text='(webhook)',
function='zerver.views.webhooks.github_webhook.api_github_webhook'
function='zerver.webhooks.github_webhook.view.api_github_webhook'
),
WebhookIntegration('gitlab', display_name='GitLab'),
WebhookIntegration('gosquared', display_name='GoSquared'),
WebhookIntegration('hellosign', display_name='HelloSign'),
WebhookIntegration('helloworld', display_name='Hello World'),
WebhookIntegration('heroku', display_name='Heroku'),
WebhookIntegration('ifttt', function='zerver.views.webhooks.ifttt.api_iftt_app_webhook', display_name='IFTTT'),
WebhookIntegration('ifttt', function='zerver.webhooks.ifttt.view.api_iftt_app_webhook', display_name='IFTTT'),
WebhookIntegration('jira', secondary_line_text='(hosted or v5.2+)', display_name='JIRA'),
WebhookIntegration('librato'),
WebhookIntegration('mention', display_name='Mention'),
Expand All @@ -152,7 +152,7 @@ def url_object(self):
WebhookIntegration('updown'),
WebhookIntegration(
'yo',
function='zerver.views.webhooks.yo.api_yo_app_webhook',
function='zerver.webhooks.yo.view.api_yo_app_webhook',
logo='static/images/integrations/logos/yo-app.png',
display_name='Yo App'
),
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from zerver.lib.test_classes import WebhookTestCase
from django.test import TestCase

from zerver.views.webhooks.appfollow import convert_markdown
from zerver.webhooks.appfollow.view import convert_markdown

class AppFollowHookTests(WebhookTestCase):
STREAM_NAME = 'appfollow'
Expand Down
File renamed without changes.
Empty file.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import base64
from functools import wraps

from .github import build_message_from_gitlog
from zerver.webhooks.github.view import build_message_from_gitlog

from typing import Any, Callable, Dict, TypeVar
from zerver.lib.str_utils import force_str, force_bytes
Expand Down
Empty file.
50 changes: 50 additions & 0 deletions zerver/webhooks/bitbucket/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# -*- coding: utf-8 -*-
from six import text_type
from typing import Union
from zerver.lib.test_classes import WebhookTestCase

class BitbucketHookTests(WebhookTestCase):
STREAM_NAME = 'bitbucket'
URL_TEMPLATE = "/api/v1/external/bitbucket?payload={payload}&stream={stream}"
FIXTURE_DIR_NAME = 'bitbucket'
EXPECTED_SUBJECT = u"Repository name"
EXPECTED_SUBJECT_BRANCH_EVENTS = u"Repository name / master"

def test_bitbucket_on_push_event(self):
# type: () -> None
fixture_name = 'push'
self.url = self.build_url(fixture_name)
commit_info = u'* [25f93d2](https://bitbucket.org/kolaszek/repository-name/commits/25f93d22b719e2d678a7ad5ee0ef0d1fcdf39c12): c'
expected_message = u"kolaszek pushed to branch master\n\n{}".format(commit_info)
self.send_and_test_stream_message(fixture_name, self.EXPECTED_SUBJECT_BRANCH_EVENTS, expected_message, **self.api_auth(self.TEST_USER_EMAIL))

def test_bitbucket_on_push_commits_above_limit_event(self):
# type: () -> None
fixture_name = 'push_commits_above_limit'
self.url = self.build_url(fixture_name)
commit_info = u'* [25f93d2](https://bitbucket.org/kolaszek/repository-name/commits/25f93d22b719e2d678a7ad5ee0ef0d1fcdf39c12): c\n'
expected_message = u"kolaszek pushed to branch master\n\n{}[and 40 more commit(s)]".format(commit_info * 10)
self.send_and_test_stream_message(fixture_name, self.EXPECTED_SUBJECT_BRANCH_EVENTS, expected_message, **self.api_auth(self.TEST_USER_EMAIL))

def test_bitbucket_on_force_push_event(self):
# type: () -> None
fixture_name = 'force_push'
self.url = self.build_url(fixture_name)
expected_message = u"kolaszek [force pushed](https://bitbucket.org/kolaszek/repository-name)"
self.send_and_test_stream_message(fixture_name, self.EXPECTED_SUBJECT, expected_message, **self.api_auth(self.TEST_USER_EMAIL))

def get_body(self, fixture_name):
# type: (text_type) -> Union[text_type, Dict[str, text_type]]
return {}

def get_payload(self, fixture_name):
# type: (text_type) -> Union[text_type, Dict[str, text_type]]
return self.fixture_data(self.FIXTURE_DIR_NAME, fixture_name)

def build_webhook_url(self):
# type: () -> text_type
return ''

def build_url(self, fixture_name):
# type: (text_type) -> text_type
return self.URL_TEMPLATE.format(payload=self.get_payload(fixture_name), stream=self.STREAM_NAME)
File renamed without changes.
Empty file.
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
# -*- coding: utf-8 -*-
from typing import Union, Text
from zerver.lib.webhooks.git import COMMITS_LIMIT
from zerver.lib.test_classes import WebhookTestCase

class Bitbucket2HookTests(WebhookTestCase):
Expand Down Expand Up @@ -180,49 +178,3 @@ def test_bitbucket2_on_more_than_one_push_event(self):
msg = self.get_last_message()
self.do_test_message(msg, 'kolaszek pushed tag [a](https://bitbucket.org/kolaszek/repository-name/commits/tag/a)')
self.do_test_subject(msg, self.EXPECTED_SUBJECT)

class BitbucketHookTests(WebhookTestCase):
STREAM_NAME = 'bitbucket'
URL_TEMPLATE = "/api/v1/external/bitbucket?payload={payload}&stream={stream}"
FIXTURE_DIR_NAME = 'bitbucket'
EXPECTED_SUBJECT = u"Repository name"
EXPECTED_SUBJECT_BRANCH_EVENTS = u"Repository name / master"

def test_bitbucket_on_push_event(self):
# type: () -> None
fixture_name = 'push'
self.url = self.build_url(fixture_name)
commit_info = u'* [25f93d2](https://bitbucket.org/kolaszek/repository-name/commits/25f93d22b719e2d678a7ad5ee0ef0d1fcdf39c12): c'
expected_message = u"kolaszek pushed to branch master\n\n{}".format(commit_info)
self.send_and_test_stream_message(fixture_name, self.EXPECTED_SUBJECT_BRANCH_EVENTS, expected_message, **self.api_auth(self.TEST_USER_EMAIL))

def test_bitbucket_on_push_commits_above_limit_event(self):
# type: () -> None
fixture_name = 'push_commits_above_limit'
self.url = self.build_url(fixture_name)
commit_info = u'* [25f93d2](https://bitbucket.org/kolaszek/repository-name/commits/25f93d22b719e2d678a7ad5ee0ef0d1fcdf39c12): c\n'
expected_message = u"kolaszek pushed to branch master\n\n{}[and 40 more commit(s)]".format(commit_info * 10)
self.send_and_test_stream_message(fixture_name, self.EXPECTED_SUBJECT_BRANCH_EVENTS, expected_message, **self.api_auth(self.TEST_USER_EMAIL))

def test_bitbucket_on_force_push_event(self):
# type: () -> None
fixture_name = 'force_push'
self.url = self.build_url(fixture_name)
expected_message = u"kolaszek [force pushed](https://bitbucket.org/kolaszek/repository-name)"
self.send_and_test_stream_message(fixture_name, self.EXPECTED_SUBJECT, expected_message, **self.api_auth(self.TEST_USER_EMAIL))

def get_body(self, fixture_name):
# type: (Text) -> Union[Text, Dict[str, Text]]
return {}

def get_payload(self, fixture_name):
# type: (Text) -> Union[Text, Dict[str, Text]]
return self.fixture_data(self.FIXTURE_DIR_NAME, fixture_name)

def build_webhook_url(self):
# type: () -> Text
return ''

def build_url(self, fixture_name):
# type: (Text) -> Text
return self.URL_TEMPLATE.format(payload=self.get_payload(fixture_name), stream=self.STREAM_NAME)
File renamed without changes.
Empty file.
File renamed without changes.
File renamed without changes.
Empty file.
File renamed without changes.
File renamed without changes.
Empty file.
File renamed without changes.
File renamed without changes.
Empty file.
File renamed without changes.
File renamed without changes.
Empty file.
File renamed without changes.
File renamed without changes.
Empty file.
File renamed without changes.
File renamed without changes.
Empty file.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from __future__ import absolute_import
from django.http import HttpRequest, HttpResponse
from django.views.decorators.csrf import csrf_exempt
from .github_webhook import api_github_webhook
from .github import api_github_landing
from .github_webhook.view import api_github_webhook
from .github.view import api_github_landing

# Since this dispatcher is an API-style endpoint, it needs to be
# explicitly marked as CSRF-exempt
Expand Down
Empty file.
File renamed without changes.
File renamed without changes.
Empty file.
File renamed without changes.
File renamed without changes.
Empty file.
File renamed without changes.
File renamed without changes.
Empty file.
File renamed without changes.
File renamed without changes.
Empty file.
File renamed without changes.
File renamed without changes.
Empty file.
File renamed without changes.
File renamed without changes.
Empty file.
File renamed without changes.
File renamed without changes.
Empty file.
File renamed without changes.
File renamed without changes.
Empty file.
File renamed without changes.
File renamed without changes.
Empty file.
File renamed without changes.
File renamed without changes.
Empty file.
File renamed without changes.
File renamed without changes.
Empty file.
File renamed without changes.
File renamed without changes.
Empty file.
File renamed without changes.
File renamed without changes.
Empty file.
File renamed without changes.
File renamed without changes.
Empty file.
File renamed without changes.
File renamed without changes.
Empty file.
File renamed without changes.
File renamed without changes.
Empty file.
File renamed without changes.
File renamed without changes.
Empty file.
File renamed without changes.
File renamed without changes.
Empty file.
File renamed without changes.
File renamed without changes.
Empty file.
File renamed without changes.
File renamed without changes.
Empty file.
File renamed without changes.
File renamed without changes.
Empty file.
File renamed without changes.
File renamed without changes.
Empty file.
File renamed without changes.
File renamed without changes.
Empty file.
File renamed without changes.
File renamed without changes.
38 changes: 38 additions & 0 deletions zerver/webhooks/trello/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Webhooks for external integrations.
from __future__ import absolute_import
import ujson
from typing import Mapping, Any, Tuple, Text
from django.utils.translation import ugettext as _
from django.http import HttpRequest, HttpResponse
from zerver.lib.actions import check_send_message
from zerver.decorator import return_success_on_head_request
from zerver.lib.response import json_success, json_error
from zerver.models import UserProfile, Client
from zerver.decorator import REQ, has_request_variables, api_key_only_webhook_view

from .view.card_actions import SUPPORTED_CARD_ACTIONS, process_card_action
from .view.board_actions import SUPPORTED_BOARD_ACTIONS, process_board_action
from .view.exceptions import UnsupportedAction

@api_key_only_webhook_view('Trello')
@return_success_on_head_request
@has_request_variables
def api_trello_webhook(request, user_profile, client, payload=REQ(argument_type='body'), stream=REQ(default='trello')):
# type: (HttpRequest, UserProfile, Client, Mapping[str, Any], Text) -> HttpResponse
payload = ujson.loads(request.body)
action_type = payload.get('action').get('type')
try:
subject, body = get_subject_and_body(payload, action_type)
except UnsupportedAction:
return json_error(_('Unsupported action_type: {action_type}'.format(action_type=action_type)))

check_send_message(user_profile, client, 'stream', [stream], subject, body)
return json_success()

def get_subject_and_body(payload, action_type):
# type: (Mapping[str, Any], Text) -> Tuple[Text, Text]
if action_type in SUPPORTED_CARD_ACTIONS:
return process_card_action(payload, action_type)
if action_type in SUPPORTED_BOARD_ACTIONS:
return process_board_action(payload, action_type)
raise UnsupportedAction('{} if not supported'.format(action_type))
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Empty file.
File renamed without changes.
File renamed without changes.
Empty file added zerver/webhooks/yo/__init__.py
Empty file.
File renamed without changes.
File renamed without changes.
Empty file.
File renamed without changes.
File renamed without changes.
Empty file.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion zproject/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from zproject.legacy_urls import legacy_urls
from zerver.views.integrations import IntegrationView, APIView, HelpView
from zerver.lib.integrations import WEBHOOK_INTEGRATIONS
from zerver.views.webhooks import github_dispatcher
from zerver.webhooks import github_dispatcher


from django.contrib.auth.views import (login, password_reset,
Expand Down

0 comments on commit 7de4595

Please sign in to comment.