diff --git a/bodhi/client/__init__.py b/bodhi/client/__init__.py index 497881b07d..6e95218ff9 100644 --- a/bodhi/client/__init__.py +++ b/bodhi/client/__init__.py @@ -59,7 +59,7 @@ def _warn_if_url_and_staging_set(ctx, param, value): click.option('--bugs', help='Comma-separated list of bug numbers', default=''), click.option('--close-bugs', default=True, is_flag=True, help='Automatically close bugs'), click.option('--request', help='Requested repository', - type=click.Choice(['testing', 'stable', 'unpush'])), + type=click.Choice(['testing', 'stable', 'unpush', 'batched'])), click.option('--autokarma', is_flag=True, help='Enable karma automatism'), click.option('--stable-karma', type=click.INT, help='Stable karma threshold'), click.option('--unstable-karma', type=click.INT, help='Unstable karma threshold'), @@ -274,7 +274,7 @@ def edit(user, password, url, **kwargs): @click.option('--releases', help='Updates for specific releases') @click.option('--locked', help='Updates that are in a locked state') @click.option('--request', help='Updates with a specific request', - type=click.Choice(['testing', 'stable', 'unpush'])) + type=click.Choice(['testing', 'stable', 'unpush', 'batched'])) @click.option('--submitted-since', help='Updates that have been submitted since a certain time') @click.option('--status', help='Filter by update status', @@ -324,7 +324,7 @@ def request(update, state, user, password, url, **kwargs): UPDATE: The title of the update (e.g. FEDORA-2017-f8e0ef2850) STATE: The state you wish to change the update\'s request to. Valid options are - testing, stable, obsolete, unpush, and revoke. + testing, stable, obsolete, unpush, batched, and revoke. """ # Developer Docs diff --git a/bodhi/server/config.py b/bodhi/server/config.py index 385ba0352c..41a1b29a04 100644 --- a/bodhi/server/config.py +++ b/bodhi/server/config.py @@ -510,6 +510,9 @@ class BodhiConfig(dict): 'value': ('%s has been pushed to the %s repository. If problems still persist, please ' 'make note of it in this bug report.'), 'validator': unicode}, + 'stable_from_batched_msg': { + 'value': ('This update has been dequeued from batched and is now entering stable.'), + 'validator': unicode}, 'stacks_enabled': { 'value': False, 'validator': _validate_bool}, diff --git a/bodhi/server/models.py b/bodhi/server/models.py index ab99deed08..55dcbb10d1 100644 --- a/bodhi/server/models.py +++ b/bodhi/server/models.py @@ -1732,7 +1732,7 @@ def set_request(self, db, action, username): # 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: + or UpdateRequest.batched and action is UpdateRequest.revoke: self.status = UpdateStatus.testing self.revoke() flash_log("%s has been revoked." % self.title) @@ -1748,7 +1748,7 @@ def set_request(self, db, action, username): return # Disable pushing critical path updates for pending releases directly to stable - if action is UpdateRequest.stable and self.critpath: + if action is (UpdateRequest.stable or UpdateRequest.batched) and self.critpath: if config.get('critpath.num_admin_approvals') is not None: if not self.critpath_approved: stern_note = ( @@ -1774,7 +1774,7 @@ def set_request(self, db, action, username): # Ensure this update meets the minimum testing requirements flash_notes = '' - if action is UpdateRequest.stable and not self.critpath: + if action is (UpdateRequest.stable or UpdateRequest.batched) and not self.critpath: # Check if we've met the karma requirements if (self.stable_karma not in (None, 0) and self.karma >= self.stable_karma) or self.critpath_approved: @@ -1799,7 +1799,7 @@ def set_request(self, db, action, username): # Add the appropriate 'pending' koji tag to this update, so tools like # AutoQA can mash repositories of them for testing. - if action is UpdateRequest.testing: + if action is UpdateRequest.testing or UpdateRequest.batched: self.add_tag(self.release.pending_signing_tag) elif action is UpdateRequest.stable: self.add_tag(self.release.pending_stable_tag) @@ -2373,13 +2373,19 @@ def check_karma_thresholds(self, db, agent): self.comment(db, text, author=u'bodhi') elif self.stable_karma and self.karma >= self.stable_karma: if self.autokarma: - log.info("Automatically marking %s as stable" % self.title) - self.set_request(db, UpdateRequest.stable, agent) - self.request = UpdateRequest.stable - self.date_pushed = None - notifications.publish( - topic='update.karma.threshold.reach', - msg=dict(update=self, status='stable')) + if self.severity is UpdateSeverity.urgent or self.type is UpdateType.security: + log.info("Automatically marking %s as stable" % self.title) + self.set_request(db, UpdateRequest.stable, agent) + self.request = UpdateRequest.stable + self.date_pushed = None + notifications.publish( + topic='update.karma.threshold.reach', + msg=dict(update=self, status='stable')) + else: + log.info("Automatically adding %s to batch of updates that will be pushed to" + " stable at a later date" % self.title) + self.set_request(db, UpdateRequest.batched, agent) + self.request = UpdateRequest.batched else: # Add the 'testing_approval_msg_based_on_karma' message now log.info(( @@ -2571,7 +2577,7 @@ def requested_tag(self): # release to the Release.dist-tag if self.release.state is ReleaseState.pending: tag = self.release.dist_tag - elif self.request is UpdateRequest.testing: + elif self.request is UpdateRequest.testing or UpdateRequest.batched: tag = self.release.testing_tag elif self.request is UpdateRequest.obsolete: tag = self.release.candidate_tag diff --git a/bodhi/server/scripts/dequeue_stable.py b/bodhi/server/scripts/dequeue_stable.py new file mode 100644 index 0000000000..0d6e602a4e --- /dev/null +++ b/bodhi/server/scripts/dequeue_stable.py @@ -0,0 +1,40 @@ +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +"""This script is responsible for moving all updates with a batched request to a stable request.""" + +import sys +import click + +from bodhi.server import config, models, Session, initialize_db + + +@click.command() +@click.version_option(message='%(version)s') +def dequeue_stable(): + """Convert all batched requests to stable requests.""" + initialize_db(config.config) + db = Session() + + try: + batched = db.query(models.Update).filter_by(request=models.UpdateRequest.batched).all() + + for update in batched: + update.request = models.UpdateRequest.stable + db.commit() + + except Exception as e: + print(str(e)) + db.rollback() + Session.remove() + sys.exit(1) diff --git a/bodhi/server/scripts/untag_branched.py b/bodhi/server/scripts/untag_branched.py index e3e04f5b0c..00ba97b388 100644 --- a/bodhi/server/scripts/untag_branched.py +++ b/bodhi/server/scripts/untag_branched.py @@ -14,7 +14,7 @@ """ Used to remove the pending and testing tags from updates in a branched release. -Since a seperate task mashes the branched stable repos, this will leave +Since a separate task mashes the branched stable repos, this will leave those stable updates with the testing tags for 1 day before untagging. https://github.com/fedora-infra/bodhi/issues/576 diff --git a/bodhi/server/util.py b/bodhi/server/util.py index e675c6c3e5..9125654755 100644 --- a/bodhi/server/util.py +++ b/bodhi/server/util.py @@ -468,6 +468,7 @@ def request2html(context, request): 'obsolete': 'default', 'testing': 'warning', 'stable': 'success', + 'batched': 'success', }.get(request) return "%s" % (cls, request) diff --git a/bodhi/server/validators.py b/bodhi/server/validators.py index e7e009a0f5..5b8bd612f2 100644 --- a/bodhi/server/validators.py +++ b/bodhi/server/validators.py @@ -1036,7 +1036,7 @@ def validate_request(request): return if request.validated['request'] is UpdateRequest.stable: target = UpdateStatus.stable - elif request.validated['request'] is UpdateRequest.testing: + elif request.validated['request'] is (UpdateRequest.testing or UpdateRequest.batched): target = UpdateStatus.testing else: # obsolete, unpush, revoke... diff --git a/bodhi/tests/server/consumers/test_masher.py b/bodhi/tests/server/consumers/test_masher.py index a8d294eca3..9e897dad01 100644 --- a/bodhi/tests/server/consumers/test_masher.py +++ b/bodhi/tests/server/consumers/test_masher.py @@ -1053,7 +1053,7 @@ def test_stable_requirements_met_during_push(self, *args): # Ensure the masher set the autokarma once the push is done self.assertEquals(up.locked, False) - self.assertEquals(up.request, UpdateRequest.stable) + self.assertEquals(up.request, UpdateRequest.batched) @mock.patch(**mock_taskotron_results) @mock.patch('bodhi.server.consumers.masher.MasherThread.update_comps') diff --git a/bodhi/tests/server/scripts/test_dequeue_stable.py b/bodhi/tests/server/scripts/test_dequeue_stable.py new file mode 100644 index 0000000000..4561b46ee2 --- /dev/null +++ b/bodhi/tests/server/scripts/test_dequeue_stable.py @@ -0,0 +1,41 @@ +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" +This module contains tests for the bodhi.server.scripts.dequeue_stable module. +""" +from click import testing + +from bodhi.server import models +from bodhi.server.scripts import dequeue_stable +from bodhi.tests.server.base import BaseTestCase + + +class TestDequeueStable(BaseTestCase): + """ + This class contains tests for the dequeue_stable() function. + """ + def test_dequeue_stable(self): + """ + Assert that dequeue_stable moves only the batched updates to stable. + """ + runner = testing.CliRunner() + + update = self.db.query(models.Update).all()[0] + update.request = models.UpdateRequest.batched + update.status = models.UpdateStatus.testing + self.db.commit() + + result = runner.invoke(dequeue_stable.dequeue_stable, []) + self.assertEqual(result.exit_code, 0) + self.assertEqual(update.request, models.UpdateRequest.stable) diff --git a/bodhi/tests/server/services/test_updates.py b/bodhi/tests/server/services/test_updates.py index 61de44ee6b..23ac083296 100644 --- a/bodhi/tests/server/services/test_updates.py +++ b/bodhi/tests/server/services/test_updates.py @@ -660,7 +660,7 @@ def test_provenpackager_request_privs(self, publish, *args): update.comment(self.db, u"foo", 1, u'biz') update = self.db.query(Update).filter_by(title=nvr).one() self.assertEqual(update.karma, 3) - self.assertEqual(update.request, UpdateRequest.stable) + self.assertEqual(update.request, UpdateRequest.batched) # Set it back to testing update.request = UpdateRequest.testing @@ -2234,7 +2234,7 @@ def test_pending_update_on_stable_karma_reached_autopush_enabled(self, publish, up = self.db.query(Update).filter_by(title=nvr).one() self.assertEquals(up.karma, 2) - self.assertEquals(up.request, UpdateRequest.stable) + self.assertEquals(up.request, UpdateRequest.batched) self.assertEquals(up.status, UpdateStatus.pending) @mock.patch(**mock_valid_requirements) @@ -3455,7 +3455,7 @@ def test_autopush_critical_update_with_no_negative_karma(self, publish, *args): self.assertEquals(up.autokarma, True) up = self.db.query(Update).filter_by(title=resp.json['title']).one() - self.assertEquals(up.request, UpdateRequest.stable) + self.assertEquals(up.request, UpdateRequest.batched) @mock.patch(**mock_valid_requirements) @mock.patch('bodhi.server.notifications.publish') @@ -3644,7 +3644,7 @@ def test_autopush_non_critical_update_with_no_negative_karma(self, publish, *arg self.assertEquals(up.autokarma, True) up = self.db.query(Update).filter_by(title=resp.json['title']).one() - self.assertEquals(up.request, UpdateRequest.stable) + self.assertEquals(up.request, UpdateRequest.batched) @mock.patch(**mock_valid_requirements) @mock.patch('bodhi.server.notifications.publish')