Repository: fedora-infra/bodhi

Issue:
When a package is update but change the bug type from bugfix to security, bodhi does not obsolete the previous one
Hello
Something wrong it is happening look at https://bodhi.fedoraproject.org/updates/?packages=p7zip

p7zip-15.09-3.fc23 now says that is security when it isn't .
p7zip-15.09-4.fc23 doesn't obsolete p7zip-15.09-3.fc23 

Anyway let's wait for pushes , to see if situation gets better .

Thanks.



Discussion:
bodhi publish both package clearly a bug , bodhi when I change the type of the package doesn't obsolete the package with same name 

p7zip-15.09-3.fc23 is bugfix type 
p7zip-15.09-4.fc23 is security type

bodhi have to obsolete p7zip-15.09-3.fc23 ! 

The auto-obsoletion code doesn't care about the update `type`. I think this issue is due to the fact that `-3` was `locked` and actively being pushed to `testing` when `-4` was submitted, thus bodhi did not obsolete it.

Actually, it doesn't obsolete updates that have an open `request`, which `-3` had. Now that we have proper locking, we can now obsolete updates with an open request that hasn't been pushed yet.


Resolving patch:
diff --git a/bodhi/models/models.py b/bodhi/models/models.py
--- a/bodhi/models/models.py
+++ b/bodhi/models/models.py
@@ -880,7 +880,7 @@ def obsolete_older_updates(self, request):
             for oldBuild in db.query(Build).join(Update).filter(
                 and_(Build.nvr != build.nvr,
                      Build.package == build.package,
-                     Update.request == None,
+                     Update.locked == False,
                      Update.release == self.release,
                      or_(Update.status == UpdateStatus.testing,
                          Update.status == UpdateStatus.pending))


Test patch:
diff --git a/bodhi/tests/__init__.py b/bodhi/tests/__init__.py
--- a/bodhi/tests/__init__.py
+++ b/bodhi/tests/__init__.py
@@ -90,4 +90,6 @@ def populate(db):
                                  expiration_date=expiration_date)
     db.add(override)
 
+    update.locked = True
+
     db.flush()
diff --git a/bodhi/tests/functional/test_updates.py b/bodhi/tests/functional/test_updates.py
--- a/bodhi/tests/functional/test_updates.py
+++ b/bodhi/tests/functional/test_updates.py
@@ -448,7 +448,7 @@ def test_list_updates(self):
         self.assertEquals(up['date_submitted'], u'1984-11-02 00:00:00')
         self.assertEquals(up['date_modified'], None)
         self.assertEquals(up['date_pushed'], None)
-        self.assertEquals(up['locked'], False)
+        self.assertEquals(up['locked'], True)
         self.assertEquals(up['alias'], alias)
         self.assertEquals(up['karma'], 1)
         self.assertEquals(up['url'], '%s/updates/%s' % (baseurl, alias))
@@ -539,7 +539,7 @@ def test_list_updates_by_approved_since(self):
         self.assertEquals(up['date_submitted'], u'1984-11-02 00:00:00')
         self.assertEquals(up['date_approved'], now.strftime("%Y-%m-%d %H:%M:%S"))
         self.assertEquals(up['date_pushed'], None)
-        self.assertEquals(up['locked'], False)
+        self.assertEquals(up['locked'], True)
         self.assertEquals(up['alias'], u'FEDORA-%s-a3bbe1a8f2' % YEAR)
         self.assertEquals(up['karma'], 1)
         self.assertEquals(len(up['bugs']), 1)
@@ -592,7 +592,7 @@ def test_list_updates_by_approved_before(self):
         self.assertEquals(up['date_submitted'], u'1984-11-02 00:00:00')
         self.assertEquals(up['date_approved'], now.strftime("%Y-%m-%d %H:%M:%S"))
         self.assertEquals(up['date_pushed'], None)
-        self.assertEquals(up['locked'], False)
+        self.assertEquals(up['locked'], True)
         self.assertEquals(up['alias'], u'FEDORA-%s-a3bbe1a8f2' % YEAR)
         self.assertEquals(up['karma'], 1)
         self.assertEquals(len(up['bugs']), 1)
@@ -627,7 +627,7 @@ def test_list_updates_by_bugs(self):
         self.assertEquals(up['date_modified'], None)
         self.assertEquals(up['date_approved'], None)
         self.assertEquals(up['date_pushed'], None)
-        self.assertEquals(up['locked'], False)
+        self.assertEquals(up['locked'], True)
         self.assertEquals(up['alias'], u'FEDORA-%s-a3bbe1a8f2' % YEAR)
         self.assertEquals(up['karma'], 1)
         self.assertEquals(len(up['bugs']), 1)
@@ -666,7 +666,7 @@ def test_list_updates_by_critpath(self):
         self.assertEquals(up['date_modified'], None)
         self.assertEquals(up['date_approved'], None)
         self.assertEquals(up['date_pushed'], None)
-        self.assertEquals(up['locked'], False)
+        self.assertEquals(up['locked'], True)
         self.assertEquals(up['alias'], u'FEDORA-%s-a3bbe1a8f2' % YEAR)
         self.assertEquals(up['karma'], 1)
 
@@ -699,7 +699,7 @@ def test_list_updates_by_cves(self):
         self.assertEquals(up['date_modified'], None)
         self.assertEquals(up['date_approved'], None)
         self.assertEquals(up['date_pushed'], None)
-        self.assertEquals(up['locked'], False)
+        self.assertEquals(up['locked'], True)
         self.assertEquals(up['alias'], u'FEDORA-%s-a3bbe1a8f2' % YEAR)
         self.assertEquals(up['karma'], 1)
         #self.assertEquals(up['cves'][0]['cve_id'], "CVE-1985-0110")
@@ -758,7 +758,7 @@ def test_list_updates_by_date_submitted_valid(self):
         self.assertEquals(up['date_modified'], None)
         self.assertEquals(up['date_approved'], None)
         self.assertEquals(up['date_pushed'], None)
-        self.assertEquals(up['locked'], False)
+        self.assertEquals(up['locked'], True)
         self.assertEquals(up['alias'], u'FEDORA-%s-a3bbe1a8f2' % YEAR)
         self.assertEquals(up['karma'], 1)
 
@@ -800,12 +800,12 @@ def test_list_updates_by_date_submitted_before_valid(self):
         self.assertEquals(up['date_modified'], None)
         self.assertEquals(up['date_approved'], None)
         self.assertEquals(up['date_pushed'], None)
-        self.assertEquals(up['locked'], False)
+        self.assertEquals(up['locked'], True)
         self.assertEquals(up['alias'], u'FEDORA-%s-a3bbe1a8f2' % YEAR)
         self.assertEquals(up['karma'], 1)
 
     def test_list_updates_by_locked(self):
-        res = self.app.get('/updates/', {"locked": "false"})
+        res = self.app.get('/updates/', {"locked": "true"})
         body = res.json_body
         self.assertEquals(len(body['updates']), 1)
 
@@ -824,7 +824,7 @@ def test_list_updates_by_locked(self):
         self.assertEquals(up['date_modified'], None)
         self.assertEquals(up['date_approved'], None)
         self.assertEquals(up['date_pushed'], None)
-        self.assertEquals(up['locked'], False)
+        self.assertEquals(up['locked'], True)
         self.assertEquals(up['alias'], u'FEDORA-%s-a3bbe1a8f2' % YEAR)
         self.assertEquals(up['karma'], 1)
 
@@ -871,7 +871,7 @@ def test_list_updates_by_modified_since(self):
         self.assertEquals(up['date_modified'], now.strftime("%Y-%m-%d %H:%M:%S"))
         self.assertEquals(up['date_approved'], None)
         self.assertEquals(up['date_pushed'], None)
-        self.assertEquals(up['locked'], False)
+        self.assertEquals(up['locked'], True)
         self.assertEquals(up['alias'], u'FEDORA-%s-a3bbe1a8f2' % YEAR)
         self.assertEquals(up['karma'], 1)
         self.assertEquals(len(up['bugs']), 1)
@@ -922,7 +922,7 @@ def test_list_updates_by_modified_before(self):
         self.assertEquals(up['date_modified'], now.strftime("%Y-%m-%d %H:%M:%S"))
         self.assertEquals(up['date_approved'], None)
         self.assertEquals(up['date_pushed'], None)
-        self.assertEquals(up['locked'], False)
+        self.assertEquals(up['locked'], True)
         self.assertEquals(up['alias'], u'FEDORA-%s-a3bbe1a8f2' % YEAR)
         self.assertEquals(up['karma'], 1)
         self.assertEquals(len(up['bugs']), 1)
@@ -957,7 +957,7 @@ def test_list_updates_by_package(self):
         self.assertEquals(up['date_modified'], None)
         self.assertEquals(up['date_approved'], None)
         self.assertEquals(up['date_pushed'], None)
-        self.assertEquals(up['locked'], False)
+        self.assertEquals(up['locked'], True)
         self.assertEquals(up['alias'], u'FEDORA-%s-a3bbe1a8f2' % YEAR)
         self.assertEquals(up['karma'], 1)
 
@@ -985,7 +985,7 @@ def test_list_updates_by_builds(self):
         self.assertEquals(up['date_modified'], None)
         self.assertEquals(up['date_approved'], None)
         self.assertEquals(up['date_pushed'], None)
-        self.assertEquals(up['locked'], False)
+        self.assertEquals(up['locked'], True)
         self.assertEquals(up['alias'], u'FEDORA-%s-a3bbe1a8f2' % YEAR)
         self.assertEquals(up['karma'], 1)
 
@@ -1014,7 +1014,7 @@ def test_list_updates_by_pushed(self):
         self.assertEquals(up['date_modified'], None)
         self.assertEquals(up['date_approved'], None)
         self.assertEquals(up['date_pushed'], None)
-        self.assertEquals(up['locked'], False)
+        self.assertEquals(up['locked'], True)
         self.assertEquals(up['alias'], u'FEDORA-%s-a3bbe1a8f2' % YEAR)
         self.assertEquals(up['karma'], 1)
         self.assertEquals(up['pushed'], False)
@@ -1061,7 +1061,7 @@ def test_list_updates_by_pushed_since(self):
         self.assertEquals(up['date_submitted'], u'1984-11-02 00:00:00')
         self.assertEquals(up['date_approved'], None)
         self.assertEquals(up['date_pushed'], now.strftime("%Y-%m-%d %H:%M:%S"))
-        self.assertEquals(up['locked'], False)
+        self.assertEquals(up['locked'], True)
         self.assertEquals(up['alias'], u'FEDORA-%s-a3bbe1a8f2' % YEAR)
         self.assertEquals(up['karma'], 1)
         self.assertEquals(len(up['bugs']), 1)
@@ -1111,7 +1111,7 @@ def test_list_updates_by_pushed_before(self):
         self.assertEquals(up['date_submitted'], u'1984-11-02 00:00:00')
         self.assertEquals(up['date_approved'], None)
         self.assertEquals(up['date_pushed'], now.strftime("%Y-%m-%d %H:%M:%S"))
-        self.assertEquals(up['locked'], False)
+        self.assertEquals(up['locked'], True)
         self.assertEquals(up['alias'], u'FEDORA-%s-a3bbe1a8f2' % YEAR)
         self.assertEquals(up['karma'], 1)
         self.assertEquals(len(up['bugs']), 1)
@@ -1146,7 +1146,7 @@ def test_list_updates_by_release_name(self):
         self.assertEquals(up['date_modified'], None)
         self.assertEquals(up['date_approved'], None)
         self.assertEquals(up['date_pushed'], None)
-        self.assertEquals(up['locked'], False)
+        self.assertEquals(up['locked'], True)
         self.assertEquals(up['alias'], u'FEDORA-%s-a3bbe1a8f2' % YEAR)
         self.assertEquals(up['karma'], 1)
 
@@ -1170,7 +1170,7 @@ def test_list_updates_by_release_version(self):
         self.assertEquals(up['date_modified'], None)
         self.assertEquals(up['date_approved'], None)
         self.assertEquals(up['date_pushed'], None)
-        self.assertEquals(up['locked'], False)
+        self.assertEquals(up['locked'], True)
         self.assertEquals(up['alias'], u'FEDORA-%s-a3bbe1a8f2' % YEAR)
         self.assertEquals(up['karma'], 1)
 
@@ -1202,7 +1202,7 @@ def test_list_updates_by_request(self):
         self.assertEquals(up['date_modified'], None)
         self.assertEquals(up['date_approved'], None)
         self.assertEquals(up['date_pushed'], None)
-        self.assertEquals(up['locked'], False)
+        self.assertEquals(up['locked'], True)
         self.assertEquals(up['alias'], u'FEDORA-%s-a3bbe1a8f2' % YEAR)
         self.assertEquals(up['karma'], 1)
 
@@ -1236,7 +1236,7 @@ def test_list_updates_by_severity(self):
         self.assertEquals(up['date_modified'], None)
         self.assertEquals(up['date_approved'], None)
         self.assertEquals(up['date_pushed'], None)
-        self.assertEquals(up['locked'], False)
+        self.assertEquals(up['locked'], True)
         self.assertEquals(up['alias'], u'FEDORA-%s-a3bbe1a8f2' % YEAR)
         self.assertEquals(up['karma'], 1)
 
@@ -1269,7 +1269,7 @@ def test_list_updates_by_status(self):
         self.assertEquals(up['date_modified'], None)
         self.assertEquals(up['date_approved'], None)
         self.assertEquals(up['date_pushed'], None)
-        self.assertEquals(up['locked'], False)
+        self.assertEquals(up['locked'], True)
         self.assertEquals(up['alias'], u'FEDORA-%s-a3bbe1a8f2' % YEAR)
         self.assertEquals(up['karma'], 1)
 
@@ -1302,7 +1302,7 @@ def test_list_updates_by_suggest(self):
         self.assertEquals(up['date_modified'], None)
         self.assertEquals(up['date_approved'], None)
         self.assertEquals(up['date_pushed'], None)
-        self.assertEquals(up['locked'], False)
+        self.assertEquals(up['locked'], True)
         self.assertEquals(up['alias'], u'FEDORA-%s-a3bbe1a8f2' % YEAR)
         self.assertEquals(up['karma'], 1)
 
@@ -1335,7 +1335,7 @@ def test_list_updates_by_type(self):
         self.assertEquals(up['date_modified'], None)
         self.assertEquals(up['date_approved'], None)
         self.assertEquals(up['date_pushed'], None)
-        self.assertEquals(up['locked'], False)
+        self.assertEquals(up['locked'], True)
         self.assertEquals(up['alias'], u'FEDORA-%s-a3bbe1a8f2' % YEAR)
         self.assertEquals(up['karma'], 1)
 
@@ -1368,7 +1368,7 @@ def test_list_updates_by_username(self):
         self.assertEquals(up['date_modified'], None)
         self.assertEquals(up['date_approved'], None)
         self.assertEquals(up['date_pushed'], None)
-        self.assertEquals(up['locked'], False)
+        self.assertEquals(up['locked'], True)
         self.assertEquals(up['alias'], u'FEDORA-%s-a3bbe1a8f2' % YEAR)
         self.assertEquals(up['karma'], 1)
 
@@ -1778,11 +1778,15 @@ def test_obsoletion(self, publish, *args):
 
     @mock.patch(**mock_valid_requirements)
     @mock.patch('bodhi.notifications.publish')
-    def test_obsoletion_with_open_request(self, publish, *args):
+    def test_obsoletion_locked_with_open_request(self, publish, *args):
         nvr = 'bodhi-2.0.0-2.fc17'
         args = self.get_update(nvr)
         self.app.post_json('/updates/', args)
 
+        up = self.db.query(Update).filter_by(title=nvr).one()
+        up.locked = True
+        self.db.flush()
+
         args = self.get_update('bodhi-2.0.0-3.fc17')
         r = self.app.post_json('/updates/', args).json_body
         self.assertEquals(r['request'], 'testing')
@@ -1791,6 +1795,21 @@ def test_obsoletion_with_open_request(self, publish, *args):
         self.assertEquals(up.status, UpdateStatus.pending)
         self.assertEquals(up.request, UpdateRequest.testing)
 
+    @mock.patch(**mock_valid_requirements)
+    @mock.patch('bodhi.notifications.publish')
+    def test_obsoletion_locked_with_open_request(self, publish, *args):
+        nvr = 'bodhi-2.0.0-2.fc17'
+        args = self.get_update(nvr)
+        self.app.post_json('/updates/', args)
+
+        args = self.get_update('bodhi-2.0.0-3.fc17')
+        r = self.app.post_json('/updates/', args).json_body
+        self.assertEquals(r['request'], 'testing')
+
+        up = self.db.query(Update).filter_by(title=nvr).one()
+        self.assertEquals(up.status, UpdateStatus.obsolete)
+        self.assertEquals(up.request, None)
+
     @mock.patch(**mock_taskotron_results)
     @mock.patch(**mock_valid_requirements)
     def test_invalid_request(self, *args):
@@ -1817,6 +1836,8 @@ def test_invalid_request(self, *args):
     @mock.patch('bodhi.notifications.publish')
     def test_testing_request(self, publish, *args):
         """Test submitting a valid testing request"""
+        Update.get(u'bodhi-2.0-1.fc17', self.db).locked = False
+
         args = self.get_update()
         args['request'] = None
         resp = self.app.post_json(
@@ -1829,6 +1850,8 @@ def test_testing_request(self, publish, *args):
     @mock.patch(**mock_valid_requirements)
     def test_invalid_stable_request(self, *args):
         """Test submitting a stable request for an update that has yet to meet the stable requirements"""
+        Update.get(u'bodhi-2.0-1.fc17', self.db).locked = False
+
         args = self.get_update()
         resp = self.app.post_json(
             '/updates/%s/request' % args['builds'],
diff --git a/bodhi/tests/test_masher.py b/bodhi/tests/test_masher.py
--- a/bodhi/tests/test_masher.py
+++ b/bodhi/tests/test_masher.py
@@ -145,6 +145,11 @@ def test_invalid_signature(self, publish):
         """Make sure the masher ignores messages that aren't signed with the
         appropriate releng cert
         """
+        with self.db_factory() as session:
+            # Ensure that the update was locked
+            up = session.query(Update).one()
+            up.locked = False
+
         fakehub = FakeHub()
         fakehub.config['releng_fedmsg_certname'] = 'foo'
         self.masher = Masher(fakehub, db_factory=self.db_factory)
@@ -179,7 +184,7 @@ def test_push_invalid_update(self, publish):
     def test_update_locking(self, publish, *args):
         with self.db_factory() as session:
             up = session.query(Update).one()
-            self.assertFalse(up.locked)
+            up.locked = False
 
         self.masher.consume(self.msg)