slack: updated slack integration to use the attachements for nicer formatting.
This commit is contained in:
parent
dae4affd34
commit
4392d7803f
3 changed files with 146 additions and 72 deletions
|
|
@ -128,6 +128,9 @@ class PullRequestCommentEvent(PullRequestEvent):
|
|||
'comment': {
|
||||
'status': status,
|
||||
'text': self.comment.text,
|
||||
'type': self.comment.comment_type,
|
||||
'file': self.comment.f_path,
|
||||
'line': self.comment.line_no,
|
||||
'url': CommentsModel().get_url(self.comment)
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -34,10 +34,9 @@ def _commits_as_dict(commit_ids, repos):
|
|||
:param repos: list of repos to check
|
||||
"""
|
||||
from rhodecode.lib.utils2 import extract_mentioned_users
|
||||
from rhodecode.model.db import Repository
|
||||
from rhodecode.lib import helpers as h
|
||||
from rhodecode.lib.helpers import process_patterns
|
||||
from rhodecode.lib.helpers import urlify_commit_message
|
||||
from rhodecode.lib.helpers import (
|
||||
urlify_commit_message, process_patterns, chop_at_smart)
|
||||
|
||||
if not repos:
|
||||
raise Exception('no repo defined')
|
||||
|
|
@ -78,14 +77,15 @@ def _commits_as_dict(commit_ids, repos):
|
|||
cs_data['issues'] = issues_data
|
||||
cs_data['message_html'] = urlify_commit_message(cs_data['message'],
|
||||
repo.repo_name)
|
||||
cs_data['message_html_title'] = chop_at_smart(cs_data['message'], '\n', suffix_if_chopped='...')
|
||||
commits.append(cs_data)
|
||||
|
||||
needed_commits.remove(commit_id)
|
||||
|
||||
except Exception as e:
|
||||
log.exception(e)
|
||||
# we don't send any commits when crash happens, only full list matters
|
||||
# we short circuit then.
|
||||
# we don't send any commits when crash happens, only full list
|
||||
# matters we short circuit then.
|
||||
return []
|
||||
|
||||
missing_commits = set(commit_ids) - set(c['raw_id'] for c in commits)
|
||||
|
|
|
|||
|
|
@ -19,12 +19,14 @@
|
|||
# and proprietary license terms, please see https://rhodecode.com/licenses/
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import deform
|
||||
import re
|
||||
import time
|
||||
import textwrap
|
||||
import logging
|
||||
|
||||
import deform
|
||||
import requests
|
||||
import colander
|
||||
import textwrap
|
||||
from celery.task import task
|
||||
from mako.template import Template
|
||||
|
||||
|
|
@ -85,17 +87,6 @@ class SlackSettingsSchema(colander.Schema):
|
|||
)
|
||||
|
||||
|
||||
repo_push_template = Template(r'''
|
||||
*${data['actor']['username']}* pushed to repo <${data['repo']['url']}|${data['repo']['repo_name']}>:
|
||||
%for branch, branch_commits in branches_commits.items():
|
||||
branch: <${branch_commits['branch']['url']}|${branch_commits['branch']['name']}>
|
||||
%for commit in branch_commits['commits']:
|
||||
> <${commit['url']}|${commit['short_id']}> - ${commit['message_html']|html_to_slack_links}
|
||||
%endfor
|
||||
%endfor
|
||||
''')
|
||||
|
||||
|
||||
class SlackIntegrationType(IntegrationTypeBase):
|
||||
key = 'slack'
|
||||
display_name = _('Slack')
|
||||
|
|
@ -124,25 +115,31 @@ class SlackIntegrationType(IntegrationTypeBase):
|
|||
|
||||
data = event.as_dict()
|
||||
|
||||
# defaults
|
||||
title = '*%s* caused a *%s* event' % (
|
||||
data['actor']['username'], event.name)
|
||||
text = '*%s* caused a *%s* event' % (
|
||||
data['actor']['username'], event.name)
|
||||
fields = None
|
||||
overrides = None
|
||||
|
||||
log.debug('handling slack event for %s' % event.name)
|
||||
|
||||
if isinstance(event, events.PullRequestCommentEvent):
|
||||
text = self.format_pull_request_comment_event(event, data)
|
||||
(title, text, fields, overrides) \
|
||||
= self.format_pull_request_comment_event(event, data)
|
||||
elif isinstance(event, events.PullRequestReviewEvent):
|
||||
text = self.format_pull_request_review_event(event, data)
|
||||
title, text = self.format_pull_request_review_event(event, data)
|
||||
elif isinstance(event, events.PullRequestEvent):
|
||||
text = self.format_pull_request_event(event, data)
|
||||
title, text = self.format_pull_request_event(event, data)
|
||||
elif isinstance(event, events.RepoPushEvent):
|
||||
text = self.format_repo_push_event(data)
|
||||
title, text = self.format_repo_push_event(data)
|
||||
elif isinstance(event, events.RepoCreateEvent):
|
||||
text = self.format_repo_create_event(data)
|
||||
title, text = self.format_repo_create_event(data)
|
||||
else:
|
||||
log.error('unhandled event type: %r' % event)
|
||||
|
||||
run_task(post_text_to_slack, self.settings, text)
|
||||
run_task(post_text_to_slack, self.settings, title, text, fields, overrides)
|
||||
|
||||
def settings_schema(self):
|
||||
schema = SlackSettingsSchema()
|
||||
|
|
@ -167,38 +164,61 @@ class SlackIntegrationType(IntegrationTypeBase):
|
|||
comment_url=data['comment']['url'],
|
||||
)
|
||||
|
||||
comment_status = ''
|
||||
if data['comment']['status']:
|
||||
comment_status = '[{}]: '.format(data['comment']['status'])
|
||||
fields = None
|
||||
overrides = None
|
||||
status_text = None
|
||||
|
||||
return (textwrap.dedent(
|
||||
'''
|
||||
*{user}* commented on pull request <{pr_url}|#{number}> - {pr_title}:
|
||||
>>> {comment_status}{comment_text}
|
||||
''').format(
|
||||
comment_status=comment_status,
|
||||
user=data['actor']['username'],
|
||||
number=data['pullrequest']['pull_request_id'],
|
||||
pr_url=data['pullrequest']['url'],
|
||||
pr_status=data['pullrequest']['status'],
|
||||
pr_title=data['pullrequest']['title'],
|
||||
comment_text=comment_text
|
||||
)
|
||||
)
|
||||
if data['comment']['status']:
|
||||
status_color = {
|
||||
'approved': '#0ac878',
|
||||
'rejected': '#e85e4d'}.get(data['comment']['status'])
|
||||
|
||||
if status_color:
|
||||
overrides = {"color": status_color}
|
||||
|
||||
status_text = data['comment']['status']
|
||||
|
||||
if data['comment']['file']:
|
||||
fields = [
|
||||
{
|
||||
"title": "file",
|
||||
"value": data['comment']['file']
|
||||
},
|
||||
{
|
||||
"title": "line",
|
||||
"value": data['comment']['line']
|
||||
}
|
||||
]
|
||||
|
||||
title = Template(textwrap.dedent(r'''
|
||||
*${data['actor']['username']}* left ${data['comment']['type']} on pull request <${data['pullrequest']['url']}|#${data['pullrequest']['pull_request_id']}>:
|
||||
''')).render(data=data, comment=event.comment)
|
||||
|
||||
text = Template(textwrap.dedent(r'''
|
||||
*pull request title*: ${pr_title}
|
||||
% if status_text:
|
||||
*submitted status*: `${status_text}`
|
||||
% endif
|
||||
>>> ${comment_text}
|
||||
''')).render(comment_text=comment_text,
|
||||
pr_title=data['pullrequest']['title'],
|
||||
status_text=status_text)
|
||||
|
||||
return title, text, fields, overrides
|
||||
|
||||
def format_pull_request_review_event(self, event, data):
|
||||
return (textwrap.dedent(
|
||||
'''
|
||||
Status changed to {pr_status} for pull request <{pr_url}|#{number}> - {pr_title}
|
||||
''').format(
|
||||
user=data['actor']['username'],
|
||||
number=data['pullrequest']['pull_request_id'],
|
||||
pr_url=data['pullrequest']['url'],
|
||||
pr_status=data['pullrequest']['status'],
|
||||
pr_title=data['pullrequest']['title'],
|
||||
)
|
||||
title = Template(textwrap.dedent(r'''
|
||||
*${data['actor']['username']}* changed status of pull request <${data['pullrequest']['url']}|#${data['pullrequest']['pull_request_id']} to `${data['pullrequest']['status']}`>:
|
||||
''')).render(data=data)
|
||||
|
||||
text = Template(textwrap.dedent(r'''
|
||||
*pull request title*: ${pr_title}
|
||||
''')).render(
|
||||
pr_title=data['pullrequest']['title'],
|
||||
)
|
||||
|
||||
return title, text
|
||||
|
||||
def format_pull_request_event(self, event, data):
|
||||
action = {
|
||||
events.PullRequestCloseEvent: 'closed',
|
||||
|
|
@ -207,15 +227,22 @@ class SlackIntegrationType(IntegrationTypeBase):
|
|||
events.PullRequestCreateEvent: 'created',
|
||||
}.get(event.__class__, str(event.__class__))
|
||||
|
||||
return ('Pull request <{url}|#{number}> - {title} '
|
||||
'`{action}` by *{user}*').format(
|
||||
user=data['actor']['username'],
|
||||
number=data['pullrequest']['pull_request_id'],
|
||||
url=data['pullrequest']['url'],
|
||||
title=data['pullrequest']['title'],
|
||||
action=action
|
||||
title = Template(textwrap.dedent(r'''
|
||||
*${data['actor']['username']}* `${action}` pull request <${data['pullrequest']['url']}|#${data['pullrequest']['pull_request_id']}>:
|
||||
''')).render(data=data, action=action)
|
||||
|
||||
text = Template(textwrap.dedent(r'''
|
||||
*pull request title*: ${pr_title}
|
||||
%if data['pullrequest']['commits']:
|
||||
*commits*: ${len(data['pullrequest']['commits'])}
|
||||
%endif
|
||||
''')).render(
|
||||
pr_title=data['pullrequest']['title'],
|
||||
data=data
|
||||
)
|
||||
|
||||
return title, text
|
||||
|
||||
def format_repo_push_event(self, data):
|
||||
branch_data = {branch['name']: branch
|
||||
for branch in data['push']['branches']}
|
||||
|
|
@ -230,20 +257,38 @@ class SlackIntegrationType(IntegrationTypeBase):
|
|||
branch_commits = branches_commits[commit['branch']]
|
||||
branch_commits['commits'].append(commit)
|
||||
|
||||
result = repo_push_template.render(
|
||||
title = Template(r'''
|
||||
*${data['actor']['username']}* pushed to repo <${data['repo']['url']}|${data['repo']['repo_name']}>:
|
||||
''').render(data=data)
|
||||
|
||||
repo_push_template = Template(textwrap.dedent(r'''
|
||||
%for branch, branch_commits in branches_commits.items():
|
||||
branch: <${branch_commits['branch']['url']}|${branch_commits['branch']['name']}>
|
||||
%for commit in branch_commits['commits']:
|
||||
`<${commit['url']}|${commit['short_id']}>` - ${commit['message_html_title']|html_to_slack_links}
|
||||
%endfor
|
||||
%endfor
|
||||
'''))
|
||||
|
||||
text = repo_push_template.render(
|
||||
data=data,
|
||||
branches_commits=branches_commits,
|
||||
html_to_slack_links=html_to_slack_links,
|
||||
)
|
||||
return result
|
||||
|
||||
return title, text
|
||||
|
||||
def format_repo_create_event(self, data):
|
||||
return '<{}|{}> ({}) repository created by *{}*'.format(
|
||||
data['repo']['url'],
|
||||
data['repo']['repo_name'],
|
||||
data['repo']['repo_type'],
|
||||
data['actor']['username'],
|
||||
)
|
||||
title = Template(r'''
|
||||
*${data['actor']['username']}* created new repository ${data['repo']['repo_name']}:
|
||||
''').render(data=data)
|
||||
|
||||
text = Template(textwrap.dedent(r'''
|
||||
repo_url: ${data['repo']['url']}
|
||||
repo_type: ${data['repo']['repo_type']}
|
||||
''')).render(data=data)
|
||||
|
||||
return title, text
|
||||
|
||||
|
||||
def html_to_slack_links(message):
|
||||
|
|
@ -252,12 +297,38 @@ def html_to_slack_links(message):
|
|||
|
||||
|
||||
@task(ignore_result=True)
|
||||
def post_text_to_slack(settings, text):
|
||||
log.debug('sending %s to slack %s' % (text, settings['service']))
|
||||
resp = requests.post(settings['service'], json={
|
||||
def post_text_to_slack(settings, title, text, fields=None, overrides=None):
|
||||
log.debug('sending %s (%s) to slack %s' % (
|
||||
title, text, settings['service']))
|
||||
|
||||
fields = fields or []
|
||||
overrides = overrides or {}
|
||||
|
||||
message_data = {
|
||||
"fallback": text,
|
||||
"color": "#427cc9",
|
||||
"pretext": title,
|
||||
#"author_name": "Bobby Tables",
|
||||
#"author_link": "http://flickr.com/bobby/",
|
||||
#"author_icon": "http://flickr.com/icons/bobby.jpg",
|
||||
#"title": "Slack API Documentation",
|
||||
#"title_link": "https://api.slack.com/",
|
||||
"text": text,
|
||||
"fields": fields,
|
||||
#"image_url": "http://my-website.com/path/to/image.jpg",
|
||||
#"thumb_url": "http://example.com/path/to/thumb.png",
|
||||
"footer": "RhodeCode",
|
||||
#"footer_icon": "",
|
||||
"ts": time.time(),
|
||||
"mrkdwn_in": ["pretext", "text"]
|
||||
}
|
||||
message_data.update(overrides)
|
||||
json_message = {
|
||||
"icon_emoji": settings.get('icon_emoji', ':studio_microphone:'),
|
||||
"channel": settings.get('channel', ''),
|
||||
"username": settings.get('username', 'Rhodecode'),
|
||||
"text": text,
|
||||
"icon_emoji": settings.get('icon_emoji', ':studio_microphone:')
|
||||
})
|
||||
"attachments": [message_data]
|
||||
}
|
||||
|
||||
resp = requests.post(settings['service'], json=json_message)
|
||||
resp.raise_for_status() # raise exception on a failed request
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue