Support for updating epic status via commit message

remotes/origin/issue/4795/notification_even_they_are_disabled
Alejandro Alonso 2016-09-15 12:20:48 +02:00
parent 564cd43504
commit 4e50135234
8 changed files with 176 additions and 13 deletions

View File

@ -20,7 +20,8 @@ import re
from django.utils.translation import ugettext as _
from django.contrib.auth import get_user_model
from taiga.projects.models import IssueStatus, TaskStatus, UserStoryStatus
from taiga.projects.models import IssueStatus, TaskStatus, UserStoryStatus, EpicStatus
from taiga.projects.epics.models import Epic
from taiga.projects.issues.models import Issue
from taiga.projects.tasks.models import Task
from taiga.projects.userstories.models import UserStory
@ -189,7 +190,10 @@ class BasePushEventHook(BaseEventHook):
return _simple_status_change_message.format(platform=self.platform)
def get_item_classes(self, ref):
if Issue.objects.filter(project=self.project, ref=ref).exists():
if Epic.objects.filter(project=self.project, ref=ref).exists():
modelClass = Epic
statusClass = EpicStatus
elif Issue.objects.filter(project=self.project, ref=ref).exists():
modelClass = Issue
statusClass = IssueStatus
elif Task.objects.filter(project=self.project, ref=ref).exists():

View File

@ -116,6 +116,10 @@ class RelatedUserStory(WatchedModelMixin, models.Model):
def project_id(self):
return self.epic.project_id
@property
def owner(self):
return self.epic.owner
@property
def owner_id(self):
return self.epic.owner_id

View File

@ -80,7 +80,7 @@ _values_impl_map = {}
# Not important fields for models (history entries with only
# this fields are marked as hidden).
_not_important_fields = {
"epics.epic": frozenset(["epics_order"]),
"epics.epic": frozenset(["epics_order", "user_stories"]),
"userstories.userstory": frozenset(["backlog_order", "sprint_order", "kanban_order"]),
"tasks.task": frozenset(["us_order", "taskboard_order"]),
}

View File

@ -242,31 +242,31 @@ def test_epic_related_userstories_create(client, data):
]
create_data = json.dumps({
"user_story": data.public_us.id,
"user_story": f.UserStoryFactory(project=data.public_project).id,
"epic": data.public_epic.id
})
url = reverse('epics-related-userstories-list', args=[data.public_epic.pk])
results = helper_test_http_method(client, 'post', url, create_data, users)
assert results == [401, 403, 403, 201, 201]
assert results == [401, 403, 403, 201, 400]
create_data = json.dumps({
"user_story": data.private_us1.id,
"user_story": f.UserStoryFactory(project=data.private_project1).id,
"epic": data.private_epic1.id
})
url = reverse('epics-related-userstories-list', args=[data.private_epic1.pk])
results = helper_test_http_method(client, 'post', url, create_data, users)
assert results == [401, 403, 403, 201, 201]
assert results == [401, 403, 403, 201, 400]
create_data = json.dumps({
"user_story": data.private_us2.id,
"user_story": f.UserStoryFactory(project=data.private_project2).id,
"epic": data.private_epic2.id
})
url = reverse('epics-related-userstories-list', args=[data.private_epic2.pk])
results = helper_test_http_method(client, 'post', url, create_data, users)
assert results == [401, 403, 403, 201, 201]
assert results == [401, 403, 403, 201, 400]
create_data = json.dumps({
"user_story": data.blocked_us.id,
"user_story": f.UserStoryFactory(project=data.blocked_project).id,
"epic": data.blocked_epic.id
})
url = reverse('epics-related-userstories-list', args=[data.blocked_epic.pk])
@ -379,14 +379,29 @@ def test_bulk_create_related_userstories(client, data):
]
bulk_data = json.dumps({
"userstories": "test1\ntest2",
"bulk_userstories": "test1\ntest2",
"project_id": data.public_project.id
})
results = helper_test_http_method(client, 'post', public_url, bulk_data, users)
assert results == [401, 403, 403, 200, 200]
bulk_data = json.dumps({
"bulk_userstories": "test1\ntest2",
"project_id": data.private_project1.id
})
results = helper_test_http_method(client, 'post', private_url1, bulk_data, users)
assert results == [401, 403, 403, 200, 200]
bulk_data = json.dumps({
"bulk_userstories": "test1\ntest2",
"project_id": data.private_project2.id
})
results = helper_test_http_method(client, 'post', private_url2, bulk_data, users)
assert results == [401, 403, 403, 200, 200]
bulk_data = json.dumps({
"bulk_userstories": "test1\ntest2",
"project_id": data.blocked_project.id
})
results = helper_test_http_method(client, 'post', blocked_url, bulk_data, users)
assert results == [401, 403, 403, 451, 451]

View File

@ -31,6 +31,7 @@ from taiga.hooks.bitbucket import event_hooks
from taiga.hooks.bitbucket.api import BitBucketViewSet
from taiga.hooks.exceptions import ActionSyntaxException
from taiga.projects import choices as project_choices
from taiga.projects.epics.models import Epic
from taiga.projects.issues.models import Issue
from taiga.projects.tasks.models import Task
from taiga.projects.userstories.models import UserStory
@ -239,6 +240,38 @@ def test_push_event_detected(client):
assert response.status_code == 204
def test_push_event_epic_processing(client):
creation_status = f.EpicStatusFactory()
role = f.RoleFactory(project=creation_status.project, permissions=["view_epics"])
f.MembershipFactory(project=creation_status.project, role=role, user=creation_status.project.owner)
new_status = f.EpicStatusFactory(project=creation_status.project)
epic = f.EpicFactory.create(status=creation_status, project=creation_status.project, owner=creation_status.project.owner)
payload = {
"actor": {
"user": {
"uuid": "{ce1054cd-3f43-49dc-8aea-d3085ee7ec9b}",
"username": "test-user",
"links": {"html": {"href": "http://bitbucket.com/test-user"}}
}
},
"push": {
"changes": [
{
"commits": [
{ "message": "test message test TG-%s #%s ok bye!" % (epic.ref, new_status.slug) }
]
}
]
}
}
mail.outbox = []
ev_hook = event_hooks.PushEventHook(epic.project, payload)
ev_hook.process_event()
epic = Epic.objects.get(id=epic.id)
assert epic.status.id == new_status.id
assert len(mail.outbox) == 1
def test_push_event_issue_processing(client):
creation_status = f.IssueStatusFactory()
role = f.RoleFactory(project=creation_status.project, permissions=["view_issues"])
@ -534,6 +567,36 @@ def test_push_event_task_bad_processing_non_existing_ref(client):
assert len(mail.outbox) == 0
def test_push_event_task_bad_processing_non_existing_ref(client):
issue_status = f.IssueStatusFactory()
payload = {
"actor": {
"user": {
"uuid": "{ce1054cd-3f43-49dc-8aea-d3085ee7ec9b}",
"username": "test-user",
"links": {"html": {"href": "http://bitbucket.com/test-user"}}
}
},
"push": {
"changes": [
{
"commits": [
{ "message": "test message test TG-6666666 #%s ok bye!" % (issue_status.slug) }
]
}
]
}
}
mail.outbox = []
ev_hook = event_hooks.PushEventHook(issue_status.project, payload)
with pytest.raises(ActionSyntaxException) as excinfo:
ev_hook.process_event()
assert str(excinfo.value) == "The referenced element doesn't exist"
assert len(mail.outbox) == 0
def test_push_event_us_bad_processing_non_existing_status(client):
user_story = f.UserStoryFactory.create()
payload = {

View File

@ -29,6 +29,7 @@ from taiga.hooks.github import event_hooks
from taiga.hooks.github.api import GitHubViewSet
from taiga.hooks.exceptions import ActionSyntaxException
from taiga.projects import choices as project_choices
from taiga.projects.epics.models import Epic
from taiga.projects.issues.models import Issue
from taiga.projects.tasks.models import Task
from taiga.projects.userstories.models import UserStory
@ -111,6 +112,26 @@ def test_push_event_detected(client):
assert response.status_code == 204
def test_push_event_epic_processing(client):
creation_status = f.EpicStatusFactory()
role = f.RoleFactory(project=creation_status.project, permissions=["view_epics"])
f.MembershipFactory(project=creation_status.project, role=role, user=creation_status.project.owner)
new_status = f.EpicStatusFactory(project=creation_status.project)
epic = f.EpicFactory.create(status=creation_status, project=creation_status.project, owner=creation_status.project.owner)
payload = {"commits": [
{"message": """test message
test TG-%s #%s ok
bye!
""" % (epic.ref, new_status.slug)},
]}
mail.outbox = []
ev_hook = event_hooks.PushEventHook(epic.project, payload)
ev_hook.process_event()
epic = Epic.objects.get(id=epic.id)
assert epic.status.id == new_status.id
assert len(mail.outbox) == 1
def test_push_event_issue_processing(client):
creation_status = f.IssueStatusFactory()
role = f.RoleFactory(project=creation_status.project, permissions=["view_issues"])

View File

@ -30,6 +30,7 @@ from taiga.hooks.gitlab import event_hooks
from taiga.hooks.gitlab.api import GitLabViewSet
from taiga.hooks.exceptions import ActionSyntaxException
from taiga.projects import choices as project_choices
from taiga.projects.epics.models import Epic
from taiga.projects.issues.models import Issue
from taiga.projects.tasks.models import Task
from taiga.projects.userstories.models import UserStory
@ -446,6 +447,30 @@ def test_push_event_detected(client):
assert response.status_code == 204
def test_push_event_epic_processing(client):
creation_status = f.EpicStatusFactory()
role = f.RoleFactory(project=creation_status.project, permissions=["view_epics"])
f.MembershipFactory(project=creation_status.project, role=role, user=creation_status.project.owner)
new_status = f.EpicStatusFactory(project=creation_status.project)
epic = f.EpicFactory.create(status=creation_status, project=creation_status.project, owner=creation_status.project.owner)
payload = deepcopy(push_base_payload)
payload["commits"] = [{
"message": """test message
test TG-%s #%s ok
bye!
""" % (epic.ref, new_status.slug),
"id": "b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327",
"url": "http://example.com/mike/diaspora/commit/b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327",
}]
payload["total_commits_count"] = 1
mail.outbox = []
ev_hook = event_hooks.PushEventHook(epic.project, payload)
ev_hook.process_event()
epic = Epic.objects.get(id=epic.id)
assert epic.status.id == new_status.id
assert len(mail.outbox) == 1
def test_push_event_issue_processing(client):
creation_status = f.IssueStatusFactory()
role = f.RoleFactory(project=creation_status.project, permissions=["view_issues"])

View File

@ -29,6 +29,7 @@ from taiga.hooks.gogs import event_hooks
from taiga.hooks.gogs.api import GogsViewSet
from taiga.hooks.exceptions import ActionSyntaxException
from taiga.projects import choices as project_choices
from taiga.projects.epics.models import Epic
from taiga.projects.issues.models import Issue
from taiga.projects.tasks.models import Task
from taiga.projects.userstories.models import UserStory
@ -120,6 +121,36 @@ def test_push_event_detected(client):
assert response.status_code == 204
def test_push_event_epic_processing(client):
creation_status = f.EpicStatusFactory()
role = f.RoleFactory(project=creation_status.project, permissions=["view_epics"])
f.MembershipFactory(project=creation_status.project, role=role, user=creation_status.project.owner)
new_status = f.EpicStatusFactory(project=creation_status.project)
epic = f.EpicFactory.create(status=creation_status, project=creation_status.project, owner=creation_status.project.owner)
payload = {
"commits": [
{
"message": """test message
test TG-%s #%s ok
bye!
""" % (epic.ref, new_status.slug),
"author": {
"username": "test",
},
}
],
"repository": {
"url": "http://test-url/test/project"
}
}
mail.outbox = []
ev_hook = event_hooks.PushEventHook(epic.project, payload)
ev_hook.process_event()
epic = Epic.objects.get(id=epic.id)
assert epic.status.id == new_status.id
assert len(mail.outbox) == 1
def test_push_event_issue_processing(client):
creation_status = f.IssueStatusFactory()
role = f.RoleFactory(project=creation_status.project, permissions=["view_issues"])