Merge lp:~gmb/launchpad/prompt-user-to-subscribe-to-master-bug-485627 into lp:launchpad

Proposed by Graham Binns
Status: Merged
Approved by: Edwin Grubbs
Approved revision: no longer in the source branch.
Merged at revision: 11488
Proposed branch: lp:~gmb/launchpad/prompt-user-to-subscribe-to-master-bug-485627
Merge into: lp:launchpad
Diff against target: 370 lines (+116/-51)
4 files modified
lib/lp/bugs/adapters/bugchange.py (+25/-9)
lib/lp/bugs/doc/bug-change.txt (+1/-0)
lib/lp/bugs/doc/bugnotification-sending.txt (+50/-31)
lib/lp/bugs/tests/test_bugchanges.py (+40/-11)
To merge this branch: bzr merge lp:~gmb/launchpad/prompt-user-to-subscribe-to-master-bug-485627
Reviewer Review Type Date Requested Status
Edwin Grubbs (community) code Approve
Review via email: mp+34302@code.launchpad.net

Commit message

Users will now be prompted to subscribe to the master bug when they are notified that one bug has been marked as a duplicate of another.

Description of the change

This branch adds a link to notifications about bugs being marked as a
duplicate, prompting the user to subscribe to the master bug.

Changes made:

== lib/lp/bugs/adapters/bugchange.py ==

 - I've updated the BugDuplicateChange class to add the 'you can
   subscribe by following this link' footer to duplication
   notifications.
 - I've cleaned up some lint.

== lib/lp/bugs/doc/bugnotification-sending.txt ==

 - Weirdly, this test failed after I'd made my change, but in a code
   path not related to my changes. Adding the switch_db_user calls to
   the point of failure fixed it; AFAICT this test should never have
   passed in the first place.
 - I've taken the opportunity to move this test to ReST format and to
   clean up some lint.

== lib/lp/bugs/tests/test_bugchanges.py ==

 - I've updated the tests for bug duplicate notifications to reflect the
   changes made to bugchange.py above.

To post a comment you must log in.
Revision history for this message
Edwin Grubbs (edwin-grubbs) wrote :

Hi Graham,

This branch looks good.

-Edwin

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/bugs/adapters/bugchange.py'
--- lib/lp/bugs/adapters/bugchange.py 2010-08-20 20:31:18 +0000
+++ lib/lp/bugs/adapters/bugchange.py 2010-09-02 10:32:47 +0000
@@ -213,7 +213,7 @@
213 lines.append(u"%13s: %s" % (213 lines.append(u"%13s: %s" % (
214 u"Status", self.bug_task.status.title))214 u"Status", self.bug_task.status.title))
215 return {215 return {
216 'text': '\n'.join(lines)216 'text': '\n'.join(lines),
217 }217 }
218218
219219
@@ -381,8 +381,16 @@
381 "%d" % self.new_value.id)381 "%d" % self.new_value.id)
382 else:382 else:
383 new_value_text = (383 new_value_text = (
384 "** This bug has been marked a duplicate of bug %d\n"384 "** This bug has been marked a duplicate of bug "
385 " %s" % (self.new_value.id, self.new_value.title))385 "%(bug_id)d\n %(bug_title)s\n"
386 " * You can subscribe to bug %(bug_id)d by following "
387 "this link: %(subscribe_link)s" % {
388 'bug_id': self.new_value.id,
389 'bug_title': self.new_value.title,
390 'subscribe_link': canonical_url(
391 self.new_value.default_bugtask,
392 view_name='+subscribe'),
393 })
386394
387 text = "\n".join((old_value_text, new_value_text))395 text = "\n".join((old_value_text, new_value_text))
388396
@@ -393,8 +401,16 @@
393 "%d" % self.new_value.id)401 "%d" % self.new_value.id)
394 else:402 else:
395 text = (403 text = (
396 "** This bug has been marked a duplicate of bug %d\n"404 "** This bug has been marked a duplicate of bug "
397 " %s" % (self.new_value.id, self.new_value.title))405 "%(bug_id)d\n %(bug_title)s\n"
406 " * You can subscribe to bug %(bug_id)d by following "
407 "this link: %(subscribe_link)s" % {
408 'bug_id': self.new_value.id,
409 'bug_title': self.new_value.title,
410 'subscribe_link': canonical_url(
411 self.new_value.default_bugtask,
412 view_name='+subscribe'),
413 })
398414
399 elif self.new_value is None:415 elif self.new_value is None:
400 if self.old_value.private:416 if self.old_value.private:
@@ -492,7 +508,7 @@
492 def getBugNotification(self):508 def getBugNotification(self):
493 return {509 return {
494 'text': self.notification_mapping[510 'text': self.notification_mapping[
495 (self.old_value, self.new_value)]511 (self.old_value, self.new_value)],
496 }512 }
497513
498514
@@ -685,9 +701,9 @@
685 u"** Changed in: %(bug_target_name)s\n"701 u"** Changed in: %(bug_target_name)s\n"
686 "%(label)13s: %(oldval)s => %(newval)s\n" % {702 "%(label)13s: %(oldval)s => %(newval)s\n" % {
687 'bug_target_name': self.bug_task.bugtargetname,703 'bug_target_name': self.bug_task.bugtargetname,
688 'label' : self.display_notification_label,704 'label': self.display_notification_label,
689 'oldval' : self.display_old_value,705 'oldval': self.display_old_value,
690 'newval' : self.display_new_value,706 'newval': self.display_new_value,
691 })707 })
692708
693 return {'text': text.rstrip()}709 return {'text': text.rstrip()}
694710
=== modified file 'lib/lp/bugs/doc/bug-change.txt'
--- lib/lp/bugs/doc/bug-change.txt 2010-08-16 13:50:28 +0000
+++ lib/lp/bugs/doc/bug-change.txt 2010-09-02 10:32:47 +0000
@@ -300,6 +300,7 @@
300 >>> print bug_duplicate_change.getBugNotification()['text']300 >>> print bug_duplicate_change.getBugNotification()['text']
301 ** This bug has been marked a duplicate of bug ...301 ** This bug has been marked a duplicate of bug ...
302 Fish can't walk302 Fish can't walk
303 * You can subscribe to bug ... by following this link:...
303304
304BugDuplicateChange overrides getBugActivity() to customize all the305BugDuplicateChange overrides getBugActivity() to customize all the
305returned fields.306returned fields.
306307
=== modified file 'lib/lp/bugs/doc/bugnotification-sending.txt'
--- lib/lp/bugs/doc/bugnotification-sending.txt 2010-08-23 09:28:02 +0000
+++ lib/lp/bugs/doc/bugnotification-sending.txt 2010-09-02 10:32:47 +0000
@@ -1,4 +1,5 @@
1= Sending the Bug Notifications =1Sending the Bug Notifications
2=============================
23
3As explained in bugnotifications.txt, a change to a bug causes a bug4As explained in bugnotifications.txt, a change to a bug causes a bug
4notification to be added. These notifications should be assembled into5notification to be added. These notifications should be assembled into
@@ -29,6 +30,21 @@
29 ... print email_notification.get_payload(decode=True)30 ... print email_notification.get_payload(decode=True)
30 ... print "-" * 7031 ... print "-" * 70
3132
33We'll also define some helper functions to help us with database users.
34
35 >>> from canonical.config import config
36 >>> from canonical.database.sqlbase import commit
37 >>> from canonical.testing import LaunchpadZopelessLayer
38
39 >>> def switch_db_to_launchpad():
40 ... commit()
41 ... LaunchpadZopelessLayer.switchDbUser('launchpad')
42
43 >>> def switch_db_to_bugnotification():
44 ... commit()
45 ... LaunchpadZopelessLayer.switchDbUser(
46 ... config.malone.bugnotification_dbuser)
47
32You'll note that we are printing out an X-Launchpad-Message-Rationale48You'll note that we are printing out an X-Launchpad-Message-Rationale
33header. This header is a simple string that allows people to filter49header. This header is a simple string that allows people to filter
34bugmail according to the reason they are getting emailed. For instance,50bugmail according to the reason they are getting emailed. For instance,
@@ -46,7 +62,8 @@
46 ... datecreated=ten_minutes_ago)62 ... datecreated=ten_minutes_ago)
47 >>> bug_one.addCommentNotification(comment)63 >>> bug_one.addCommentNotification(comment)
4864
49 >>> notifications = getUtility(IBugNotificationSet).getNotificationsToSend()65 >>> notifications = getUtility(
66 ... IBugNotificationSet).getNotificationsToSend()
50 >>> len(notifications)67 >>> len(notifications)
51 168 1
5269
@@ -323,6 +340,7 @@
323 ... print member.preferredemail.email340 ... print member.preferredemail.email
324 marilize@hbd.com341 marilize@hbd.com
325342
343 >>> switch_db_to_launchpad()
326 >>> bug_one.subscribe(shipit_admins, shipit_admins)344 >>> bug_one.subscribe(shipit_admins, shipit_admins)
327 <...>345 <...>
328346
@@ -330,6 +348,8 @@
330 ... 'subject', 'a comment.', sample_person,348 ... 'subject', 'a comment.', sample_person,
331 ... datecreated=ten_minutes_ago)349 ... datecreated=ten_minutes_ago)
332 >>> bug_one.addCommentNotification(comment)350 >>> bug_one.addCommentNotification(comment)
351
352 >>> switch_db_to_bugnotification()
333 >>> pending_notifications = getUtility(353 >>> pending_notifications = getUtility(
334 ... IBugNotificationSet).getNotificationsToSend()354 ... IBugNotificationSet).getNotificationsToSend()
335 >>> len(pending_notifications)355 >>> len(pending_notifications)
@@ -348,22 +368,8 @@
348 >>> flush_notifications()368 >>> flush_notifications()
349369
350370
351== Duplicates ==371Duplicates
352372----------
353We will need some helper functions.
354
355 >>> from canonical.config import config
356 >>> from canonical.database.sqlbase import commit
357 >>> from canonical.testing import LaunchpadZopelessLayer
358
359 >>> def switch_db_to_launchpad():
360 ... commit()
361 ... LaunchpadZopelessLayer.switchDbUser('launchpad')
362
363 >>> def switch_db_to_bugnotification():
364 ... commit()
365 ... LaunchpadZopelessLayer.switchDbUser(
366 ... config.malone.bugnotification_dbuser)
367373
368We will also need a fresh new bug.374We will also need a fresh new bug.
369375
@@ -391,11 +397,13 @@
391 ... 'subject', 'a comment.', sample_person,397 ... 'subject', 'a comment.', sample_person,
392 ... datecreated=ten_minutes_ago)398 ... datecreated=ten_minutes_ago)
393 >>> new_bug.addCommentNotification(comment)399 >>> new_bug.addCommentNotification(comment)
394 >>> notifications = getUtility(IBugNotificationSet).getNotificationsToSend()400 >>> notifications = getUtility(
401 ... IBugNotificationSet).getNotificationsToSend()
395 >>> len(notifications)402 >>> len(notifications)
396 1403 1
397404
398 >>> for bug_notifications, messages in get_email_notifications(notifications):405 >>> for bug_notifications, messages in (
406 ... get_email_notifications(notifications)):
399 ... for message in messages:407 ... for message in messages:
400 ... print_notification(message)408 ... print_notification(message)
401 To: support@ubuntu.com409 To: support@ubuntu.com
@@ -436,7 +444,8 @@
436 >>> flush_notifications()444 >>> flush_notifications()
437445
438446
439== Security Vulnerabilities ==447Security Vulnerabilities
448------------------------
440449
441When a new security related bug is filed, a small notification is450When a new security related bug is filed, a small notification is
442inserted at the top of the message body.451inserted at the top of the message body.
@@ -499,7 +508,8 @@
499 >>> flush_notifications()508 >>> flush_notifications()
500509
501510
502== The cronscript ==511The cronscript
512--------------
503513
504There's a cronsript which does the sending of the email. Let's add a514There's a cronsript which does the sending of the email. Let's add a
505few notifications to show that it works.515few notifications to show that it works.
@@ -528,7 +538,8 @@
528 ... '** Summary changed to: New summary.', sample_person,538 ... '** Summary changed to: New summary.', sample_person,
529 ... when=ten_minutes_ago)539 ... when=ten_minutes_ago)
530540
531 >>> notifications = getUtility(IBugNotificationSet).getNotificationsToSend()541 >>> notifications = getUtility(
542 ... IBugNotificationSet).getNotificationsToSend()
532 >>> len(notifications)543 >>> len(notifications)
533 6544 6
534545
@@ -620,7 +631,8 @@
620 >>> flush_notifications()631 >>> flush_notifications()
621632
622633
623== The X-Launchpad-Bug header ==634The X-Launchpad-Bug header
635--------------------------
624636
625When a notification is sent out about a bug, the X-Launchpad-Bug header is637When a notification is sent out about a bug, the X-Launchpad-Bug header is
626filled with data about that bug:638filled with data about that bug:
@@ -658,7 +670,8 @@
658 False670 False
659671
660672
661== The X-Launchpad-Bug-Tags header ==673The X-Launchpad-Bug-Tags header
674-------------------------------
662675
663First, a helper function that triggers notifications by adding a676First, a helper function that triggers notifications by adding a
664comment to a given bug, another that returns a sorted list of new677comment to a given bug, another that returns a sorted list of new
@@ -723,7 +736,8 @@
723 ... message.get_all('X-Launchpad-Bug-Tags')736 ... message.get_all('X-Launchpad-Bug-Tags')
724737
725738
726== The X-Launchpad-Bug-Private header ==739The X-Launchpad-Bug-Private header
740----------------------------------
727741
728When a notification is sent out about a bug, the742When a notification is sent out about a bug, the
729X-Launchpad-Bug-Private header shows if the bug is marked as743X-Launchpad-Bug-Private header shows if the bug is marked as
@@ -748,7 +762,8 @@
748 mark@example.com ['yes']762 mark@example.com ['yes']
749763
750764
751== The X-Launchpad-Bug-Security-Vulnerability header ==765The X-Launchpad-Bug-Security-Vulnerability header
766-------------------------------------------------
752767
753When a notification is sent out about a bug, the768When a notification is sent out about a bug, the
754X-Launchpad-Bug-Security-Vulnerability header records if the bug is a769X-Launchpad-Bug-Security-Vulnerability header records if the bug is a
@@ -776,7 +791,8 @@
776 mark@example.com ['yes']791 mark@example.com ['yes']
777792
778793
779== The X-Launchpad-Bug-Commenters header ==794The X-Launchpad-Bug-Commenters header
795-------------------------------------
780796
781The X-Launchpad-Bug-Recipient-Commented header lists all user IDs of797The X-Launchpad-Bug-Recipient-Commented header lists all user IDs of
782people who have ever commented on the bug. It's a space-separated798people who have ever commented on the bug. It's a space-separated
@@ -809,7 +825,8 @@
809 name12 name16825 name12 name16
810826
811827
812== The X-Launchpad-Bug-Reporter header ==828The X-Launchpad-Bug-Reporter header
829-----------------------------------
813830
814The X-Launchpad-Bug-Reporter header contains information about the Launchpad831The X-Launchpad-Bug-Reporter header contains information about the Launchpad
815user who originally reported the bug and opened the bug's first bug task.832user who originally reported the bug and opened the bug's first bug task.
@@ -819,7 +836,8 @@
819 Foo Bar (name16)836 Foo Bar (name16)
820837
821838
822== Verbose bug notifications ==839Verbose bug notifications
840-------------------------
823841
824It is possible for users to have all the bug notifications which they842It is possible for users to have all the bug notifications which they
825receive include the bug description and status. This helps in those843receive include the bug description and status. This helps in those
@@ -1016,7 +1034,8 @@
1016 ----------------------------------------------------------------------1034 ----------------------------------------------------------------------
10171035
10181036
1019== Notification Recipients ==1037Notification Recipients
1038-----------------------
10201039
1021Bug notifications are sent to direct subscribers of a bug as well as to1040Bug notifications are sent to direct subscribers of a bug as well as to
1022structural subscribers. Structural subcribers can select the1041structural subscribers. Structural subcribers can select the
10231042
=== modified file 'lib/lp/bugs/tests/test_bugchanges.py'
--- lib/lp/bugs/tests/test_bugchanges.py 2010-08-20 20:31:18 +0000
+++ lib/lp/bugs/tests/test_bugchanges.py 2010-09-02 10:32:47 +0000
@@ -1292,8 +1292,17 @@
12921292
1293 expected_notification = {1293 expected_notification = {
1294 'person': self.user,1294 'person': self.user,
1295 'text': ("** This bug has been marked a duplicate of bug %d\n"1295 'text': (
1296 " %s" % (self.bug.id, self.bug.title)),1296 "** This bug has been marked a duplicate of bug "
1297 "%(bug_id)d\n %(bug_title)s\n"
1298 " * You can subscribe to bug %(bug_id)d by following "
1299 "this link: %(subscribe_link)s" % {
1300 'bug_id': self.bug.id,
1301 'bug_title': self.bug.title,
1302 'subscribe_link': canonical_url(
1303 self.bug.default_bugtask,
1304 view_name='+subscribe'),
1305 }),
1297 'recipients': duplicate_bug_recipients,1306 'recipients': duplicate_bug_recipients,
1298 }1307 }
12991308
@@ -1361,11 +1370,21 @@
13611370
1362 expected_notification = {1371 expected_notification = {
1363 'person': self.user,1372 'person': self.user,
1364 'text': ("** This bug is no longer a duplicate of bug %d\n"1373 'text': (
1365 " %s\n"1374 "** This bug is no longer a duplicate of bug "
1366 "** This bug has been marked a duplicate of bug %d\n"1375 "%(bug_one_id)d\n %(bug_one_title)s\n"
1367 " %s" % (bug_one.id, bug_one.title,1376 "** This bug has been marked a duplicate of bug "
1368 bug_two.id, bug_two.title)),1377 "%(bug_two_id)d\n %(bug_two_title)s\n"
1378 " * You can subscribe to bug %(bug_two_id)d by following "
1379 "this link: %(subscribe_link)s" % {
1380 'bug_one_id': bug_one.id,
1381 'bug_one_title': bug_one.title,
1382 'bug_two_id': bug_two.id,
1383 'bug_two_title': bug_two.title,
1384 'subscribe_link': canonical_url(
1385 bug_two.default_bugtask,
1386 view_name='+subscribe'),
1387 }),
1369 'recipients': bug_recipients,1388 'recipients': bug_recipients,
1370 }1389 }
13711390
@@ -1474,10 +1493,20 @@
1474 expected_notification = {1493 expected_notification = {
1475 'person': self.user,1494 'person': self.user,
1476 'text': (1495 'text': (
1477 "** This bug is no longer a duplicate of private bug %d\n"1496 "** This bug is no longer a duplicate of private bug "
1478 "** This bug has been marked a duplicate of bug %d\n"1497 "%(private_bug_id)d\n"
1479 " %s" % (private_bug.id, public_bug.id,1498 "** This bug has been marked a duplicate of bug "
1480 public_bug.title)),1499 "%(public_bug_id)d\n %(public_bug_title)s\n"
1500 " * You can subscribe to bug %(public_bug_id)d by following "
1501 "this link: %(subscribe_link)s" % {
1502 'private_bug_id': private_bug.id,
1503 'private_bug_title': private_bug.title,
1504 'public_bug_id': public_bug.id,
1505 'public_bug_title': public_bug.title,
1506 'subscribe_link': canonical_url(
1507 public_bug.default_bugtask,
1508 view_name='+subscribe'),
1509 }),
1481 'recipients': bug_recipients,1510 'recipients': bug_recipients,
1482 }1511 }
14831512