comments: added new events for comment editing to handle them in integrations.

This commit is contained in:
Marcin Kuzminski 2020-07-13 11:18:28 +02:00
parent 7c55d3dab0
commit 74e96ea4b4
15 changed files with 231 additions and 7 deletions

View file

@ -48,6 +48,7 @@ from rhodecode.model.db import (
Session, ChangesetStatus, RepositoryField, Repository, RepoGroup,
ChangesetComment)
from rhodecode.model.permission import PermissionModel
from rhodecode.model.pull_request import PullRequestModel
from rhodecode.model.repo import RepoModel
from rhodecode.model.scm import ScmModel, RepoList
from rhodecode.model.settings import SettingsModel, VcsSettingsModel
@ -1869,6 +1870,20 @@ def edit_comment(request, apiuser, message, comment_id, version,
raise JSONRPCError(
"comment ({}) can't be changed with empty string".format(comment_id)
)
if comment.pull_request:
pull_request = comment.pull_request
PullRequestModel().trigger_pull_request_hook(
pull_request, apiuser, 'comment_edit',
data={'comment': comment})
else:
db_repo = comment.repo
commit_id = comment.revision
commit = db_repo.get_commit(commit_id)
CommentsModel().trigger_commit_comment_hook(
db_repo, apiuser, 'edit',
data={'comment': comment, 'commit': commit})
data = {
'comment': comment,
'version': comment_history.version if comment_history else None,

View file

@ -649,6 +649,12 @@ class RepoCommitsView(RepoAppView):
if not comment_history:
raise HTTPNotFound()
commit_id = self.request.matchdict['commit_id']
commit = self.db_repo.get_commit(commit_id)
CommentsModel().trigger_commit_comment_hook(
self.db_repo, self._rhodecode_user, 'edit',
data={'comment': comment, 'commit': commit})
Session().commit()
return {
'comment_history_id': comment_history.comment_history_id,

View file

@ -1611,6 +1611,11 @@ class RepoPullRequestsView(RepoAppView, DataGridAppView):
raise HTTPNotFound()
Session().commit()
PullRequestModel().trigger_pull_request_hook(
pull_request, self._rhodecode_user, 'comment_edit',
data={'comment': comment})
return {
'comment_history_id': comment_history.comment_history_id,
'comment_id': comment.comment_id,

View file

@ -53,7 +53,8 @@ from rhodecode.events.user import ( # pragma: no cover
)
from rhodecode.events.repo import ( # pragma: no cover
RepoEvent, RepoCommitCommentEvent,
RepoEvent,
RepoCommitCommentEvent, RepoCommitCommentEditEvent,
RepoPreCreateEvent, RepoCreateEvent,
RepoPreDeleteEvent, RepoDeleteEvent,
RepoPrePushEvent, RepoPushEvent,
@ -72,8 +73,8 @@ from rhodecode.events.pullrequest import ( # pragma: no cover
PullRequestCreateEvent,
PullRequestUpdateEvent,
PullRequestCommentEvent,
PullRequestCommentEditEvent,
PullRequestReviewEvent,
PullRequestMergeEvent,
PullRequestCloseEvent,
PullRequestCommentEvent,
)

View file

@ -19,8 +19,7 @@
import logging
from rhodecode.translation import lazy_ugettext
from rhodecode.events.repo import (
RepoEvent, _commits_as_dict, _issues_as_dict)
from rhodecode.events.repo import (RepoEvent, _commits_as_dict, _issues_as_dict)
log = logging.getLogger(__name__)
@ -155,6 +154,46 @@ class PullRequestCommentEvent(PullRequestEvent):
'type': self.comment.comment_type,
'file': self.comment.f_path,
'line': self.comment.line_no,
'version': self.comment.last_version,
'url': CommentsModel().get_url(
self.comment, request=self.request),
'permalink_url': CommentsModel().get_url(
self.comment, request=self.request, permalink=True),
}
})
return data
class PullRequestCommentEditEvent(PullRequestEvent):
"""
An instance of this class is emitted as an :term:`event` after a pull
request comment is edited.
"""
name = 'pullrequest-comment-edit'
display_name = lazy_ugettext('pullrequest comment edited')
description = lazy_ugettext('Event triggered after a comment was edited on a code '
'in the pull request')
def __init__(self, pullrequest, comment):
super(PullRequestCommentEditEvent, self).__init__(pullrequest)
self.comment = comment
def as_dict(self):
from rhodecode.model.comment import CommentsModel
data = super(PullRequestCommentEditEvent, 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,
'type': self.comment.comment_type,
'file': self.comment.f_path,
'line': self.comment.line_no,
'version': self.comment.last_version,
'url': CommentsModel().get_url(
self.comment, request=self.request),
'permalink_url': CommentsModel().get_url(

View file

@ -211,6 +211,42 @@ class RepoCommitCommentEvent(RepoEvent):
'comment_type': self.comment.comment_type,
'comment_f_path': self.comment.f_path,
'comment_line_no': self.comment.line_no,
'comment_version': self.comment.last_version,
}
return data
class RepoCommitCommentEditEvent(RepoEvent):
"""
An instance of this class is emitted as an :term:`event` after a comment is edited
on repository commit.
"""
name = 'repo-commit-edit-comment'
display_name = lazy_ugettext('repository commit edit comment')
description = lazy_ugettext('Event triggered after a comment was edited '
'on commit inside a repository')
def __init__(self, repo, commit, comment):
super(RepoCommitCommentEditEvent, self).__init__(repo)
self.commit = commit
self.comment = comment
def as_dict(self):
data = super(RepoCommitCommentEditEvent, self).as_dict()
data['commit'] = {
'commit_id': self.commit.raw_id,
'commit_message': self.commit.message,
'commit_branch': self.commit.branch,
}
data['comment'] = {
'comment_id': self.comment.comment_id,
'comment_text': self.comment.text,
'comment_type': self.comment.comment_type,
'comment_f_path': self.comment.f_path,
'comment_line_no': self.comment.line_no,
'comment_version': self.comment.last_version,
}
return data

View file

@ -331,6 +331,26 @@ class WebhookDataHandler(CommitParsingDataHandler):
return [(url, self.headers, data)]
def repo_commit_comment_edit_handler(self, event, data):
url = self.get_base_parsed_template(data)
log.debug('register %s call(%s) to url %s', self.name, event, url)
comment_vars = [
('commit_comment_id', data['comment']['comment_id']),
('commit_comment_text', data['comment']['comment_text']),
('commit_comment_type', data['comment']['comment_type']),
('commit_comment_f_path', data['comment']['comment_f_path']),
('commit_comment_line_no', data['comment']['comment_line_no']),
('commit_comment_commit_id', data['commit']['commit_id']),
('commit_comment_commit_branch', data['commit']['commit_branch']),
('commit_comment_commit_message', data['commit']['commit_message']),
]
for k, v in comment_vars:
url = UrlTmpl(url).safe_substitute(**{k: v})
return [(url, self.headers, data)]
def repo_create_event_handler(self, event, data):
url = self.get_base_parsed_template(data)
log.debug('register %s call(%s) to url %s', self.name, event, url)
@ -360,6 +380,8 @@ class WebhookDataHandler(CommitParsingDataHandler):
return self.repo_create_event_handler(event, data)
elif isinstance(event, events.RepoCommitCommentEvent):
return self.repo_commit_comment_handler(event, data)
elif isinstance(event, events.RepoCommitCommentEditEvent):
return self.repo_commit_comment_edit_handler(event, data)
elif isinstance(event, events.PullRequestEvent):
return self.pull_request_event_handler(event, data)
else:

View file

@ -133,6 +133,8 @@ class HipchatIntegrationType(IntegrationTypeBase, CommitParsingDataHandler):
if isinstance(event, events.PullRequestCommentEvent):
text = self.format_pull_request_comment_event(event, data)
elif isinstance(event, events.PullRequestCommentEditEvent):
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):

View file

@ -157,6 +157,9 @@ class SlackIntegrationType(IntegrationTypeBase, CommitParsingDataHandler):
if isinstance(event, events.PullRequestCommentEvent):
(title, text, fields, overrides) \
= self.format_pull_request_comment_event(event, data)
elif isinstance(event, events.PullRequestCommentEditEvent):
(title, text, fields, overrides) \
= self.format_pull_request_comment_event(event, data)
elif isinstance(event, events.PullRequestReviewEvent):
title, text = self.format_pull_request_review_event(event, data)
elif isinstance(event, events.PullRequestEvent):

View file

@ -144,11 +144,13 @@ class WebhookIntegrationType(IntegrationTypeBase):
events.PullRequestMergeEvent,
events.PullRequestUpdateEvent,
events.PullRequestCommentEvent,
events.PullRequestCommentEditEvent,
events.PullRequestReviewEvent,
events.PullRequestCreateEvent,
events.RepoPushEvent,
events.RepoCreateEvent,
events.RepoCommitCommentEvent,
events.RepoCommitCommentEditEvent,
]
def settings_schema(self):

View file

@ -97,6 +97,34 @@ def trigger_comment_commit_hooks(username, repo_name, repo_type, repo, data=None
hooks_base.log_comment_commit_repository(**extras)
def trigger_comment_commit_edit_hooks(username, repo_name, repo_type, repo, data=None):
"""
Triggers when a comment is edited on a commit
:param username: username who edits the comment
:param repo_name: name of target repo
:param repo_type: the type of SCM target repo
:param repo: the repo object we trigger the event for
:param data: extra data for specific events e.g {'comment': comment_obj, 'commit': commit_obj}
"""
if not _supports_repo_type(repo_type):
return
extras = _get_vcs_operation_context(username, repo_name, repo_type, 'comment_commit')
comment = data['comment']
commit = data['commit']
events.trigger(events.RepoCommitCommentEditEvent(repo, commit, comment))
extras.update(repo.get_dict())
extras.commit = commit.serialize()
extras.comment = comment.get_api_data()
extras.created_by = username
# TODO(marcink): rcextensions handlers ??
hooks_base.log_comment_commit_repository(**extras)
def trigger_create_pull_request_hook(username, repo_name, repo_type, pull_request, data=None):
"""
Triggers create pull request action hooks
@ -196,6 +224,29 @@ def trigger_comment_pull_request_hook(username, repo_name, repo_type, pull_reque
hooks_base.log_comment_pull_request(**extras)
def trigger_comment_pull_request_edit_hook(username, repo_name, repo_type, pull_request, data=None):
"""
Triggers when a comment was edited on a pull request
:param username: username who made the edit
:param repo_name: name of target repo
:param repo_type: the type of SCM target repo
:param pull_request: the pull request that comment was made on
:param data: extra data for specific events e.g {'comment': comment_obj}
"""
if not _supports_repo_type(repo_type):
return
extras = _get_vcs_operation_context(username, repo_name, repo_type, 'comment_pull_request')
comment = data['comment']
events.trigger(events.PullRequestCommentEditEvent(pull_request, comment))
extras.update(pull_request.get_api_data())
extras.comment = comment.get_api_data()
# TODO(marcink): handle rcextensions...
hooks_base.log_comment_pull_request(**extras)
def trigger_update_pull_request_hook(username, repo_name, repo_type, pull_request, data=None):
"""
Triggers update pull request action hooks

View file

@ -789,8 +789,7 @@ class CommentsModel(BaseModel):
if action == 'create':
trigger_hook = hooks_utils.trigger_comment_commit_hooks
elif action == 'edit':
# TODO(dan): when this is supported we trigger edit hook too
return
trigger_hook = hooks_utils.trigger_comment_commit_edit_hooks
else:
return

View file

@ -703,6 +703,8 @@ class PullRequestModel(BaseModel):
trigger_hook = hooks_utils.trigger_update_pull_request_hook
elif action == 'comment':
trigger_hook = hooks_utils.trigger_comment_pull_request_hook
elif action == 'comment_edit':
trigger_hook = hooks_utils.trigger_comment_pull_request_edit_hook
else:
return

View file

@ -28,6 +28,7 @@ from rhodecode.events import (
PullRequestCreateEvent,
PullRequestUpdateEvent,
PullRequestCommentEvent,
PullRequestCommentEditEvent,
PullRequestReviewEvent,
PullRequestMergeEvent,
PullRequestCloseEvent,
@ -79,6 +80,21 @@ def test_pullrequest_comment_events_serialized(pr_util, config_stub):
assert data['comment']['text'] == comment.text
@pytest.mark.backends("git", "hg")
def test_pullrequest_comment_edit_events_serialized(pr_util, config_stub):
pr = pr_util.create_pull_request()
comment = CommentsModel().get_comments(
pr.target_repo.repo_id, pull_request=pr)[0]
event = PullRequestCommentEditEvent(pr, comment)
data = event.as_dict()
assert data['name'] == PullRequestCommentEditEvent.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['pullrequest']['permalink_url']
assert data['comment']['text'] == comment.text
@pytest.mark.backends("git", "hg")
def test_close_pull_request_events(pr_util, user_admin, config_stub):
pr = pr_util.create_pull_request()

View file

@ -29,7 +29,8 @@ from rhodecode.events.repo import (
RepoPrePullEvent, RepoPullEvent,
RepoPrePushEvent, RepoPushEvent,
RepoPreCreateEvent, RepoCreateEvent,
RepoPreDeleteEvent, RepoDeleteEvent, RepoCommitCommentEvent,
RepoPreDeleteEvent, RepoDeleteEvent,
RepoCommitCommentEvent, RepoCommitCommentEditEvent
)
@ -138,6 +139,30 @@ def test_repo_commit_event(config_stub, repo_stub, EventClass):
'comment_type': 'comment_type',
'f_path': 'f_path',
'line_no': 'line_no',
'last_version': 0,
})
event = EventClass(repo=repo_stub, commit=commit, comment=comment)
data = event.as_dict()
assert data['commit']['commit_id']
assert data['comment']['comment_id']
@pytest.mark.parametrize('EventClass', [RepoCommitCommentEditEvent])
def test_repo_commit_edit_event(config_stub, repo_stub, EventClass):
commit = StrictAttributeDict({
'raw_id': 'raw_id',
'message': 'message',
'branch': 'branch',
})
comment = StrictAttributeDict({
'comment_id': 'comment_id',
'text': 'text',
'comment_type': 'comment_type',
'f_path': 'f_path',
'line_no': 'line_no',
'last_version': 0,
})
event = EventClass(repo=repo_stub, commit=commit, comment=comment)
data = event.as_dict()