# HG changeset patch # User Daniel Dourvaris # Date 2016-07-13 08:39:54 # Node ID c2778156ed6bca6aca33f1448dd74dc40bda66aa # Parent 94cb44ca227ac7d1e5bc8c11fdec2dd70316eede events: add an event for pull request comments with review status diff --git a/rhodecode/controllers/pullrequests.py b/rhodecode/controllers/pullrequests.py --- a/rhodecode/controllers/pullrequests.py +++ b/rhodecode/controllers/pullrequests.py @@ -32,6 +32,7 @@ from pylons.i18n.translation import _ from sqlalchemy.sql import func from sqlalchemy.sql.expression import or_ +from rhodecode import events from rhodecode.lib import auth, diffs, helpers as h from rhodecode.lib.ext_json import json from rhodecode.lib.base import ( @@ -764,6 +765,8 @@ class PullrequestsController(BaseRepoCon closing_pr=close_pr ) + + if allowed_to_change_status: old_calculated_status = pull_request.calculated_review_status() # get status if set ! @@ -777,6 +780,7 @@ class PullrequestsController(BaseRepoCon ) Session().flush() + events.trigger(events.PullRequestCommentEvent(pull_request, comm)) # we now calculate the status of pull request, and based on that # calculation we set the commits status calculated_status = pull_request.calculated_review_status() diff --git a/rhodecode/events/__init__.py b/rhodecode/events/__init__.py --- a/rhodecode/events/__init__.py +++ b/rhodecode/events/__init__.py @@ -64,6 +64,7 @@ from rhodecode.events.pullrequest import PullRequestEvent, PullRequestCreateEvent, PullRequestUpdateEvent, + PullRequestCommentEvent, PullRequestReviewEvent, PullRequestMergeEvent, PullRequestCloseEvent, diff --git a/rhodecode/events/pullrequest.py b/rhodecode/events/pullrequest.py --- a/rhodecode/events/pullrequest.py +++ b/rhodecode/events/pullrequest.py @@ -44,7 +44,8 @@ class PullRequestEvent(RepoEvent): 'title': self.pullrequest.title, 'issues': issues, 'pull_request_id': self.pullrequest.pull_request_id, - 'url': PullRequestModel().get_url(self.pullrequest) + 'url': PullRequestModel().get_url(self.pullrequest), + 'status': self.pullrequest.calculated_review_status(), } }) return data @@ -71,10 +72,19 @@ class PullRequestCloseEvent(PullRequestE class PullRequestUpdateEvent(PullRequestEvent): """ An instance of this class is emitted as an :term:`event` after a pull - request is updated. + request's commits have been updated. """ name = 'pullrequest-update' - display_name = lazy_ugettext('pullrequest updated') + display_name = lazy_ugettext('pullrequest commits updated') + + +class PullRequestReviewEvent(PullRequestEvent): + """ + An instance of this class is emitted as an :term:`event` after a pull + request review has changed. + """ + name = 'pullrequest-review' + display_name = lazy_ugettext('pullrequest review changed') class PullRequestMergeEvent(PullRequestEvent): @@ -86,12 +96,31 @@ class PullRequestMergeEvent(PullRequestE display_name = lazy_ugettext('pullrequest merged') -class PullRequestReviewEvent(PullRequestEvent): +class PullRequestCommentEvent(PullRequestEvent): """ An instance of this class is emitted as an :term:`event` after a pull - request is reviewed. + request comment is created. """ - name = 'pullrequest-review' - display_name = lazy_ugettext('pullrequest reviewed') + name = 'pullrequest-comment' + display_name = lazy_ugettext('pullrequest commented') + + def __init__(self, pullrequest, comment): + super(PullRequestCommentEvent, self).__init__(pullrequest) + self.comment = comment + + def as_dict(self): + from rhodecode.model.comment import ChangesetCommentsModel + data = super(PullRequestCommentEvent, self).as_dict() + status = None + if self.comment.status_change: + status = self.comment.status_change[0].status + data.update({ + 'comment': { + 'status': status, + 'text': self.comment.text, + 'url': ChangesetCommentsModel().get_url(self.comment) + } + }) + return data diff --git a/rhodecode/integrations/types/slack.py b/rhodecode/integrations/types/slack.py --- a/rhodecode/integrations/types/slack.py +++ b/rhodecode/integrations/types/slack.py @@ -24,6 +24,7 @@ import re import logging import requests import colander +import textwrap from celery.task import task from mako.template import Template @@ -105,6 +106,7 @@ class SlackIntegrationType(IntegrationTy events.PullRequestCloseEvent, events.PullRequestMergeEvent, events.PullRequestUpdateEvent, + events.PullRequestCommentEvent, events.PullRequestReviewEvent, events.PullRequestCreateEvent, events.RepoPushEvent, @@ -127,7 +129,11 @@ class SlackIntegrationType(IntegrationTy log.debug('handling slack event for %s' % event.name) - if isinstance(event, events.PullRequestEvent): + if isinstance(event, events.PullRequestCommentEvent): + text = self.format_pull_request_comment_event(event, data) + elif isinstance(event, events.PullRequestReviewEvent): + text = self.format_pull_request_review_event(event, data) + elif isinstance(event, events.PullRequestEvent): text = self.format_pull_request_event(event, data) elif isinstance(event, events.RepoPushEvent): text = self.format_repo_push_event(data) @@ -150,16 +156,55 @@ class SlackIntegrationType(IntegrationTy )) return schema + def format_pull_request_comment_event(self, event, data): + comment_text = data['comment']['text'] + if len(comment_text) > 200: + comment_text = '<{comment_url}|{comment_text}...>'.format( + comment_text=comment_text[:200], + comment_url=data['comment']['url'], + ) + + comment_status = '' + if data['comment']['status']: + comment_status = '[{}]: '.format(data['comment']['status']) + + 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 + ) + ) + + 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'], + ) + ) + def format_pull_request_event(self, event, data): action = { events.PullRequestCloseEvent: 'closed', events.PullRequestMergeEvent: 'merged', events.PullRequestUpdateEvent: 'updated', - events.PullRequestReviewEvent: 'reviewed', events.PullRequestCreateEvent: 'created', - }.get(event.__class__, '') + }.get(event.__class__, str(event.__class__)) - return ('Pull request <{url}|#{number}> ({title}) ' + return ('Pull request <{url}|#{number}> - {title} ' '{action} by {user}').format( user=data['actor']['username'], number=data['pullrequest']['pull_request_id'], diff --git a/rhodecode/model/comment.py b/rhodecode/model/comment.py --- a/rhodecode/model/comment.py +++ b/rhodecode/model/comment.py @@ -156,12 +156,7 @@ class ChangesetCommentsModel(BaseModel): cs_author = repo.user recipients += [cs_author] - commit_comment_url = h.url( - 'changeset_home', - repo_name=repo.repo_name, - revision=commit_obj.raw_id, - anchor='comment-%s' % comment.comment_id, - qualified=True,) + commit_comment_url = self.get_url(comment) target_repo_url = h.link_to( repo.repo_name, @@ -271,6 +266,23 @@ class ChangesetCommentsModel(BaseModel): q = q.order_by(ChangesetComment.created_on) return q.all() + def get_url(self, comment): + comment = self.__get_commit_comment(comment) + if comment.pull_request: + return h.url( + 'pullrequest_show', + repo_name=comment.pull_request.target_repo.repo_name, + pull_request_id=comment.pull_request.pull_request_id, + anchor='comment-%s' % comment.comment_id, + qualified=True,) + else: + return h.url( + 'changeset_home', + repo_name=comment.repo.repo_name, + revision=comment.revision, + anchor='comment-%s' % comment.comment_id, + qualified=True,) + def get_comments(self, repo_id, revision=None, pull_request=None): """ Gets main comments based on revision or pull_request_id diff --git a/rhodecode/tests/events/test_pullrequest.py b/rhodecode/tests/events/test_pullrequest.py --- a/rhodecode/tests/events/test_pullrequest.py +++ b/rhodecode/tests/events/test_pullrequest.py @@ -22,10 +22,12 @@ import pytest from rhodecode.tests.events.conftest import EventCatcher +from rhodecode.model.comment import ChangesetCommentsModel from rhodecode.model.pull_request import PullRequestModel from rhodecode.events import ( PullRequestCreateEvent, PullRequestUpdateEvent, + PullRequestCommentEvent, PullRequestReviewEvent, PullRequestMergeEvent, PullRequestCloseEvent, @@ -56,6 +58,19 @@ def test_create_pull_request_events(pr_u assert PullRequestCreateEvent in event_catcher.events_types +@pytest.mark.backends("git", "hg") +def test_pullrequest_comment_events_serialized(pr_util): + pr = pr_util.create_pull_request() + comment = ChangesetCommentsModel().get_comments( + pr.target_repo.repo_id, pull_request=pr)[0] + event = PullRequestCommentEvent(pr, comment) + data = event.as_dict() + assert data['name'] == PullRequestCommentEvent.name + assert data['repo']['repo_name'] == pr.target_repo.repo_name + assert data['pullrequest']['pull_request_id'] == pr.pull_request_id + assert data['pullrequest']['url'] + assert data['comment']['text'] == comment.text + @pytest.mark.backends("git", "hg") def test_close_pull_request_events(pr_util, user_admin):