mirror of
https://github.com/zulip/zulip.git
synced 2025-11-02 21:13:36 +00:00
Add Semaphore webhook integration.
This commit is contained in:
BIN
static/images/integrations/logos/semaphore.png
Normal file
BIN
static/images/integrations/logos/semaphore.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
BIN
static/images/integrations/semaphore/001.png
Normal file
BIN
static/images/integrations/semaphore/001.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 63 KiB |
BIN
static/images/integrations/semaphore/002.png
Normal file
BIN
static/images/integrations/semaphore/002.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
BIN
static/images/integrations/semaphore/003.png
Normal file
BIN
static/images/integrations/semaphore/003.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
@@ -232,6 +232,12 @@
|
||||
<span class="integration-label">RSS</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="integration-lozenge integration-semaphore">
|
||||
<a class="integration-link integration-semaphore" href="#semaphore">
|
||||
<img class="integration-logo" src="/static/images/integrations/logos/semaphore.png" alt="Semaphore logo" />
|
||||
<span class="integration-label">Semaphore</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="integration-lozenge integration-stash">
|
||||
<a class="integration-link integration-stash" href="#stash">
|
||||
<img class="integration-logo" src="/static/images/integrations/logos/stash.png" alt="Stash logo" />
|
||||
@@ -1768,6 +1774,50 @@ key = NAGIOS_BOT_API_KEY
|
||||
</div>
|
||||
|
||||
|
||||
<div id="semaphore" class="integration-instructions">
|
||||
<h4>Semaphore</h4>
|
||||
|
||||
<p>See build and deploy statuses on Semaphore right in Zulip with the Zulip
|
||||
Semaphore plugin!</p>
|
||||
|
||||
<p>First, create the stream you'd like to use for Semaphore notifications, and
|
||||
subscribe all interested parties to this stream. We recommend the
|
||||
name <code>builds</code>.</p>
|
||||
|
||||
<p>Next, on your <a href="/#settings" target="_blank">Zulip settings
|
||||
page</a>, create a Semaphore bot.</p>
|
||||
|
||||
<p>Then, log into your account on <a href="http://semaphoreci.com">semaphoreci.com</a>, and:</p>
|
||||
|
||||
<ol>
|
||||
<li>
|
||||
<p>Visit the "Project Settings" page for the project for which you'd like to generate
|
||||
Zulip notifications. Click the "Notifications" tab in the left sidebar,
|
||||
click on "Webhooks" in the resulting menu, and then click on "+ Add Webhook".</p>
|
||||
|
||||
<img class="screenshot" src="/static/images/integrations/semaphore/001.png" />
|
||||
</li>
|
||||
<li>
|
||||
<p> You should now see a form that looks like this: </p>
|
||||
|
||||
<p> <img class="screenshot" style="border:1px solid #000000" src="/static/images/integrations/semaphore/002.png" /> </p>
|
||||
|
||||
<p> Enter the following webhook URI, replacing the bot email address,
|
||||
bot API key, and Zulip stream with the appropriate
|
||||
information. <b>Note:</b> the <code>@</code>-sign in the bot e-mail
|
||||
address must be escaped to <code>%40</code>:</p>
|
||||
|
||||
<p><code>{{ external_uri_scheme }}<font color="#00A26F">semaphore-bot%40example.com</font>:<font color="#00A26F">api_key</font>@{{ external_api_path }}/v1/external/semaphore?stream=<font color="#00A26F">builds</font></code></p>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<p><b>Congratulations! You're done!</b><br /> When you push to Semaphore, the
|
||||
team can see these updates in real time in Zulip:</p>
|
||||
|
||||
<img class="screenshot" src="/static/images/integrations/semaphore/003.png" />
|
||||
</div>
|
||||
|
||||
|
||||
<div id="stash" class="integration-instructions">
|
||||
<h4>Stash</h4>
|
||||
|
||||
|
||||
20
zerver/fixtures/semaphore/semaphore_build.json
Normal file
20
zerver/fixtures/semaphore/semaphore_build.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"branch_name":"master",
|
||||
"branch_url":"https://semaphoreci.com/rishig/semaphore-test/branches/master",
|
||||
"project_name":"knighthood",
|
||||
"project_hash_id":"dff749fa-6acf-467c-85c9-119d63c8af4b",
|
||||
"build_url":"https://semaphoreci.com/donquixote/knighthood/branches/master/builds/314",
|
||||
"build_number":314,
|
||||
"result":"passed",
|
||||
"event":"build",
|
||||
"started_at":"1605-01-16T00:01:58Z",
|
||||
"finished_at":"1605-01-16T00:02:09Z",
|
||||
"commit":{
|
||||
"id":"a490b8d508ebbdab1d77a5c2aefa35ceb2d62daf",
|
||||
"url":"https://github.com/donquixote/knighthood/commit/a490b8d508ebbdab1d77a5c2aefa35ceb2d62daf",
|
||||
"author_name":"Don Quixote",
|
||||
"author_email":"don@lamancha.com",
|
||||
"message":"Create user account for Rocinante :horse:.",
|
||||
"timestamp":"1605-01-16T00:01:41Z"
|
||||
}
|
||||
}
|
||||
25
zerver/fixtures/semaphore/semaphore_deploy.json
Normal file
25
zerver/fixtures/semaphore/semaphore_deploy.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"project_name":"knighthood",
|
||||
"project_hash_id":"dff749fa-6acf-467c-85c9-119d63c8af4b",
|
||||
"server_name":"lamancha-271",
|
||||
"number":17,
|
||||
"event":"deploy",
|
||||
"result":"passed",
|
||||
"created_at":"2016-06-17T00:59:09Z",
|
||||
"updated_at":"2016-06-17T01:00:11Z",
|
||||
"started_at":"2016-06-17T00:59:11Z",
|
||||
"finished_at":"2016-06-17T00:59:21Z",
|
||||
"html_url":"https://semaphoreci.com/donquixote/knighthood/servers/lamancha-271/deploys/17",
|
||||
"build_number":314,
|
||||
"build_html_url":"https://semaphoreci.com/donquixote/knighthood/branches/master/builds/314",
|
||||
"branch_name":"master",
|
||||
"branch_html_url":"https://semaphoreci.com/donquixote/knighthood/branches/master",
|
||||
"commit":{
|
||||
"id":"a490b8d508ebbdab1d77a5c2aefa35ceb2d62daf",
|
||||
"url":"https://github.com/donquixote/knighthood/commit/a490b8d508ebbdab1d77a5c2aefa35ceb2d62daf",
|
||||
"author_name":"Don Quixote",
|
||||
"author_email":"don@lamancha.com",
|
||||
"message":"Create user account for Rocinante :horse:.",
|
||||
"timestamp":"2016-06-16T18:29:08Z"
|
||||
}
|
||||
}
|
||||
@@ -1479,3 +1479,31 @@ class IFTTTHookTests(WebhookTestCase):
|
||||
expected_subject = u"Email sent from email@email.com"
|
||||
expected_message = u"Email subject: Subject"
|
||||
self.send_and_test_stream_message('correct_subject_and_body', expected_subject, expected_message)
|
||||
|
||||
class SemaphoreHookTests(WebhookTestCase):
|
||||
STREAM_NAME = 'semaphore'
|
||||
URL_TEMPLATE = "/api/v1/external/semaphore?stream={stream}&api_key={api_key}"
|
||||
|
||||
# Messages are generated by Semaphore on git push. The subject lines below
|
||||
# contain information on the repo and branch, and the message has links and
|
||||
# details about the build, deploy, server, author, and commit
|
||||
|
||||
def test_semaphore_build(self):
|
||||
# type: () -> None
|
||||
expected_subject = u"knighthood/master" # repo/branch
|
||||
expected_message = u"""[build 314](https://semaphoreci.com/donquixote/knighthood/branches/master/builds/314): passed
|
||||
!avatar(don@lamancha.com) [`a490b8d`](https://github.com/donquixote/knighthood/commit/a490b8d508ebbdab1d77a5c2aefa35ceb2d62daf): Create user account for Rocinante :horse:."""
|
||||
self.send_and_test_stream_message('build', expected_subject, expected_message,
|
||||
content_type="application/x-www-form-urlencoded")
|
||||
|
||||
def test_semaphore_deploy(self):
|
||||
# type: () -> None
|
||||
expected_subject = u"knighthood/master"
|
||||
expected_message = u"""[deploy 17](https://semaphoreci.com/donquixote/knighthood/servers/lamancha-271/deploys/17) of [build 314](https://semaphoreci.com/donquixote/knighthood/branches/master/builds/314) on server lamancha-271: passed
|
||||
!avatar(don@lamancha.com) [`a490b8d`](https://github.com/donquixote/knighthood/commit/a490b8d508ebbdab1d77a5c2aefa35ceb2d62daf): Create user account for Rocinante :horse:."""
|
||||
self.send_and_test_stream_message('deploy', expected_subject, expected_message,
|
||||
content_type="application/x-www-form-urlencoded")
|
||||
|
||||
def get_body(self, fixture_name):
|
||||
# type: (text_type) -> text_type
|
||||
return self.fixture_data("semaphore", fixture_name, file_type="json")
|
||||
|
||||
68
zerver/views/webhooks/semaphore.py
Normal file
68
zerver/views/webhooks/semaphore.py
Normal file
@@ -0,0 +1,68 @@
|
||||
# Webhooks for external integrations.
|
||||
from __future__ import absolute_import
|
||||
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from zerver.models import get_client, get_user_profile_by_email
|
||||
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
|
||||
from zerver.models import UserProfile, Client
|
||||
import ujson
|
||||
|
||||
from six import text_type
|
||||
from typing import Any, Dict
|
||||
|
||||
|
||||
@api_key_only_webhook_view('Semaphore')
|
||||
@has_request_variables
|
||||
def api_semaphore_webhook(request, user_profile, client,
|
||||
payload=REQ(argument_type='body'),
|
||||
stream=REQ(default='builds')):
|
||||
# type: (HttpRequest, UserProfile, Client, Dict[str, Any], str) -> HttpResponse
|
||||
|
||||
# semaphore only gives the last commit, even if there were multiple commits
|
||||
# since the last build
|
||||
try:
|
||||
branch_name = payload["branch_name"]
|
||||
project_name = payload["project_name"]
|
||||
result = payload["result"]
|
||||
event = payload["event"]
|
||||
commit_id = payload["commit"]["id"]
|
||||
commit_url = payload["commit"]["url"]
|
||||
author_email = payload["commit"]["author_email"]
|
||||
message = payload["commit"]["message"]
|
||||
except KeyError as e:
|
||||
return json_error(_("Missing key %s in JSON") % (e.message,))
|
||||
|
||||
if event == "build":
|
||||
try:
|
||||
build_url = payload["build_url"]
|
||||
build_number = payload["build_number"]
|
||||
except KeyError as e:
|
||||
return json_error(_("Missing key %s in JSON") % (e.message,))
|
||||
content = u"[build %s](%s): %s\n" % (build_number, build_url, result)
|
||||
|
||||
elif event == "deploy":
|
||||
try:
|
||||
build_url = payload["build_html_url"]
|
||||
build_number = payload["build_number"]
|
||||
deploy_url = payload["html_url"]
|
||||
deploy_number = payload["number"]
|
||||
server_name = payload["server_name"]
|
||||
except KeyError as e:
|
||||
return json_error(_("Missing key %s in JSON") % (e.message,))
|
||||
content = u"[deploy %s](%s) of [build %s](%s) on server %s: %s\n" % \
|
||||
(deploy_number, deploy_url, build_number, build_url, server_name, result)
|
||||
|
||||
else: # should never get here
|
||||
content = u"%s: %s\n" % (event, result)
|
||||
|
||||
content += "!avatar(%s) [`%s`](%s): %s" % (author_email, commit_id[:7],
|
||||
commit_url, message)
|
||||
subject = u"%s/%s" % (project_name, branch_name)
|
||||
|
||||
check_send_message(user_profile, client, "stream",
|
||||
[stream], subject, content)
|
||||
return json_success()
|
||||
@@ -262,6 +262,7 @@ urls += [
|
||||
url(r'^api/v1/external/pagerduty$', 'zerver.views.webhooks.pagerduty.api_pagerduty_webhook'),
|
||||
url(r'^api/v1/external/pingdom$', 'zerver.views.webhooks.pingdom.api_pingdom_webhook'),
|
||||
url(r'^api/v1/external/pivotal$', 'zerver.views.webhooks.pivotal.api_pivotal_webhook'),
|
||||
url(r'^api/v1/external/semaphore$', 'zerver.views.webhooks.semaphore.api_semaphore_webhook'),
|
||||
url(r'^api/v1/external/stash$', 'zerver.views.webhooks.stash.api_stash_webhook'),
|
||||
url(r'^api/v1/external/taiga$', 'zerver.views.webhooks.taiga.api_taiga_webhook'),
|
||||
url(r'^api/v1/external/teamcity$', 'zerver.views.webhooks.teamcity.api_teamcity_webhook'),
|
||||
|
||||
Reference in New Issue
Block a user