Repository: fedora-infra/bodhi

Issue:
BuildrootOverrides should not be allowed if the test gating status is failed
We should add a check that disallows creating BROs if the test gating status is failed.
BuildrootOverrides should not be allowed if the test gating status is failed
We should add a check that disallows creating BROs if the test gating status is failed.


Discussion:

Resolving patch:
diff --git a/bodhi/server/validators.py b/bodhi/server/validators.py
--- a/bodhi/server/validators.py
+++ b/bodhi/server/validators.py
@@ -45,6 +45,7 @@
     ReleaseState,
     Stack,
     TestCase,
+    TestGatingStatus,
     Update,
     UpdateStatus,
     UpdateRequest,
@@ -1068,6 +1069,13 @@ def _validate_override_build(request, nvr, db):
     """
     build = Build.get(nvr)
     if build is not None:
+        if not request.validated['edited'] and \
+                build.update is not None and \
+                build.update.test_gating_status == TestGatingStatus.failed:
+            request.errors.add("body", "nvr", "Cannot create a buildroot override"
+                               " if build's test gating status is failed.")
+            return
+
         if not build.release:
             # Oddly, the build has no associated release.  Let's try to figure
             # that out and apply it.


Test patch:
diff --git a/bodhi/tests/server/services/test_overrides.py b/bodhi/tests/server/services/test_overrides.py
--- a/bodhi/tests/server/services/test_overrides.py
+++ b/bodhi/tests/server/services/test_overrides.py
@@ -23,7 +23,15 @@
 import mock
 import webtest
 
-from bodhi.server.models import BuildrootOverride, RpmBuild, RpmPackage, Release, User
+from bodhi.server.models import (
+    BuildrootOverride,
+    RpmBuild,
+    RpmPackage,
+    Release,
+    User,
+    Update,
+    TestGatingStatus,
+)
 from bodhi.server import main
 from bodhi.tests.server import base
 
@@ -306,6 +314,37 @@ def test_create_override(self, publish):
                          expiration_date.strftime("%Y-%m-%d %H:%M:%S"))
         self.assertEqual(o['expired_date'], None)
 
+    @mock.patch('bodhi.server.notifications.publish')
+    def test_create_override_for_build_with_test_gating_status_failed(self, publish):
+        """
+        Test that Override is not created when the test gating status is failed.
+        """
+        release = Release.get(u'F17')
+        package = RpmPackage(name=u'not-bodhi')
+        self.db.add(package)
+        build = RpmBuild(nvr=u'not-bodhi-2.0-2.fc17', package=package, release=release)
+        update = Update.query.first()
+        update.builds.append(build)
+        update.test_gating_status = TestGatingStatus.failed
+        self.db.add(build)
+        self.db.flush()
+
+        expiration_date = datetime.utcnow() + timedelta(days=1)
+
+        data = {'nvr': build.nvr, 'notes': u'blah blah blah',
+                'expiration_date': expiration_date,
+                'csrf_token': self.get_csrf_token()}
+        res = self.app.post('/overrides/', data, status=400)
+
+        publish.assert_not_called()
+
+        errors = res.json_body['errors']
+        self.assertEqual(len(errors), 1)
+        self.assertEqual(errors[0]['name'], 'nvr')
+        self.assertEqual(errors[0]['description'],
+                         "Cannot create a buildroot override if "
+                         "build's test gating status is failed.")
+
     @mock.patch('bodhi.server.notifications.publish')
     def test_create_duplicate_override(self, publish):
         release = Release.get(u'F17')
diff --git a/bodhi/tests/server/test_validators.py b/bodhi/tests/server/test_validators.py
--- a/bodhi/tests/server/test_validators.py
+++ b/bodhi/tests/server/test_validators.py
@@ -565,6 +565,7 @@ def test_no_build_exception(self):
         request.db = self.db
         request.errors = Errors()
         request.koji.listTags.side_effect = IOError('You forgot to pay your ISP.')
+        request.validated = {'edited': None}
 
         validators._validate_override_build(request, 'does not exist', self.db)
 
@@ -581,6 +582,7 @@ def test_indeterminate_release(self):
         request.db = self.db
         request.errors = Errors()
         request.koji.listTags.return_value = [{'name': 'invalid'}]
+        request.validated = {'edited': None}
         build = models.Build.query.first()
         build.release = None
         self.db.commit()
@@ -602,6 +604,7 @@ def test_no_release(self):
         request.db = self.db
         request.errors = Errors()
         request.koji.listTags.return_value = [{'name': release.candidate_tag}]
+        request.validated = {'edited': None}
         build = models.Build.query.first()
         build.release = None
         self.db.commit()
@@ -620,6 +623,7 @@ def test_wrong_tag(self, get_session):
         request.db = self.db
         request.errors = Errors()
         request.koji.listTags.return_value = [{'name': release.stable_tag}]
+        request.validated = {'edited': None}
         get_session.return_value.listTags.return_value = request.koji.listTags.return_value
         build = models.Build.query.first()
 
@@ -631,6 +635,25 @@ def test_wrong_tag(self, get_session):
               'description': "Invalid build.  It must be tagged as either candidate or testing."}])
         self.assertEqual(request.errors.status, exceptions.HTTPBadRequest.code)
 
+    def test_test_gating_status_is_failed(self):
+        """If a build's test gating status is failed, the validator should complain."""
+        request = mock.Mock()
+        request.db = self.db
+        request.errors = Errors()
+        request.validated = {'edited': None}
+        build = models.Build.query.first()
+        build.update.test_gating_status = models.TestGatingStatus.failed
+        self.db.commit()
+
+        validators._validate_override_build(request, build.nvr, self.db)
+
+        self.assertEqual(
+            request.errors,
+            [{'location': 'body', 'name': 'nvr',
+              'description': "Cannot create a buildroot override if build's "
+                             "test gating status is failed."}])
+        self.assertEqual(request.errors.status, exceptions.HTTPBadRequest.code)
+
 
 class TestValidateOverrideBuilds(BaseTestCase):
     """Test the validate_override_builds() function."""