Add Slack notification support
This commit is contained in:
parent
32ea1d194f
commit
6ec89bb179
6 changed files with 104 additions and 0 deletions
|
@ -5,6 +5,7 @@ import tarfile
|
||||||
import base64
|
import base64
|
||||||
import json
|
import json
|
||||||
import requests
|
import requests
|
||||||
|
import re
|
||||||
|
|
||||||
from flask.ext.mail import Message
|
from flask.ext.mail import Message
|
||||||
from app import mail, app, get_app_url
|
from app import mail, app, get_app_url
|
||||||
|
@ -302,3 +303,80 @@ class HipchatMethod(NotificationMethod):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
class SlackMethod(NotificationMethod):
|
||||||
|
""" Method for sending notifications to Slack via the API:
|
||||||
|
https://api.slack.com/docs/attachments
|
||||||
|
"""
|
||||||
|
@classmethod
|
||||||
|
def method_name(cls):
|
||||||
|
return 'slack'
|
||||||
|
|
||||||
|
def validate(self, repository, config_data):
|
||||||
|
if not config_data.get('token', ''):
|
||||||
|
raise CannotValidateNotificationMethodException('Missing Slack Token')
|
||||||
|
|
||||||
|
if not config_data.get('subdomain', '').isalnum():
|
||||||
|
raise CannotValidateNotificationMethodException('Missing Slack Subdomain Name')
|
||||||
|
|
||||||
|
def formatForSlack(self, message):
|
||||||
|
message = message.replace('\n', '')
|
||||||
|
message = re.sub(r'\s+', ' ', message)
|
||||||
|
message = message.replace('<br>', '\n')
|
||||||
|
message = re.sub(r'<a href="(.+)">(.+)</a>', '<\\1|\\2>', message)
|
||||||
|
return message
|
||||||
|
|
||||||
|
def perform(self, notification, event_handler, notification_data):
|
||||||
|
config_data = json.loads(notification.config_json)
|
||||||
|
|
||||||
|
token = config_data.get('token', '')
|
||||||
|
subdomain = config_data.get('subdomain', '')
|
||||||
|
|
||||||
|
if not token or not subdomain:
|
||||||
|
return False
|
||||||
|
|
||||||
|
owner = model.get_user(notification.repository.namespace)
|
||||||
|
if not owner:
|
||||||
|
# Something went wrong.
|
||||||
|
return False
|
||||||
|
|
||||||
|
url = 'https://%s.slack.com/services/hooks/incoming-webhook?token=%s' % (subdomain, token)
|
||||||
|
|
||||||
|
level = event_handler.get_level(notification_data['event_data'], notification_data)
|
||||||
|
color = {
|
||||||
|
'info': '#ffffff',
|
||||||
|
'warning': 'warning',
|
||||||
|
'error': 'danger',
|
||||||
|
'primary': 'good'
|
||||||
|
}.get(level, '#ffffff')
|
||||||
|
|
||||||
|
summary = event_handler.get_summary(notification_data['event_data'], notification_data)
|
||||||
|
message = event_handler.get_message(notification_data['event_data'], notification_data)
|
||||||
|
|
||||||
|
headers = {'Content-type': 'application/json'}
|
||||||
|
payload = {
|
||||||
|
'text': summary,
|
||||||
|
'username': 'quayiobot',
|
||||||
|
'attachments': [
|
||||||
|
{
|
||||||
|
'fallback': summary,
|
||||||
|
'text': self.formatForSlack(message),
|
||||||
|
'color': color
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
resp = requests.post(url, data=json.dumps(payload), headers=headers)
|
||||||
|
if resp.status_code/100 != 2:
|
||||||
|
logger.error('%s response for Slack to url: %s' % (resp.status_code,
|
||||||
|
url))
|
||||||
|
logger.error(resp.content)
|
||||||
|
return False
|
||||||
|
|
||||||
|
except requests.exceptions.RequestException as ex:
|
||||||
|
logger.exception('Slack method was unable to be sent: %s' % ex.message)
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
|
@ -253,6 +253,7 @@ def initialize_database():
|
||||||
|
|
||||||
ExternalNotificationMethod.create(name='flowdock')
|
ExternalNotificationMethod.create(name='flowdock')
|
||||||
ExternalNotificationMethod.create(name='hipchat')
|
ExternalNotificationMethod.create(name='hipchat')
|
||||||
|
ExternalNotificationMethod.create(name='slack')
|
||||||
|
|
||||||
NotificationKind.create(name='repo_push')
|
NotificationKind.create(name='repo_push')
|
||||||
NotificationKind.create(name='build_queued')
|
NotificationKind.create(name='build_queued')
|
||||||
|
|
|
@ -4573,6 +4573,13 @@ i.hipchat-icon {
|
||||||
height: 16px;
|
height: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i.slack-icon {
|
||||||
|
background-image: url(/static/img/slack.ico);
|
||||||
|
background-size: 16px;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
.external-notification-view-element {
|
.external-notification-view-element {
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
padding: 6px;
|
padding: 6px;
|
||||||
|
|
BIN
static/img/slack.ico
Normal file
BIN
static/img/slack.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
|
@ -1141,6 +1141,24 @@ quayApp = angular.module('quay', quayDependencies, function($provide, cfpLoading
|
||||||
'title': 'Notification Token'
|
'title': 'Notification Token'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'id': 'slack',
|
||||||
|
'title': 'Slack Room Notification',
|
||||||
|
'icon': 'slack-icon',
|
||||||
|
'fields': [
|
||||||
|
{
|
||||||
|
'name': 'subdomain',
|
||||||
|
'type': 'string',
|
||||||
|
'title': 'Slack Subdomain'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'name': 'token',
|
||||||
|
'type': 'string',
|
||||||
|
'title': 'Token',
|
||||||
|
'help_url': 'https://{subdomain}.slack.com/services/new/outgoing-webhook'
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
Binary file not shown.
Reference in a new issue