Skip to content

Commit 88b7b45

Browse files
author
Sasha Romijn
committed
Fix ietf-tools#2328 - Use mailtriggers to find destinations in review app
As the review app has several conditionals that don't fit entirely well within mailtriggers, the templates use a bit of extra context to figure out who exactly to include. This also extends the tests for review, to check for correct recipients. It also adds a tiny feature to mailtrigger to entirely exclude certain addresses, as required by the review-generated mails. Commit ready for merge. - Legacy-Id: 16672
1 parent 3942f9a commit 88b7b45

6 files changed

Lines changed: 272 additions & 117 deletions

File tree

ietf/doc/tests_review.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,8 @@ def test_close_request(self):
223223
self.assertFalse("review_request_close_comment" in e.desc.lower())
224224

225225
self.assertEqual(len(outbox), 1)
226+
self.assertTrue('<reviewer@example.com>' in outbox[0]["To"])
227+
self.assertFalse("<reviewsecretary@example.com>" in outbox[0]["To"])
226228
mail_content = outbox[0].get_payload(decode=True).decode("utf-8").lower()
227229
self.assertTrue("closed" in mail_content)
228230
self.assertTrue("review_request_close_comment" in mail_content)
@@ -420,6 +422,7 @@ def test_assign_reviewer(self):
420422
self.assertEqual(assignment.reviewer, reviewer)
421423
self.assertEqual(assignment.state_id, "assigned")
422424
self.assertEqual(len(outbox), 1)
425+
self.assertEqual('"Some Reviewer" <reviewer@example.com>', outbox[0]["To"])
423426
self.assertTrue("assigned" in outbox[0].get_payload(decode=True).decode("utf-8"))
424427
self.assertEqual(NextReviewerInTeam.objects.get(team=review_req.team).next_reviewer, rotation_list[1])
425428

@@ -482,6 +485,8 @@ def test_reject_reviewer_assignment(self):
482485
self.assertEqual(e.type, "closed_review_assignment")
483486
self.assertTrue("rejected" in e.desc)
484487
self.assertEqual(len(outbox), 1)
488+
self.assertTrue(assignment.reviewer.address in outbox[0]["To"])
489+
self.assertFalse("<reviewsecretary@example.com>" in outbox[0]["To"])
485490
self.assertTrue("Test message" in outbox[0].get_payload(decode=True).decode("utf-8"))
486491

487492
def make_test_mbox_tarball(self, review_req):
@@ -858,7 +863,8 @@ def test_partially_complete_review(self):
858863
self.assertTrue(assignment.review_request.doc.rev in assignment.review.name)
859864

860865
self.assertEqual(len(outbox), 2)
861-
self.assertTrue("reviewsecretary@example.com" in outbox[0]["To"])
866+
self.assertTrue("<reviewsecretary@example.com>" in outbox[0]["To"])
867+
self.assertFalse(assignment.reviewer.address in outbox[0]["To"])
862868
self.assertTrue("partially" in outbox[0]["Subject"].lower())
863869

864870
self.assertTrue(assignment.review_request.team.list_email in outbox[1]["To"])
@@ -998,6 +1004,7 @@ def test_edit_deadline(self):
9981004
r = self.client.get(url)
9991005
self.assertEqual(r.status_code, 200)
10001006

1007+
empty_outbox()
10011008
old_deadline = review_req.deadline.date()
10021009
new_deadline = old_deadline + datetime.timedelta(days=1)
10031010
r = self.client.post(url, data={
@@ -1006,7 +1013,10 @@ def test_edit_deadline(self):
10061013
self.assertEqual(r.status_code, 302)
10071014
review_req = reload_db_objects(review_req)
10081015
self.assertEqual(review_req.deadline,new_deadline)
1009-
self.assertTrue('Deadline changed' in outbox[-1]['Subject'])
1016+
self.assertEqual(len(outbox), 1)
1017+
self.assertTrue('<reviewsecretary@example.com>' in outbox[0]["To"])
1018+
self.assertTrue('<reviewer@example.com>' in outbox[0]["To"])
1019+
self.assertTrue('Deadline changed' in outbox[0]['Subject'])
10101020

10111021
def test_mark_no_response(self):
10121022
assignment = ReviewAssignmentFactory()
@@ -1017,12 +1027,18 @@ def test_mark_no_response(self):
10171027
r = self.client.get(url)
10181028
self.assertEqual(r.status_code, 200)
10191029

1030+
empty_outbox()
10201031
r=self.client.post(url, data={"action":"noresponse"})
10211032
self.assertEqual(r.status_code, 302)
10221033

10231034
assignment = reload_db_objects(assignment)
10241035
self.assertEqual(assignment.state_id, 'no-response')
10251036

1037+
self.assertEqual(len(outbox), 1)
1038+
self.assertTrue(assignment.reviewer.address in outbox[0]["To"])
1039+
self.assertFalse('<reviewsecretary@example.com>' in outbox[0]["To"])
1040+
self.assertTrue('Reviewer assignment marked no-response' in outbox[0]['Subject'])
1041+
10261042
def test_withdraw_assignment(self):
10271043
assignment = ReviewAssignmentFactory()
10281044
secr = RoleFactory(group=assignment.review_request.team,person__user__username='reviewsecretary',person__user__email='reviewsecretary@example.com',name_id='secr').person
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# Copyright The IETF Trust 2019, All Rights Reserved
2+
# -*- coding: utf-8 -*-
3+
4+
from __future__ import absolute_import, print_function, unicode_literals
5+
6+
from django.db import migrations
7+
8+
def forward(apps, schema_editor):
9+
MailTrigger = apps.get_model('mailtrigger','MailTrigger')
10+
Recipient = apps.get_model('mailtrigger', 'Recipient')
11+
12+
review_assignment_reviewer = Recipient.objects.create(
13+
slug="review_assignment_reviewer",
14+
desc="The reviewer assigned to a review assignment",
15+
template="{% if not skip_review_reviewer %}{{review_assignment.reviewer.email_address}}{% endif %}",
16+
)
17+
review_assignment_review_req_by = Recipient.objects.create(
18+
slug="review_assignment_review_req_by",
19+
desc="The requester of an assigned review",
20+
template="{% if not skip_review_requested_by %}{{review_assignment.review_request.requested_by.email_address}}{% endif %}",
21+
)
22+
review_req_requested_by = Recipient.objects.create(
23+
slug="review_req_requested_by",
24+
desc="The requester of a review",
25+
template="{% if not skip_review_requested_by %}{{review_req.requested_by.email_address}}{% endif %}",
26+
)
27+
review_req_reviewers = Recipient.objects.create(
28+
slug="review_req_reviewers",
29+
desc="All reviewers assigned to a review request",
30+
template=None,
31+
)
32+
review_secretaries = Recipient.objects.create(
33+
slug="review_secretaries",
34+
desc="The secretaries of the review team of a review request or assignment",
35+
template=None,
36+
)
37+
Recipient.objects.create(
38+
slug="review_reviewer",
39+
desc="A single reviewer",
40+
template="{{reviewer.email_address}}",
41+
)
42+
43+
review_assignment_changed = MailTrigger.objects.create(
44+
slug="review_assignment_changed",
45+
desc="Recipients for a change to a review assignment",
46+
)
47+
review_assignment_changed.to.set([review_assignment_review_req_by, review_assignment_reviewer,
48+
review_secretaries])
49+
50+
review_req_changed = MailTrigger.objects.create(
51+
slug="review_req_changed",
52+
desc="Recipients for a change to a review request",
53+
)
54+
review_req_changed.to.set([review_req_requested_by, review_req_reviewers, review_secretaries])
55+
56+
review_availability_changed = MailTrigger.objects.create(
57+
slug="review_availability_changed",
58+
desc="Recipients for a change to a reviewer's availability",
59+
)
60+
review_availability_changed.to.set(
61+
Recipient.objects.filter(slug__in=['review_reviewer', 'group_secretaries'])
62+
)
63+
64+
65+
def reverse(apps, schema_editor):
66+
MailTrigger = apps.get_model('mailtrigger','MailTrigger')
67+
Recipient = apps.get_model('mailtrigger', 'Recipient')
68+
69+
MailTrigger.objects.filter(slug__in=[
70+
'review_assignment_changed', 'review_req_changed', 'review_availability_changed',
71+
]).delete()
72+
Recipient.objects.filter(slug__in=[
73+
'review_assignment_reviewer', 'review_assignment_review_req_by', 'review_req_requested_by',
74+
'review_req_reviewers', 'review_secretaries', 'review_reviewer',
75+
]).delete()
76+
77+
78+
class Migration(migrations.Migration):
79+
80+
dependencies = [
81+
('mailtrigger', '0006_sub_new_wg_00'),
82+
]
83+
84+
operations = [
85+
migrations.RunPython(forward, reverse)
86+
]

ietf/mailtrigger/models.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,20 @@ def gather_group_secretaries(self, **kwargs):
184184
else:
185185
addrs.extend(group.role_set.filter(name='secr').values_list('email__address',flat=True))
186186
return addrs
187-
187+
188+
def gather_review_req_reviewers(self, **kwargs):
189+
addrs = []
190+
if 'review_request' in kwargs:
191+
review_request = kwargs['review_request']
192+
for assignment in review_request.reviewassignment_set.all():
193+
addrs.append(assignment.reviewer.formatted_email())
194+
return addrs
195+
196+
def gather_review_secretaries(self, **kwargs):
197+
if not kwargs.get('skip_secretary'):
198+
return self.gather_group_secretaries(**kwargs)
199+
return []
200+
188201
def gather_doc_group_responsible_directors(self, **kwargs):
189202
addrs = []
190203
if 'doc' in kwargs:

ietf/mailtrigger/utils.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# Copyright The IETF Trust 2019, All Rights Reserved
2+
13
from collections import namedtuple
24

35
import debug # pyflakes:ignore
@@ -17,18 +19,22 @@ def as_strings(self,compact=True):
1719

1820
return namedtuple('AddrListsAsStrings',['to','cc'])(to=to_string,cc=cc_string)
1921

20-
def gather_address_lists(slug, **kwargs):
22+
def gather_address_lists(slug, skipped_recipients=None, **kwargs):
2123
mailtrigger = MailTrigger.objects.get(slug=slug)
2224

2325
to = set()
2426
for recipient in mailtrigger.to.all():
2527
to.update(recipient.gather(**kwargs))
2628
to.discard('')
29+
if skipped_recipients:
30+
to -= set(skipped_recipients)
2731

2832
cc = set()
2933
for recipient in mailtrigger.cc.all():
3034
cc.update(recipient.gather(**kwargs))
3135
cc.discard('')
36+
if skipped_recipients:
37+
cc -= set(skipped_recipients)
3238

3339
return AddrLists(to=list(to),cc=list(cc))
3440

ietf/name/fixtures/names.json

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4126,6 +4126,44 @@
41264126
"model": "mailtrigger.mailtrigger",
41274127
"pk": "sub_new_wg_00"
41284128
},
4129+
{
4130+
"model": "mailtrigger.mailtrigger",
4131+
"pk": "review_assignment_changed",
4132+
"fields": {
4133+
"desc": "Recipients for a change to a review assignment",
4134+
"to": [
4135+
"review_assignment_reviewer",
4136+
"review_assignment_review_req_by",
4137+
"review_secretaries"
4138+
],
4139+
"cc": []
4140+
}
4141+
},
4142+
{
4143+
"model": "mailtrigger.mailtrigger",
4144+
"pk": "review_req_changed",
4145+
"fields": {
4146+
"desc": "Recipients for a change to a review request",
4147+
"to": [
4148+
"review_req_requested_by",
4149+
"review_req_reviewers",
4150+
"review_secretaries"
4151+
],
4152+
"cc": []
4153+
}
4154+
},
4155+
{
4156+
"model": "mailtrigger.mailtrigger",
4157+
"pk": "review_availability_changed",
4158+
"fields": {
4159+
"desc": "Recipients for a change to a reviewer's availability",
4160+
"to": [
4161+
"review_reviewer",
4162+
"group_secretaries"
4163+
],
4164+
"cc": []
4165+
}
4166+
},
41294167
{
41304168
"fields": {
41314169
"desc": "The person providing a comment to nomcom",
@@ -4702,6 +4740,54 @@
47024740
"model": "mailtrigger.recipient",
47034741
"pk": "submission_submitter"
47044742
},
4743+
{
4744+
"model": "mailtrigger.recipient",
4745+
"pk": "review_assignment_reviewer",
4746+
"fields": {
4747+
"desc": "The reviewer assigned to a review assignment",
4748+
"template": "{% if not skip_review_reviewer %}{{review_assignment.reviewer.email_address}}{% endif %}"
4749+
}
4750+
},
4751+
{
4752+
"model": "mailtrigger.recipient",
4753+
"pk": "review_assignment_review_req_by",
4754+
"fields": {
4755+
"desc": "The requester of an assigned review",
4756+
"template": "{% if not skip_review_requested_by %}{{review_assignment.review_request.requested_by.email_address}}{% endif %}"
4757+
}
4758+
},
4759+
{
4760+
"model": "mailtrigger.recipient",
4761+
"pk": "review_req_requested_by",
4762+
"fields": {
4763+
"desc": "The requester of a review",
4764+
"template": "{% if not skip_review_requested_by %}{{review_req.requested_by.email_address}}{% endif %}"
4765+
}
4766+
},
4767+
{
4768+
"model": "mailtrigger.recipient",
4769+
"pk": "review_req_reviewers",
4770+
"fields": {
4771+
"desc": "All reviewers assigned to a review request",
4772+
"template": null
4773+
}
4774+
},
4775+
{
4776+
"model": "mailtrigger.recipient",
4777+
"pk": "review_secretaries",
4778+
"fields": {
4779+
"desc": "The secretaries of the review team of a review request or assignment",
4780+
"template": null
4781+
}
4782+
},
4783+
{
4784+
"model": "mailtrigger.recipient",
4785+
"pk": "review_reviewer",
4786+
"fields": {
4787+
"desc": "A single reviewer",
4788+
"template": "{{reviewer.email_address}}"
4789+
}
4790+
},
47054791
{
47064792
"fields": {
47074793
"desc": "",

0 commit comments

Comments
 (0)