diff --git a/static/images/integrations/codebase/001.png b/static/images/integrations/codebase/001.png index bd4abb494833b0..6e5d97e006acf5 100644 Binary files a/static/images/integrations/codebase/001.png and b/static/images/integrations/codebase/001.png differ diff --git a/zerver/lib/integrations.py b/zerver/lib/integrations.py index a866f2bec4bd2b..9c7a9a65466c45 100644 --- a/zerver/lib/integrations.py +++ b/zerver/lib/integrations.py @@ -289,6 +289,7 @@ def __init__(self, name: str, *args: Any, **kwargs: Any) -> None: WebhookIntegration('circleci', ['continuous-integration'], display_name='CircleCI'), WebhookIntegration('clubhouse', ['project-management']), WebhookIntegration('codeship', ['continuous-integration', 'deployment']), + WebhookIntegration('codebase', ['project-management'], display_name='Codebase'), WebhookIntegration('crashlytics', ['monitoring']), WebhookIntegration('dialogflow', ['customer-support'], display_name='Dialogflow'), WebhookIntegration('delighted', ['customer-support', 'marketing'], display_name='Delighted'), diff --git a/zerver/webhooks/codebase/__init__.py b/zerver/webhooks/codebase/__init__.py new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/zerver/webhooks/codebase/doc.md b/zerver/webhooks/codebase/doc.md new file mode 100644 index 00000000000000..ff5431b2dc4745 --- /dev/null +++ b/zerver/webhooks/codebase/doc.md @@ -0,0 +1,16 @@ +Get Zulip notifications for your for Codebase events! + +1. {!create-stream.md!} + +1. {!create-bot-construct-url-indented.md!} + +1. Go to your Codebase Dashboard, and click on the settings icon in + the top-right corner. Click on **Event Hooks**. + Now, click **New Event Webhook**. + +1. Set **Payload URL** to the URL constructed above, and click + **Create**. + +{!congrats.md!} + +![](/static/images/integrations/codebase/001.png) diff --git a/zerver/webhooks/codebase/fixtures/ticket_creation.json b/zerver/webhooks/codebase/fixtures/ticket_creation.json new file mode 100644 index 00000000000000..a8ed753b6f1ef6 --- /dev/null +++ b/zerver/webhooks/codebase/fixtures/ticket_creation.json @@ -0,0 +1,4 @@ +{ + "type": "ticket_creation", + "payload": "{\"id\":2,\"summary\":\"Adding the brand new feature of auto tuning to my webapp\",\"status\":{\"name\":\"New\",\"colour\":\"green\",\"closed\":false},\"milestone\":null,\"priority\":{\"name\":\"High\",\"colour\":\"orange\"},\"assignee\":{\"name\":\"Sameer Choubey\",\"username\":\"sameer-choubey-89\",\"email_address\":\"inadaptabl@firamax.club\"},\"reporter\":{\"name\":\"Sameer Choubey\",\"username\":\"sameer-choubey-89\",\"email_address\":\"inadaptabl@firamax.club\"},\"type\":{\"name\":\"Enhancement\",\"icon\":\"hat\"},\"category\":\"General\",\"description\":\"We'll first start with making a list of ideas that needed to be implemented.\",\"project\":{\"name\":\"Adding support for checking events.\",\"url\":\"http://travelalittle.codebasehq.com/projects/adding-support-for-checking-events\",\"status\":\"active\",\"account\":{\"name\":\"TravelAlIttle\",\"url\":\"https://travelalittle.codebasehq.com\",\"email\":\"inadaptabl@firamax.club\"}},\"url\":\"http://travelalittle.codebasehq.com/projects/adding-support-for-checking-events/tickets/2\"}" +} diff --git a/zerver/webhooks/codebase/fixtures/ticket_update.json b/zerver/webhooks/codebase/fixtures/ticket_update.json new file mode 100644 index 00000000000000..b6bb3b342d4dbc --- /dev/null +++ b/zerver/webhooks/codebase/fixtures/ticket_update.json @@ -0,0 +1,4 @@ +{ + "type": "ticket_update", + "payload": "{\"ticket\":{\"id\":2,\"summary\":\"Adding the brand new feature of auto tuning to my webapp\",\"status\":{\"name\":\"In Progress\",\"colour\":\"blue\",\"closed\":false},\"milestone\":null,\"priority\":{\"name\":\"Normal\",\"colour\":\"blue\"},\"assignee\":{\"name\":\"Sameer Choubey\",\"username\":\"sameer-choubey-89\",\"email_address\":\"inadaptabl@firamax.club\"},\"reporter\":{\"name\":\"Sameer Choubey\",\"username\":\"sameer-choubey-89\",\"email_address\":\"inadaptabl@firamax.club\"},\"type\":{\"name\":\"Feature\",\"icon\":\"construction\"},\"category\":\"Refactoring\",\"description\":\"We'll first start with making a list of ideas that needed to be implemented.\",\"project\":{\"name\":\"Adding support for checking events.\",\"url\":\"http://travelalittle.codebasehq.com/projects/adding-support-for-checking-events\",\"status\":\"active\",\"account\":{\"name\":\"TravelAlIttle\",\"url\":\"https://travelalittle.codebasehq.com\",\"email\":\"inadaptabl@firamax.club\"}},\"url\":\"http://travelalittle.codebasehq.com/projects/adding-support-for-checking-events/tickets/2\"},\"user\":{\"name\":\"Sameer Choubey\",\"username\":\"sameer-choubey-89\",\"email_address\":\"inadaptabl@firamax.club\"},\"content\":\"The second step is to outline the new idea with the help of block statements.\",\"changes\":{\"priority_id\":[\"High\",\"Normal\"],\"ticket_type_id\":[\"Enhancement\",\"Feature\"],\"category_id\":[\"General\",\"Refactoring\"],\"status_id\":[\"New\",\"In Progress\"]},\"commit\":null,\"attachments\":[]}" +} diff --git a/zerver/webhooks/codebase/tests.py b/zerver/webhooks/codebase/tests.py new file mode 100644 index 00000000000000..1d8977e55bbe39 --- /dev/null +++ b/zerver/webhooks/codebase/tests.py @@ -0,0 +1,18 @@ +from zerver.lib.test_classes import WebhookTestCase + +class CobebaseHookTests(WebhookTestCase): + STREAM_NAME = 'codebase' + URL_TEMPLATE = "/api/v1/external/codebase?&api_key={api_key}&stream={stream}" + FIXTURE_DIR_NAME = 'codebase' + + + def test_ticket_creation(self) -> None: + expected_topic = u"Adding the brand new feature of auto tuning to my webapp" + expected_message = u"A ticket of **[Enhancement](http://travelalittle.codebasehq.com/projects/adding-support-for-checking-events/tickets/2)** type and category **General** has been created by **Sameer Choubey**" + + self.send_and_test_stream_message('ticket_creation', expected_topic, expected_message) + + def test_ticket_update(self) -> None: + expected_topic = u"Adding the brand new feature of auto tuning to my webapp" + expected_message = u"Ticket with ID **[2](http://travelalittle.codebasehq.com/projects/adding-support-for-checking-events)**, category **Refactoring** has been updated by **Sameer Choubey**" + self.send_and_test_stream_message('ticket_update', expected_topic, expected_message) diff --git a/zerver/webhooks/codebase/view.py b/zerver/webhooks/codebase/view.py new file mode 100644 index 00000000000000..12ce351833994c --- /dev/null +++ b/zerver/webhooks/codebase/view.py @@ -0,0 +1,83 @@ +import json +from typing import Any, Dict, Iterable + +from django.http import HttpRequest, HttpResponse +from zerver.decorator import api_key_only_webhook_view +from zerver.lib.webhooks.common import check_send_webhook_message, \ + UnexpectedWebhookEventType +from zerver.lib.request import REQ, has_request_variables +from zerver.lib.response import json_success +from zerver.models import UserProfile + +def get_event_type(payload: Dict[str, Any]): + return (payload['type']) + +def get_topic_type(payload: Dict[str, Any]): + + if payload['type'] == "ticket_update": + payload = payload['payload'] + payload = json.loads(payload) + + return payload['ticket']['summary'] + else: + payload = payload['payload'] + payload = json.loads(payload) + + return payload['summary'] + +def ticket_creation(payload: Dict[str, Any], user_profile: UserProfile): + + payload = payload['payload'] + payload = json.loads(payload) + + type = payload['type']['name'] + name = payload['assignee']['name'] + category = payload['category'] + url = payload['url'] + + body = "A ticket of **[{}]({})** type and category **{}** has been created by **{}**".format(type, url, category, name) + + return body + +def ticket_update(payload: Dict[str, Any], user_profile: UserProfile): + payload = payload['payload'] + payload = json.loads(payload) + + id = payload['ticket']['id'] + type = payload['ticket']['category'] + name = payload['user']['name'] + url = payload['ticket']['project']['url'] + + body = "Ticket with ID **[{}]({})**, category **{}** has been updated by **{}**".format(id, url, type, name) + + return body + +CODEBASE_EVENT_MAPPER = { + "ticket_creation": ticket_creation, + "ticket_update": ticket_update +} + +@api_key_only_webhook_view('CodeBase') +@has_request_variables +def api_codebase_webhook( + request: HttpRequest, user_profile: UserProfile, + payload: Dict[str, Iterable[Dict[str, Any]]]=REQ(argument_type='body') +) -> HttpResponse: + + if payload is None: + return json_success() + + event = get_event_type(payload) + topic = get_topic_type(payload) + + if event is not None: + body_func = CODEBASE_EVENT_MAPPER.get(event) + + if body_func is None: + raise UnexpectedWebhookEventType('Cobdebase', event) + + body = body_func(payload, user_profile) # type : str + + check_send_webhook_message(request, user_profile, topic, body) + + return json_success()