Add codeship integration.

This commit is contained in:
Tomasz Kolek 2016-04-11 22:32:07 +02:00 committed by Tim Abbott
parent 8c62a27769
commit 5fbda3a9c1
12 changed files with 220 additions and 1 deletions

View File

@ -9,7 +9,7 @@ All notable changes to this project will be documented in this file.
- Added documentation on using Hubot to integrate with useful services
not yet integrated with Zulip directly (e.g. Google Hangouts).
- Added new management command to test sending email from Zulip.
- Added Pingdom, Teamcity, and Yo integrations.
- Added Codeship, Pingdom, Teamcity, and Yo integrations.
- Refactored the Zulip puppet modules to be more modular.
- Refactored the Tornado event system, fixing old memory leaks.
- Implemented running queue processors multithreaded in development,

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

@ -78,6 +78,12 @@
<span class="integration-label">Codebase</span>
</a>
</div>
<div class="integration-lozenge integration-codeship">
<a class="integration-link integration-codeship" href="#codeship">
<img class="integration-logo" src="/static/images/integrations/logos/codeship.png" alt="Codeship logo" />
<span class="integration-label">Codeship</span>
</a>
</div>
<div class="integration-lozenge integration-deskcom">
<a class="integration-link integration-deskcom" href="#deskcom">
<img class="integration-logo" src="/static/images/integrations/logos/deskcom.png" alt="Desk.com logo" />
@ -562,6 +568,35 @@
<img class="screenshot" src="/static/images/integrations/codebase/001.png" />
</div>
<div id="codeship" class="integration-instructions">
<p>Zulip supports integration with Codeship and can notify you of
your build statuses.</p>
<p>First, create the stream you'd like to use for Codeship notifications,
and subscribe all interested parties to this stream. We
recommend the name <code>codeship</code>.</p>
<p><code>{{ external_api_uri }}/v1/external/codeship?api_key=abcdefgh&amp;stream=codeship</code></p>
<p>where <code>api_key</code> is the API key of your Zulip bot,
and <code>stream</code> is the stream name you want the
notifications sent to.</p>
<p>Next, go to your project settings - notification settings
page. The url should look like the following:</p>
<p><code>https://codeship.com/projects/PROJECT_ID/configure_notifications</code></p>
<p>where <code>PROJECT_ID</code> is the id of your project in Codeship.</p>
<p>Scroll to the <code>Webhook</code> section and fill out the form as follows:</p>
<img class="screenshot" src="/static/images/integrations/codeship/001.png" />
<p><b>Congratulations! You're done!</b><br /> When a build is
triggered, you'll get a notification like this:</p>
<img class="screenshot" src="/static/images/integrations/codeship/002.png" />
</div>
<div id="deskcom" class="integration-instructions">

View File

@ -0,0 +1,16 @@
{
"build": {
"build_url":"https://www.codeship.com/projects/10213/builds/973711",
"commit_url":"https://github.com/codeship/docs/commit/96943dc5269634c211b6fbb18896ecdcbd40a047",
"project_id":10213,
"build_id":973711,
"status":"error",
"project_full_name":"codeship/docs",
"project_name":"codeship/docs",
"commit_id":"96943dc5269634c211b6fbb18896ecdcbd40a047",
"short_commit_id":"96943",
"message":"Merge pull request #34 from codeship/feature/shallow-clone",
"committer":"beanieboi",
"branch":"master"
}
}

View File

@ -0,0 +1,16 @@
{
"build": {
"build_url":"https://www.codeship.com/projects/10213/builds/973711",
"commit_url":"https://github.com/codeship/docs/commit/96943dc5269634c211b6fbb18896ecdcbd40a047",
"project_id":10213,
"build_id":973711,
"status":"some_other_status",
"project_full_name":"codeship/docs",
"project_name":"codeship/docs",
"commit_id":"96943dc5269634c211b6fbb18896ecdcbd40a047",
"short_commit_id":"96943",
"message":"Merge pull request #34 from codeship/feature/shallow-clone",
"committer":"beanieboi",
"branch":"master"
}
}

View File

@ -0,0 +1,16 @@
{
"build": {
"build_url":"https://www.codeship.com/projects/10213/builds/973711",
"commit_url":"https://github.com/codeship/docs/commit/96943dc5269634c211b6fbb18896ecdcbd40a047",
"project_id":10213,
"build_id":973711,
"status":"success",
"project_full_name":"codeship/docs",
"project_name":"codeship/docs",
"commit_id":"96943dc5269634c211b6fbb18896ecdcbd40a047",
"short_commit_id":"96943",
"message":"Merge pull request #34 from codeship/feature/shallow-clone",
"committer":"beanieboi",
"branch":"master"
}
}

View File

@ -0,0 +1,16 @@
{
"build": {
"build_url":"https://www.codeship.com/projects/10213/builds/973711",
"commit_url":"https://github.com/codeship/docs/commit/96943dc5269634c211b6fbb18896ecdcbd40a047",
"project_id":10213,
"build_id":973711,
"status":"testing",
"project_full_name":"codeship/docs",
"project_name":"codeship/docs",
"commit_id":"96943dc5269634c211b6fbb18896ecdcbd40a047",
"short_commit_id":"96943",
"message":"Merge pull request #34 from codeship/feature/shallow-clone",
"committer":"beanieboi",
"branch":"master"
}
}

View File

@ -1001,3 +1001,69 @@ class TeamcityHookTests(AuthedTestCase):
self.assertEqual(msg.recipient.type, Recipient.PERSONAL)
self.assertEqual(msg.content, u"Your personal build of Project :: Compile build 5535 - CL 123456 is broken with status Exit code 1 (new)! :thumbsdown:\nDetails: [changes](http://teamcity/viewLog.html?buildTypeId=Project_Compile&buildId=19952&tab=buildChangesDiv), [build log](http://teamcity/viewLog.html?buildTypeId=Project_Compile&buildId=19952)")
class CodeshipHookTests(AuthedTestCase):
STREAM_NAME = 'codeship'
TEST_USER_EMAIL = 'hamlet@zulip.com'
URL_TEMPLATE = "/api/v1/external/codeship?stream={stream}&api_key={api_key}"
def setUp(self):
api_key = self.get_api_key(self.TEST_USER_EMAIL)
self._url = self.URL_TEMPLATE.format(stream=self.STREAM_NAME, api_key=api_key)
self.subscribe_to_stream(self.TEST_USER_EMAIL, self.STREAM_NAME)
def test_codeship_build_in_testing_status_message(self):
"""
Tests if codeship testing status is mapped correctly
"""
body = self._get_fixture_data('testing_build')
self._send_post_request_with_params(body)
expected_message = u"[Build](https://www.codeship.com/projects/10213/builds/973711) triggered by beanieboi on master branch started."
msg = self._get_recently_added_message()
self.assertEqual(msg.subject, u"codeship/docs")
self.assertEqual(msg.content, expected_message)
def test_codeship_build_in_error_status_message(self):
"""
Tests if codeship error status is mapped correctly
"""
body = self._get_fixture_data('error_build')
self._send_post_request_with_params(body)
expected_message = u"[Build](https://www.codeship.com/projects/10213/builds/973711) triggered by beanieboi on master branch failed."
msg = self._get_recently_added_message()
self.assertEqual(msg.subject, u"codeship/docs")
self.assertEqual(msg.content, expected_message)
def test_codeship_build_in_success_status_message(self):
"""
Tests if codeship success status is mapped correctly
"""
body = self._get_fixture_data('success_build')
self._send_post_request_with_params(body)
expected_message = u"[Build](https://www.codeship.com/projects/10213/builds/973711) triggered by beanieboi on master branch succeeded."
msg = self._get_recently_added_message()
self.assertEqual(msg.subject, u"codeship/docs")
self.assertEqual(msg.content, expected_message)
def test_codeship_build_in_other_status_status_message(self):
"""
Tests if codeship other status is mapped correctly
"""
body = self._get_fixture_data('other_status_build')
self._send_post_request_with_params(body)
expected_message = u"[Build](https://www.codeship.com/projects/10213/builds/973711) triggered by beanieboi on master branch has some_other_status status."
msg = self._get_recently_added_message()
self.assertEqual(msg.subject, u"codeship/docs")
self.assertEqual(msg.content, expected_message)
def _get_recently_added_message(self):
return Message.objects.filter().order_by('-id')[0]
def _get_fixture_data(self, name):
return ujson.dumps(ujson.loads(self.fixture_data('codeship', name)))
def _send_post_request_with_params(self, json):
return self.client.post(self._url, json, stream_name=self.STREAM_NAME, content_type="application/json")

View File

@ -0,0 +1,53 @@
# Webhooks for external integrations.
from __future__ import absolute_import
from zerver.models import get_client
from zerver.lib.actions import check_send_message
from zerver.lib.response import json_success, json_error
from zerver.decorator import REQ, has_request_variables, api_key_only_webhook_view
import ujson
CODESHIP_SUBJECT_TEMPLATE = '{project_name}'
CODESHIP_MESSAGE_TEMPLATE = '[Build]({build_url}) triggered by {committer} on {branch} branch {status}.'
CODESHIP_DEFAULT_STATUS = 'has {status} status'
CODESHIP_STATUS_MAPPER = {
'testing': 'started',
'error': 'failed',
'success': 'succeeded',
}
@api_key_only_webhook_view
@has_request_variables
def api_codeship_webhook(request, user_profile, stream=REQ(default='codeship')):
try:
payload = ujson.loads(request.body)['build']
subject = get_subject_for_http_request(payload)
body = get_body_for_http_request(payload)
except KeyError as e:
return json_error("Missing key {} in JSON".format(e.message))
except ValueError as e:
return json_error("Malformed JSON")
check_send_message(user_profile, get_client('ZulipCodeshipWebhook'), 'stream', [stream], subject, body)
return json_success()
def get_subject_for_http_request(payload):
return CODESHIP_SUBJECT_TEMPLATE.format(project_name=payload['project_name'])
def get_body_for_http_request(payload):
return CODESHIP_MESSAGE_TEMPLATE.format(
build_url=payload['build_url'],
committer=payload['committer'],
branch=payload['branch'],
status=get_status_message(payload)
)
def get_status_message(payload):
build_status = payload['status']
return CODESHIP_STATUS_MAPPER.get(build_status, CODESHIP_DEFAULT_STATUS.format(status=build_status))

View File

@ -157,6 +157,7 @@ urlpatterns += patterns('zerver.views',
url(r'^api/v1/external/teamcity$', 'webhooks.teamcity.api_teamcity_webhook'),
url(r'^api/v1/external/pingdom$', 'webhooks.pingdom.api_pingdom_webhook'),
url(r'^api/v1/external/yo$', 'webhooks.yo.api_yo_app_webhook'),
url(r'^api/v1/external/codeship', 'webhooks.codeship.api_codeship_webhook'),
url(r'^user_uploads/(?P<realm_id>(\d*|unk))/(?P<filename>.*)', 'get_uploaded_file'),
)