Add gitlab integration with commets webhook

remotes/origin/enhancement/email-actions
Jesús Espino 2015-06-30 17:30:06 +02:00 committed by David Barragán Merino
parent 8c60b9f22b
commit 3bae896199
4 changed files with 177 additions and 1 deletions

View File

@ -9,6 +9,7 @@
- Now every user that coments USs, Issues or Tasks will be involved in it (add author to the watchers list). - Now every user that coments USs, Issues or Tasks will be involved in it (add author to the watchers list).
- Fix the compatibility with BitBucket webhooks and add issues and issues comments integration. - Fix the compatibility with BitBucket webhooks and add issues and issues comments integration.
- Add custom videoconference system. - Add custom videoconference system.
- Add support for comments in the Gitlab webhooks integration.
### Misc ### Misc
- API: Mixin fields 'users', 'members' and 'memberships' in ProjectDetailSerializer - API: Mixin fields 'users', 'members' and 'memberships' in ProjectDetailSerializer

View File

@ -30,6 +30,7 @@ class GitLabViewSet(BaseWebhookApiViewSet):
event_hook_classes = { event_hook_classes = {
"push": event_hooks.PushEventHook, "push": event_hooks.PushEventHook,
"issue": event_hooks.IssuesEventHook, "issue": event_hooks.IssuesEventHook,
"note": event_hooks.IssueCommentEventHook,
} }
def _validate_signature(self, project, request): def _validate_signature(self, project, request):

View File

@ -89,7 +89,7 @@ class PushEventHook(BaseEventHook):
def replace_gitlab_references(project_url, wiki_text): def replace_gitlab_references(project_url, wiki_text):
if wiki_text == None: if wiki_text is None:
wiki_text = "" wiki_text = ""
template = "\g<1>[GitLab#\g<2>]({}/issues/\g<2>)\g<3>".format(project_url) template = "\g<1>[GitLab#\g<2>]({}/issues/\g<2>)\g<3>".format(project_url)
@ -127,3 +127,48 @@ class IssuesEventHook(BaseEventHook):
snapshot = take_snapshot(issue, comment=_("Created from GitLab"), user=get_gitlab_user(None)) snapshot = take_snapshot(issue, comment=_("Created from GitLab"), user=get_gitlab_user(None))
send_notifications(issue, history=snapshot) send_notifications(issue, history=snapshot)
class IssueCommentEventHook(BaseEventHook):
def process_event(self):
if self.payload.get('object_attributes', {}).get("noteable_type", None) != "Issue":
return
number = self.payload.get('issue', {}).get('iid', None)
subject = self.payload.get('issue', {}).get('title', None)
project_url = self.payload.get('repository', {}).get('homepage', None)
gitlab_url = os.path.join(project_url, "issues", str(number))
gitlab_user_name = self.payload.get('user', {}).get('username', None)
gitlab_user_url = os.path.join(os.path.dirname(os.path.dirname(project_url)), "u", gitlab_user_name)
comment_message = self.payload.get('object_attributes', {}).get('note', None)
comment_message = replace_gitlab_references(project_url, comment_message)
user = get_gitlab_user(None)
if not all([comment_message, gitlab_url, project_url]):
raise ActionSyntaxException(_("Invalid issue comment information"))
issues = Issue.objects.filter(external_reference=["gitlab", gitlab_url])
tasks = Task.objects.filter(external_reference=["gitlab", gitlab_url])
uss = UserStory.objects.filter(external_reference=["gitlab", gitlab_url])
for item in list(issues) + list(tasks) + list(uss):
if number and subject and gitlab_user_name and gitlab_user_url:
comment = _("Comment by [@{gitlab_user_name}]({gitlab_user_url} "
"\"See @{gitlab_user_name}'s GitLab profile\") "
"from GitLab.\nOrigin GitLab issue: [gh#{number} - {subject}]({gitlab_url} "
"\"Go to 'gh#{number} - {subject}'\")\n\n"
"{message}").format(gitlab_user_name=gitlab_user_name,
gitlab_user_url=gitlab_user_url,
number=number,
subject=subject,
gitlab_url=gitlab_url,
message=comment_message)
else:
comment = _("Comment From GitLab:\n\n{message}").format(message=comment_message)
snapshot = take_snapshot(item, comment=comment, user=user)
send_notifications(item, history=snapshot)

View File

@ -13,6 +13,7 @@ from taiga.projects.issues.models import Issue
from taiga.projects.tasks.models import Task from taiga.projects.tasks.models import Task
from taiga.projects.userstories.models import UserStory from taiga.projects.userstories.models import UserStory
from taiga.projects.models import Membership from taiga.projects.models import Membership
from taiga.projects.history.services import get_history_queryset_by_model_instance, take_snapshot
from taiga.projects.notifications.choices import NotifyLevel from taiga.projects.notifications.choices import NotifyLevel
from taiga.projects.notifications.models import NotifyPolicy from taiga.projects.notifications.models import NotifyPolicy
from taiga.projects import services from taiga.projects import services
@ -384,6 +385,134 @@ def test_issues_event_bad_issue(client):
assert len(mail.outbox) == 0 assert len(mail.outbox) == 0
def test_issue_comment_event_on_existing_issue_task_and_us(client):
project = f.ProjectFactory()
role = f.RoleFactory(project=project, permissions=["view_tasks", "view_issues", "view_us"])
f.MembershipFactory(project=project, role=role, user=project.owner)
user = f.UserFactory()
issue = f.IssueFactory.create(external_reference=["gitlab", "http://gitlab.com/test/project/issues/11"], owner=project.owner, project=project)
take_snapshot(issue, user=user)
task = f.TaskFactory.create(external_reference=["gitlab", "http://gitlab.com/test/project/issues/11"], owner=project.owner, project=project)
take_snapshot(task, user=user)
us = f.UserStoryFactory.create(external_reference=["gitlab", "http://gitlab.com/test/project/issues/11"], owner=project.owner, project=project)
take_snapshot(us, user=user)
payload = {
"user": {
"username": "test"
},
"issue": {
"iid": "11",
"title": "test-title",
},
"object_attributes": {
"noteable_type": "Issue",
"note": "Test body",
},
"repository": {
"homepage": "http://gitlab.com/test/project",
},
}
mail.outbox = []
assert get_history_queryset_by_model_instance(issue).count() == 0
assert get_history_queryset_by_model_instance(task).count() == 0
assert get_history_queryset_by_model_instance(us).count() == 0
ev_hook = event_hooks.IssueCommentEventHook(issue.project, payload)
ev_hook.process_event()
issue_history = get_history_queryset_by_model_instance(issue)
assert issue_history.count() == 1
assert "Test body" in issue_history[0].comment
task_history = get_history_queryset_by_model_instance(task)
assert task_history.count() == 1
assert "Test body" in issue_history[0].comment
us_history = get_history_queryset_by_model_instance(us)
assert us_history.count() == 1
assert "Test body" in issue_history[0].comment
assert len(mail.outbox) == 3
def test_issue_comment_event_on_not_existing_issue_task_and_us(client):
issue = f.IssueFactory.create(external_reference=["gitlab", "10"])
take_snapshot(issue, user=issue.owner)
task = f.TaskFactory.create(project=issue.project, external_reference=["gitlab", "10"])
take_snapshot(task, user=task.owner)
us = f.UserStoryFactory.create(project=issue.project, external_reference=["gitlab", "10"])
take_snapshot(us, user=us.owner)
payload = {
"user": {
"username": "test"
},
"issue": {
"iid": "99999",
"title": "test-title",
},
"object_attributes": {
"noteable_type": "Issue",
"note": "test comment",
},
"repository": {
"homepage": "test",
},
}
mail.outbox = []
assert get_history_queryset_by_model_instance(issue).count() == 0
assert get_history_queryset_by_model_instance(task).count() == 0
assert get_history_queryset_by_model_instance(us).count() == 0
ev_hook = event_hooks.IssueCommentEventHook(issue.project, payload)
ev_hook.process_event()
assert get_history_queryset_by_model_instance(issue).count() == 0
assert get_history_queryset_by_model_instance(task).count() == 0
assert get_history_queryset_by_model_instance(us).count() == 0
assert len(mail.outbox) == 0
def test_issues_event_bad_comment(client):
issue = f.IssueFactory.create(external_reference=["gitlab", "10"])
take_snapshot(issue, user=issue.owner)
payload = {
"user": {
"username": "test"
},
"issue": {
"iid": "10",
"title": "test-title",
},
"object_attributes": {
"noteable_type": "Issue",
},
"repository": {
"homepage": "test",
},
}
ev_hook = event_hooks.IssueCommentEventHook(issue.project, payload)
mail.outbox = []
with pytest.raises(ActionSyntaxException) as excinfo:
ev_hook.process_event()
assert str(excinfo.value) == "Invalid issue comment information"
assert Issue.objects.count() == 1
assert len(mail.outbox) == 0
def test_api_get_project_modules(client): def test_api_get_project_modules(client):
project = f.create_project() project = f.create_project()
f.MembershipFactory(project=project, user=project.owner, is_owner=True) f.MembershipFactory(project=project, user=project.owner, is_owner=True)