Repository: fedora-infra/bodhi

Issue:
Disable manual creation of updates for releases not composed by Bodhi
For whatever reason, it may happen that sometimes Bodhi misses a fedora-message for a newly created build for Rawhide. This means that the update isn't automatically created and the build doesn't get tagged into rawhide.

Now, a user may be tempted to create that update manually, but that's the wrong thing to do: since Bodhi doesn't compose Rawhide, the update will never be pushed to testing/stable.

I think that in such situation all that the users should do is to remove the "updates-candidate" from the affected build and then re-add the same tag. This will trigger another fedora-message that (hopefully) will be caught by Bodhi so that the update will be automatically created as usual.

So we should disallow users to post such updates (if they don't come from side-tags) and document the correct way in docs.

Any thoughts?


Discussion:

Resolving patch:
diff --git a/bodhi/server/services/updates.py b/bodhi/server/services/updates.py
--- a/bodhi/server/services/updates.py
+++ b/bodhi/server/services/updates.py
@@ -524,6 +524,18 @@ def new_update(request):
             builds.append(build)
             releases.add(request.buildinfo[build.nvr]['release'])
 
+        # Disable manual updates for releases not composed by Bodhi
+        # see #4058
+        if not from_tag:
+            for release in releases:
+                if not release.composed_by_bodhi:
+                    request.errors.add('body', 'builds',
+                                       "Cannot manually create updates for a Release which is not "
+                                       "composed by Bodhi.\nRead the 'Automatic updates' page in "
+                                       "Bodhi docs about this error.")
+                    request.db.rollback()
+                    return
+
         # We want to go ahead and commit the transaction now so that the Builds are in the database.
         # Otherwise, there will be a race condition between robosignatory signing the Builds and the
         # signed handler attempting to mark the builds as signed. When we lose that race, the signed


Test patch:
diff --git a/bodhi/tests/server/services/test_updates.py b/bodhi/tests/server/services/test_updates.py
--- a/bodhi/tests/server/services/test_updates.py
+++ b/bodhi/tests/server/services/test_updates.py
@@ -267,6 +267,29 @@ def test_new_rpm_update(self, *args):
         assert up['karma'] == 0
         assert up['requirements'] == 'rpmlint'
 
+    @mock.patch.dict('bodhi.server.validators.config', {'acl_system': 'dummy'})
+    @mock.patch(**mock_uuid4_version1)
+    @mock.patch(**mock_valid_requirements)
+    def test_new_rawhide_rpm_update(self, *args):
+        """Posting a new update against Rawhide should fail."""
+        release = Release.query.one()
+        release.composed_by_bodhi = False
+        self.db.commit()
+        with fml_testing.mock_sends():
+            res = self.app.post_json('/updates/', self.get_update('bodhi-2.0.0-2.fc17'),
+                                     status=400)
+
+        expected_error = {
+            "location": "body",
+            "name": "builds",
+            "description": ("Cannot manually create updates for a Release which is not "
+                            "composed by Bodhi.\nRead the 'Automatic updates' page in "
+                            "Bodhi docs about this error.")
+        }
+        assert expected_error in res.json_body['errors']
+        build = self.db.query(RpmBuild).filter_by(nvr='bodhi-2.0.0-2.fc17').first()
+        assert build is None
+
     @mock.patch.dict('bodhi.server.validators.config', {'acl_system': 'dummy'})
     @mock.patch(**mock_uuid4_version1)
     @mock.patch(**mock_valid_requirements)
diff --git a/devel/ci/integration/tests/test_bodhi_tasks.py b/devel/ci/integration/tests/test_bodhi_tasks.py
--- a/devel/ci/integration/tests/test_bodhi_tasks.py
+++ b/devel/ci/integration/tests/test_bodhi_tasks.py
@@ -83,8 +83,8 @@ def find_update():
             "FROM updates u "
             "JOIN releases r ON u.release_id = r.id "
             "JOIN users us ON u.user_id = us.id "
-            "WHERE r.state != 'archived' AND u.locked = FALSE "
-            "AND u.status IN ('pending', 'testing') "
+            "WHERE r.state != 'archived' AND r.composed_by_bodhi = TRUE "
+            "AND u.locked = FALSE AND u.status IN ('pending', 'testing') "
             "AND us.name NOT LIKE '%packagerbot%' "
             "ORDER BY u.date_submitted DESC LIMIT 1"
         )