Repository: fedora-infra/bodhi

Issue:
Do not send multiple notifications due to BZ ticket updates
When my update was pushed into stable, I received two notifications from BZ [1], one with comment and second with remaining flags modified. Is there chance to do this in one action, preventing BZ to send multiple emails?

[1] https://bugzilla.redhat.com/show_bug.cgi?id=1253872



Discussion:
Just FYI, it used to be done in one step:

https://bugzilla.redhat.com/show_bug.cgi?id=1227779#c16

:+1: probably possible.  Will just need to change the `bodhi.bugtracker` object's behavior.  Sorry for the noise!


Resolving patch:
diff --git a/bodhi/server/bugs.py b/bodhi/server/bugs.py
--- a/bodhi/server/bugs.py
+++ b/bodhi/server/bugs.py
@@ -263,15 +263,18 @@ def update_details(self, bug, bug_entity):
         if 'security' in [keyword.lower() for keyword in keywords]:
             bug_entity.security = True
 
-    def modified(self, bug_id):
+    def modified(self, bug_id, comment):
         """
         Change the status of this bug to MODIFIED if not already MODIFIED, VERIFIED, or CLOSED.
 
         This method will only operate on bugs that are associated with products listed
         in the bz_products setting.
 
+        This will also comment on the bug stating that an update has been submitted.
+
         Args:
             bug_id (basestring or int): The bug you wish to mark MODIFIED.
+            comment (basestring): The comment to be included with the state change.
         """
         try:
             bug = self.bz.getbug(bug_id)
@@ -280,7 +283,9 @@ def modified(self, bug_id):
                 return
             if bug.bug_status not in ('MODIFIED', 'VERIFIED', 'CLOSED'):
                 log.info('Setting bug #%d status to MODIFIED' % bug_id)
-                bug.setstatus('MODIFIED')
+                bug.setstatus('MODIFIED', comment=comment)
+            else:
+                bug.addcomment(comment)
         except Exception:
             log.exception("Unable to alter bug #%d" % bug_id)
 
diff --git a/bodhi/server/consumers/updates.py b/bodhi/server/consumers/updates.py
--- a/bodhi/server/consumers/updates.py
+++ b/bodhi/server/consumers/updates.py
@@ -194,9 +194,8 @@ def work_on_bugs(self, session, update, bugs):
                 log.info("Commenting on %r" % bug.bug_id)
                 comment = config['initial_bug_msg'] % (
                     update.title, update.release.long_name, update.abs_url())
-                bug.add_comment(update, comment)
 
                 log.info("Modifying %r" % bug.bug_id)
-                bug.modified(update)
+                bug.modified(update, comment)
             except Exception:
                 log.warning('Error occurred during updating single bug', exc_info=True)
diff --git a/bodhi/server/models.py b/bodhi/server/models.py
--- a/bodhi/server/models.py
+++ b/bodhi/server/models.py
@@ -4164,17 +4164,19 @@ def close_bug(self, update):
         ])
         bugs.bugtracker.close(self.bug_id, versions=versions, comment=self.default_message(update))
 
-    def modified(self, update):
+    def modified(self, update, comment):
         """
         Change the status of this bug to MODIFIED unless it is a parent security bug.
 
+        Also, comment on the bug stating that an update has been submitted.
+
         Args:
             update (Update): The update that is associated with this bug.
         """
         if update.type is UpdateType.security and self.parent:
             log.debug('Not modifying on parent security bug %s', self.bug_id)
         else:
-            bugs.bugtracker.modified(self.bug_id)
+            bugs.bugtracker.modified(self.bug_id, comment)
 
 
 user_group_table = Table('user_group_table', Base.metadata,


Test patch:
diff --git a/bodhi/tests/server/test_bugs.py b/bodhi/tests/server/test_bugs.py
--- a/bodhi/tests/server/test_bugs.py
+++ b/bodhi/tests/server/test_bugs.py
@@ -268,17 +268,31 @@ def test_getbug(self):
     @mock.patch('bodhi.server.bugs.log.info')
     @mock.patch.dict('bodhi.server.bugs.config', {'bz_products': 'aproduct'})
     def test_modified(self, info):
-        """Test the modified() method"""
+        """Ensure correct execution of the modified() method."""
         bz = bugs.Bugzilla()
         bz._bz = mock.MagicMock()
         bz._bz.getbug.return_value.product = 'aproduct'
         bz._bz.getbug.return_value.bug_status = 'NEW'
 
-        bz.modified(1411188)
+        bz.modified(1411188, 'A mean message.')
 
         bz._bz.getbug.assert_called_once_with(1411188)
         info.assert_called_once_with("Setting bug #1411188 status to MODIFIED")
-        self.assertEqual(bz._bz.getbug.return_value.setstatus.call_count, 1)
+        bz._bz.getbug.return_value.setstatus.assert_called_once_with('MODIFIED',
+                                                                     comment='A mean message.')
+
+    @mock.patch.dict('bodhi.server.bugs.config', {'bz_products': 'aproduct'})
+    def test_modified_after_verified(self):
+        """Test the modified() method when the status of bug is VERIFIED."""
+        bz = bugs.Bugzilla()
+        bz._bz = mock.MagicMock()
+        bz._bz.getbug.return_value.product = 'aproduct'
+        bz._bz.getbug.return_value.bug_status = 'VERIFIED'
+
+        bz.modified(1411188, 'A mean message.')
+
+        bz._bz.getbug.assert_called_once_with(1411188)
+        bz._bz.getbug.return_value.addcomment.assert_called_once_with('A mean message.')
 
     @mock.patch('bodhi.server.bugs.log.info')
     def test_modified_product_skipped(self, info):
@@ -287,7 +301,7 @@ def test_modified_product_skipped(self, info):
         bz._bz = mock.MagicMock()
         bz._bz.getbug.return_value.product = 'not fedora!'
 
-        bz.modified(1411188)
+        bz.modified(1411188, 'A mean message.')
 
         bz._bz.getbug.assert_called_once_with(1411188)
         info.assert_called_once_with("Skipping set modified on 'not fedora!' bug #1411188")
@@ -300,7 +314,7 @@ def test_modified_exception(self, exception_log):
         bz._bz = mock.MagicMock()
         bz._bz.getbug.side_effect = Exception()
 
-        bz.modified(1411188)
+        bz.modified(1411188, 'A mean message.')
 
         bz._bz.getbug.assert_called_once_with(1411188)
         exception_log.assert_called_once_with("Unable to alter bug #1411188")