Repository: fedora-infra/bodhi

Issue:
revoking the request on a pending update should set the status to revoked
it currently removed the request, but it leaves the status as pending (which is super confusing).



Discussion:
I would like to work on it. :)

can you give me the steps to duplicate this bug please?

So it's not really a bug, just non-obvious resulting behavior from a 'revoke'. So in `models.py` there are a bunch of `UpdateStatus` enumerated types, and I think we'll need a new `revoked` status, which will get set by `Update.set_request`. Then, writing a simple unit test for this should be pretty easy.

This might actually require an alembic db migration script as well?

Could we re-use the "unpushed" status (like [this one](https://bodhi.fedoraproject.org/updates/FEDORA-2015-15628)) or would you rather go with a new `revoked` status?

If the update has never been pushed to testing, you could say (in a way) that it is "unpushed".  No?

But if an update is `testing` with a `stable` request and you `revoke` it, it doesn't get `unpushed` and is still `testing`, as you're revoking the request, not the update itself... Not sure what the best solution is.

How about:
- If we're pending going to testing and we revoke, set the status to unpushed.
- If we're testing going to stable, and we revoke, keep the status at testing.

Does that cover all the cases?

hey, can i work on this bug ?

Please.  Whoever fixes it first gets :cake:!

@ralphbean i want to :) just tell me how to replicate the bug 

The best way is probably to try and write a test case for it that _fails_ in `bodhi/tests/functional/test_updates.py`.

Try to get the test suite running first with `nosetests`.

@rahulbajaj0509  seems to be a new contributor who wants to get started in case he isn't willing to take it up I will do it :) , thanks a ton @ralphbean 

(You two can work on it together, too... ;p)  @rahulbajaj0509, we often talk development in the `#fedora-apps` channel on the freenode IRC network if you'd like to join us there.

@ralphbean That will be amazing :) i would love to :)

> How about:
> 
>    If we're pending going to testing and we revoke, set the status to unpushed.
>    If we're testing going to stable, and we revoke, keep the status at testing.

and the result is that an obsolete update can't removed from updates-testing, see 
https://github.com/fedora-infra/bodhi/issues/693


Resolving patch:
diff --git a/bodhi/models/models.py b/bodhi/models/models.py
--- a/bodhi/models/models.py
+++ b/bodhi/models/models.py
@@ -1042,6 +1042,29 @@ def set_request(self, db, action, username):
             notifications.publish(topic=topic, msg=dict(
                 update=self, agent=username))
             return
+
+        # If status is pending going to testing request and action is revoke,
+        # set the status to unpushed
+        elif self.status is UpdateStatus.pending and self.request is UpdateRequest.testing \
+                and action is UpdateRequest.revoke:
+            self.status = UpdateStatus.unpushed
+            self.revoke()
+            flash_log("%s has been revoked." % self.title)
+            notifications.publish(topic=topic, msg=dict(
+                update=self, agent=username))
+            return
+
+        # If status is testing going to stable request and action is revoke,
+        # keep the status at testing
+        elif self.status is UpdateStatus.testing and self.request is UpdateRequest.stable \
+                and action is UpdateRequest.revoke:
+            self.status = UpdateStatus.testing
+            self.revoke()
+            flash_log("%s has been revoked." % self.title)
+            notifications.publish(topic=topic, msg=dict(
+                update=self, agent=username))
+            return
+
         elif action is UpdateRequest.revoke:
             self.revoke()
             flash_log("%s has been revoked." % self.title)


Test patch:
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
@@ -1867,6 +1867,52 @@ def test_testing_request(self, publish, *args):
         eq_(resp.json['update']['request'], 'testing')
         self.assertEquals(publish.call_args_list, [])
 
+    @mock.patch(**mock_taskotron_results)
+    @mock.patch(**mock_valid_requirements)
+    @mock.patch('bodhi.notifications.publish')
+    def test_revoke_action_for_stable_request(self, publish, *args):
+        """
+        Test revoke action for stable request on testing update
+        and check status after revoking the request
+        """
+        args = self.get_update('bodhi-2.0.0-3.fc17')
+        resp = self.app.post_json('/updates/', args)
+        up = self.db.query(Update).filter_by(title=resp.json['title']).one()
+        up.status = UpdateStatus.testing
+        up.request = UpdateRequest.stable
+        self.db.flush()
+
+        resp = self.app.post_json(
+            '/updates/%s/request' % args['builds'],
+            {'request': 'revoke', 'csrf_token': self.get_csrf_token()})
+        eq_(resp.json['update']['request'], None)
+        eq_(resp.json['update']['status'], 'testing')
+        publish.assert_called_with(
+                topic='update.request.revoke', msg=mock.ANY)
+
+    @mock.patch(**mock_taskotron_results)
+    @mock.patch(**mock_valid_requirements)
+    @mock.patch('bodhi.notifications.publish')
+    def test_revoke_action_for_testing_request(self, publish, *args):
+        """
+        Test revoke action for testing request on pending update
+        and check status after revoking the request
+        """
+        args = self.get_update('bodhi-2.0.0-3.fc17')
+        resp = self.app.post_json('/updates/', args)
+        up = self.db.query(Update).filter_by(title=resp.json['title']).one()
+        up.status = UpdateStatus.pending
+        up.request = UpdateRequest.testing
+        self.db.flush()
+
+        resp = self.app.post_json(
+            '/updates/%s/request' % args['builds'],
+            {'request': 'revoke', 'csrf_token': self.get_csrf_token()})
+        eq_(resp.json['update']['request'], None)
+        eq_(resp.json['update']['status'], 'unpushed')
+        publish.assert_called_with(
+                topic='update.request.revoke', msg=mock.ANY)
+
     @mock.patch(**mock_taskotron_results)
     @mock.patch(**mock_valid_requirements)
     def test_invalid_stable_request(self, *args):