diff --git a/bodhi/__init__.py b/bodhi/__init__.py index 7565457308..4d6c6bc06f 100644 --- a/bodhi/__init__.py +++ b/bodhi/__init__.py @@ -17,7 +17,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. """Fedora's update manager.""" -__version__ = "5.7.1b0" +__version__ = "5.7.1" # This is a regular expression used to match username mentions in comments. MENTION_RE = r'(?%s" % (url, display) + url = config.get('buglink') % str(bug.bug_id) + link = f"BZ#{bug.bug_id}" if not short: if bug.title: # We're good, but we do need to clean the bug title in case it contains malicious diff --git a/bodhi/tests/server/services/test_updates.py b/bodhi/tests/server/services/test_updates.py index cba032cabb..e18948dd27 100644 --- a/bodhi/tests/server/services/test_updates.py +++ b/bodhi/tests/server/services/test_updates.py @@ -3364,6 +3364,42 @@ def test_edit_testing_update_with_new_builds_with_stable_request(self, *args): assert up['builds'][0]['nvr'] == 'bodhi-2.0.0-3.fc17' assert self.db.query(RpmBuild).filter_by(nvr='bodhi-2.0.0-2.fc17').first() is None + @mock.patch('bodhi.server.services.updates.handle_side_and_related_tags_task', mock.Mock()) + @mock.patch('bodhi.server.models.tag_update_builds_task', mock.Mock()) + @mock.patch(**mock_valid_requirements) + def test_edit_testing_update_with_stable_request_no_edit_build(self, *args): + """An update with stable request should not be pushed back to testing if + build list is not changed.""" + nvr = 'bodhi-2.0.0-2.fc17' + args = self.get_update(nvr) + + with fml_testing.mock_sends(update_schemas.UpdateRequestTestingV1): + r = self.app.post_json('/updates/', args) + + # Mark it as testing + upd = Update.get(r.json['alias']) + upd.status = UpdateStatus.testing + upd.request = UpdateRequest.stable + # Clear pending messages + self.db.info['messages'] = [] + self.db.commit() + + args['edited'] = upd.alias + args['notes'] = 'A nifty description.' + + with fml_testing.mock_sends(update_schemas.UpdateEditV1): + r = self.app.post_json('/updates/', args) + + up = r.json_body + assert up['title'] == 'bodhi-2.0.0-2.fc17' + assert up['status'] == 'testing' + assert up['request'] == 'stable' + assert up['notes'] == 'A nifty description.' + assert up['comments'][-1]['text'] == 'guest edited this update.' + assert up['comments'][-3]['text'] == 'This update has been submitted for testing by guest. ' + assert len(up['builds']) == 1 + assert up['builds'][0]['nvr'] == 'bodhi-2.0.0-2.fc17' + @mock.patch('bodhi.server.services.updates.handle_side_and_related_tags_task', mock.Mock()) @mock.patch('bodhi.server.models.tag_update_builds_task', mock.Mock()) @mock.patch(**mock_valid_requirements) @@ -3463,23 +3499,6 @@ def test_edit_locked_update(self, *args): build = self.db.query(RpmBuild).filter_by(nvr=nvr).one() assert up.builds == [build] - # Changing the request should fail - args['notes'] = 'Still new notes' - args['builds'] = nvr - args['request'] = 'stable' - r = self.app.post_json('/updates/', args, status=400).json_body - assert r['status'] == 'error' - assert 'errors' in r - assert {'description': "Can't change the request on a locked update", - 'location': 'body', 'name': 'builds'} in r['errors'] - up = self.db.query(Update).get(up_id) - assert up.notes == 'Some new notes' - # We need to re-retrieve the build since we started a new transaction in the call to - # /updates - build = self.db.query(RpmBuild).filter_by(nvr=nvr).one() - assert up.builds == [build] - assert up.request is None - @mock.patch(**mock_valid_requirements) def test_pending_update_on_stable_karma_reached_autopush_enabled(self, *args): """Ensure that a pending update stays in testing if it hits stable karma while pending.""" @@ -6449,7 +6468,7 @@ def test_get_test_results_calling_greenwave(self, call_api, *args): service_name='Greenwave' ) - assert res.json_body == {'decision': {'foo': 'bar'}} + assert res.json_body == {'decisions': [{'foo': 'bar'}]} @mock.patch.dict(config, [('greenwave_api_url', 'https://greenwave.api')]) @mock.patch('bodhi.server.util.call_api') @@ -6464,23 +6483,25 @@ def test_get_test_results_calling_greenwave_critpath(self, call_api, *args): res = self.app.get(f'/updates/{update.alias}/get-test-results') - call_api.assert_called_once_with( - 'https://greenwave.api/decision', - data={ - 'product_version': 'fedora-17', - 'decision_context': 'bodhi_update_push_testing_critpath', - 'subject': [ - {'item': 'bodhi-2.0-1.fc17', 'type': 'koji_build'}, - {'item': update.alias, 'type': 'bodhi_update'} - ], - 'verbose': True, - }, - method='POST', - retries=3, - service_name='Greenwave' - ) + assert call_api.call_args_list == [ + mock.call( + 'https://greenwave.api/decision', + data={ + 'product_version': 'fedora-17', + 'decision_context': context, + 'subject': [ + {'item': 'bodhi-2.0-1.fc17', 'type': 'koji_build'}, + {'item': update.alias, 'type': 'bodhi_update'} + ], + 'verbose': True, + }, + method='POST', + retries=3, + service_name='Greenwave' + ) for context in ('bodhi_update_push_testing_critpath', 'bodhi_update_push_testing') + ] - assert res.json_body == {'decision': {'foo': 'bar'}} + assert res.json_body == {'decisions': [{'foo': 'bar'}, {'foo': 'bar'}]} @mock.patch('bodhi.server.util.call_api') def test_get_test_results_calling_greenwave_no_session(self, call_api, *args): @@ -6513,7 +6534,7 @@ def test_get_test_results_calling_greenwave_no_session(self, call_api, *args): service_name='Greenwave' ) - assert res.json_body == {'decision': {'foo': 'bar'}} + assert res.json_body == {'decisions': [{'foo': 'bar'}]} @mock.patch('bodhi.server.util.call_api') def test_get_test_results_calling_greenwave_unauth(self, call_api, *args): diff --git a/bodhi/tests/server/tasks/test_check_policies.py b/bodhi/tests/server/tasks/test_check_policies.py index 3abb7d00b0..ee0d11c936 100644 --- a/bodhi/tests/server/tasks/test_check_policies.py +++ b/bodhi/tests/server/tasks/test_check_policies.py @@ -17,7 +17,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. """This module contains tests for the bodhi.server.tasks.check_policies module.""" -from unittest.mock import patch +from unittest.mock import patch, call import datetime from bodhi.server import models @@ -58,40 +58,57 @@ def test_policies_satisfied(self): self.db.info['messages'] = [] self.db.commit() with patch('bodhi.server.models.util.greenwave_api_post') as mock_greenwave: - greenwave_response = { - 'policies_satisfied': True, - 'summary': 'All required tests passed', - 'applicable_policies': [ - 'kojibuild_bodhipush_no_requirements', - 'kojibuild_bodhipush_remoterule', - 'bodhiupdate_bodhipush_no_requirements', - 'bodhiupdate_bodhipush_openqa' - ], - 'satisfied_requirements': [ - { - 'result_id': 39603316, - 'subject_type': 'bodhi_update', - 'testcase': 'update.install_default_update_netinst', - 'type': 'test-result-passed' - }, - ], - 'unsatisfied_requirements': [] - } - mock_greenwave.return_value = greenwave_response + greenwave_responses = [ + { + 'policies_satisfied': True, + 'summary': 'All required tests passed', + 'applicable_policies': [ + 'kojibuild_bodhipush_no_requirements', + 'kojibuild_bodhipush_remoterule', + 'bodhiupdate_bodhipush_no_requirements', + 'bodhiupdate_bodhipush_openqa' + ], + 'satisfied_requirements': [ + { + 'result_id': 39603316, + 'subject_type': 'bodhi_update', + 'testcase': 'update.install_default_update_netinst', + 'type': 'test-result-passed' + }, + ], + 'unsatisfied_requirements': [] + }, + { + 'policies_satisfied': True, + 'summary': 'no tests are required', + 'applicable_policies': [ + 'kojibuild_bodhipush_no_requirements', + 'kojibuild_bodhipush_remoterule', + 'bodhiupdate_bodhipush_no_requirements' + ], + 'satisfied_requirements': [], + 'unsatisfied_requirements': [], + } + ] + mock_greenwave.side_effect = greenwave_responses check_policies_main() update = self.db.query(models.Update).filter(models.Update.id == update.id).one() assert update.test_gating_status == models.TestGatingStatus.passed - expected_query = { - 'product_version': 'fedora-17', 'decision_context': 'bodhi_update_push_stable_critpath', - 'subject': [ - {'item': 'bodhi-2.0-1.fc17', 'type': 'koji_build'}, - {'item': 'FEDORA-{}-a3bbe1a8f2'.format(datetime.datetime.utcnow().year), - 'type': 'bodhi_update'}], - 'verbose': False - } - mock_greenwave.assert_called_once_with(config['greenwave_api_url'] + '/decision', - expected_query) + expected_queries = [ + { + 'product_version': 'fedora-17', 'decision_context': context, + 'subject': [ + {'item': 'bodhi-2.0-1.fc17', 'type': 'koji_build'}, + {'item': 'FEDORA-{}-a3bbe1a8f2'.format(datetime.datetime.utcnow().year), + 'type': 'bodhi_update'}], + 'verbose': False + } for context in ('bodhi_update_push_stable_critpath', 'bodhi_update_push_stable') + ] + expected_calls = [ + call(config['greenwave_api_url'] + '/decision', query) for query in expected_queries + ] + assert mock_greenwave.call_args_list == expected_calls @patch.dict(config, [('greenwave_api_url', 'http://domain.local')]) def test_policies_pending_satisfied(self): @@ -102,41 +119,58 @@ def test_policies_pending_satisfied(self): update.critpath = True self.db.commit() with patch('bodhi.server.models.util.greenwave_api_post') as mock_greenwave: - greenwave_response = { - 'policies_satisfied': True, - 'summary': 'All required tests passed', - 'applicable_policies': [ - 'kojibuild_bodhipush_no_requirements', - 'kojibuild_bodhipush_remoterule', - 'bodhiupdate_bodhipush_no_requirements', - 'bodhiupdate_bodhipush_openqa' - ], - 'satisfied_requirements': [ - { - 'result_id': 39603316, - 'subject_type': 'bodhi_update', - 'testcase': 'update.install_default_update_netinst', - 'type': 'test-result-passed' - }, - ], - 'unsatisfied_requirements': [] - } - mock_greenwave.return_value = greenwave_response + greenwave_responses = [ + { + 'policies_satisfied': True, + 'summary': 'All required tests passed', + 'applicable_policies': [ + 'kojibuild_bodhipush_no_requirements', + 'kojibuild_bodhipush_remoterule', + 'bodhiupdate_bodhipush_no_requirements', + 'bodhiupdate_bodhipush_openqa' + ], + 'satisfied_requirements': [ + { + 'result_id': 39603316, + 'subject_type': 'bodhi_update', + 'testcase': 'update.install_default_update_netinst', + 'type': 'test-result-passed' + }, + ], + 'unsatisfied_requirements': [] + }, + { + 'policies_satisfied': True, + 'summary': 'no tests are required', + 'applicable_policies': [ + 'kojibuild_bodhipush_no_requirements', + 'kojibuild_bodhipush_remoterule', + 'bodhiupdate_bodhipush_no_requirements' + ], + 'satisfied_requirements': [], + 'unsatisfied_requirements': [], + } + ] + mock_greenwave.side_effect = greenwave_responses check_policies_main() update = self.db.query(models.Update).filter(models.Update.id == update.id).one() assert update.test_gating_status == models.TestGatingStatus.passed - expected_query = { - 'product_version': 'fedora-17', - 'decision_context': 'bodhi_update_push_testing_critpath', - 'subject': [ - {'item': 'bodhi-2.0-1.fc17', 'type': 'koji_build'}, - {'item': 'FEDORA-{}-a3bbe1a8f2'.format(datetime.datetime.utcnow().year), - 'type': 'bodhi_update'}], - 'verbose': False, - } - mock_greenwave.assert_called_once_with(config['greenwave_api_url'] + '/decision', - expected_query) + expected_queries = [ + { + 'product_version': 'fedora-17', + 'decision_context': context, + 'subject': [ + {'item': 'bodhi-2.0-1.fc17', 'type': 'koji_build'}, + {'item': 'FEDORA-{}-a3bbe1a8f2'.format(datetime.datetime.utcnow().year), + 'type': 'bodhi_update'}], + 'verbose': False, + } for context in ('bodhi_update_push_testing_critpath', 'bodhi_update_push_testing') + ] + expected_calls = [ + call(config['greenwave_api_url'] + '/decision', query) for query in expected_queries + ] + assert mock_greenwave.call_args_list == expected_calls @patch.dict(config, [('greenwave_api_url', 'http://domain.local')]) def test_policies_unsatisfied_waiting(self): @@ -152,40 +186,54 @@ def test_policies_unsatisfied_waiting(self): update.date_submitted = datetime.datetime.utcnow() self.db.commit() with patch('bodhi.server.models.util.greenwave_api_post') as mock_greenwave: - greenwave_response = { - 'policies_satisfied': False, - 'summary': '2 of 2 required test results missing', - 'applicable_policies': [ - 'kojibuild_bodhipush_no_requirements', - 'kojibuild_bodhipush_remoterule', - 'bodhiupdate_bodhipush_no_requirements', - 'bodhiupdate_bodhipush_openqa' - ], - 'satisfied_requirements': [], - 'unsatisfied_requirements': [ - { - 'item': { - 'item': 'FEDORA-{}-a3bbe1a8f2'.format(datetime.datetime.utcnow().year), - 'type': 'bodhi_update' + item = 'FEDORA-{}-a3bbe1a8f2'.format(datetime.datetime.utcnow().year) + greenwave_responses = [ + { + 'policies_satisfied': False, + 'summary': '2 of 2 required test results missing', + 'applicable_policies': [ + 'kojibuild_bodhipush_no_requirements', + 'kojibuild_bodhipush_remoterule', + 'bodhiupdate_bodhipush_no_requirements', + 'bodhiupdate_bodhipush_openqa' + ], + 'satisfied_requirements': [], + 'unsatisfied_requirements': [ + { + 'item': { + 'item': item, + 'type': 'bodhi_update' + }, + 'scenario': 'fedora.updates-everything-boot-iso.x86_64.64bit', + 'subject_type': 'bodhi_update', + 'testcase': 'update.install_default_update_netinst', + 'type': 'test-result-missing' }, - 'scenario': 'fedora.updates-everything-boot-iso.x86_64.64bit', - 'subject_type': 'bodhi_update', - 'testcase': 'update.install_default_update_netinst', - 'type': 'test-result-missing' - }, - { - 'item': { - 'item': 'FEDORA-{}-a3bbe1a8f2'.format(datetime.datetime.utcnow().year), - 'type': 'bodhi_update' + { + 'item': { + 'item': item, + 'type': 'bodhi_update' + }, + 'scenario': 'fedora.updates-everything-boot-iso.x86_64.uefi', + 'subject_type': 'bodhi_update', + 'testcase': 'update.install_default_update_netinst', + 'type': 'test-result-missing' }, - 'scenario': 'fedora.updates-everything-boot-iso.x86_64.uefi', - 'subject_type': 'bodhi_update', - 'testcase': 'update.install_default_update_netinst', - 'type': 'test-result-missing' - }, - ] - } - mock_greenwave.return_value = greenwave_response + ] + }, + { + 'policies_satisfied': True, + 'summary': 'no tests are required', + 'applicable_policies': [ + 'kojibuild_bodhipush_no_requirements', + 'kojibuild_bodhipush_remoterule', + 'bodhiupdate_bodhipush_no_requirements' + ], + 'satisfied_requirements': [], + 'unsatisfied_requirements': [], + } + ] + mock_greenwave.side_effect = greenwave_responses check_policies_main() update = self.db.query(models.Update).filter(models.Update.id == update.id).one() assert update.test_gating_status == models.TestGatingStatus.waiting @@ -193,16 +241,20 @@ def test_policies_unsatisfied_waiting(self): expected_comment = "This update's test gating status has been changed to 'waiting'." assert update.comments[-1].text == expected_comment - expected_query = { - 'product_version': 'fedora-17', 'decision_context': 'bodhi_update_push_stable_critpath', - 'subject': [ - {'item': 'bodhi-2.0-1.fc17', 'type': 'koji_build'}, - {'item': 'FEDORA-{}-a3bbe1a8f2'.format(datetime.datetime.utcnow().year), - 'type': 'bodhi_update'}], - 'verbose': False - } - mock_greenwave.assert_called_once_with(config['greenwave_api_url'] + '/decision', - expected_query) + expected_queries = [ + { + 'product_version': 'fedora-17', 'decision_context': context, + 'subject': [ + {'item': 'bodhi-2.0-1.fc17', 'type': 'koji_build'}, + {'item': 'FEDORA-{}-a3bbe1a8f2'.format(datetime.datetime.utcnow().year), + 'type': 'bodhi_update'}], + 'verbose': False + } for context in ('bodhi_update_push_stable_critpath', 'bodhi_update_push_stable') + ] + expected_calls = [ + call(config['greenwave_api_url'] + '/decision', query) for query in expected_queries + ] + assert mock_greenwave.call_args_list == expected_calls @patch.dict(config, [('greenwave_api_url', 'http://domain.local')]) def test_policies_unsatisfied_waiting_too_long(self): @@ -218,40 +270,54 @@ def test_policies_unsatisfied_waiting_too_long(self): update.date_submitted = datetime.datetime.utcnow() - datetime.timedelta(days=1) self.db.commit() with patch('bodhi.server.models.util.greenwave_api_post') as mock_greenwave: - greenwave_response = { - 'policies_satisfied': False, - 'summary': '2 of 2 required test results missing', - 'applicable_policies': [ - 'kojibuild_bodhipush_no_requirements', - 'kojibuild_bodhipush_remoterule', - 'bodhiupdate_bodhipush_no_requirements', - 'bodhiupdate_bodhipush_openqa' - ], - 'satisfied_requirements': [], - 'unsatisfied_requirements': [ - { - 'item': { - 'item': 'FEDORA-{}-a3bbe1a8f2'.format(datetime.datetime.utcnow().year), - 'type': 'bodhi_update' + item = 'FEDORA-{}-a3bbe1a8f2'.format(datetime.datetime.utcnow().year) + greenwave_responses = [ + { + 'policies_satisfied': False, + 'summary': '2 of 2 required test results missing', + 'applicable_policies': [ + 'kojibuild_bodhipush_no_requirements', + 'kojibuild_bodhipush_remoterule', + 'bodhiupdate_bodhipush_no_requirements', + 'bodhiupdate_bodhipush_openqa' + ], + 'satisfied_requirements': [], + 'unsatisfied_requirements': [ + { + 'item': { + 'item': item, + 'type': 'bodhi_update' + }, + 'scenario': 'fedora.updates-everything-boot-iso.x86_64.64bit', + 'subject_type': 'bodhi_update', + 'testcase': 'update.install_default_update_netinst', + 'type': 'test-result-missing' }, - 'scenario': 'fedora.updates-everything-boot-iso.x86_64.64bit', - 'subject_type': 'bodhi_update', - 'testcase': 'update.install_default_update_netinst', - 'type': 'test-result-missing' - }, - { - 'item': { - 'item': 'FEDORA-{}-a3bbe1a8f2'.format(datetime.datetime.utcnow().year), - 'type': 'bodhi_update' + { + 'item': { + 'item': item, + 'type': 'bodhi_update' + }, + 'scenario': 'fedora.updates-everything-boot-iso.x86_64.uefi', + 'subject_type': 'bodhi_update', + 'testcase': 'update.install_default_update_netinst', + 'type': 'test-result-missing' }, - 'scenario': 'fedora.updates-everything-boot-iso.x86_64.uefi', - 'subject_type': 'bodhi_update', - 'testcase': 'update.install_default_update_netinst', - 'type': 'test-result-missing' - }, - ] - } - mock_greenwave.return_value = greenwave_response + ] + }, + { + 'policies_satisfied': True, + 'summary': 'no tests are required', + 'applicable_policies': [ + 'kojibuild_bodhipush_no_requirements', + 'kojibuild_bodhipush_remoterule', + 'bodhiupdate_bodhipush_no_requirements' + ], + 'satisfied_requirements': [], + 'unsatisfied_requirements': [], + } + ] + mock_greenwave.side_effect = greenwave_responses check_policies_main() update = self.db.query(models.Update).filter(models.Update.id == update.id).one() assert update.test_gating_status == models.TestGatingStatus.failed @@ -267,13 +333,20 @@ def test_policies_unsatisfied_waiting_too_long(self): 'type': 'bodhi_update'}], 'verbose': False } + # we only expect *one* call here because the *first* query + # (on the _critpath context) should be enough to conclude the + # status is failed: it would be wrong to needlessly run the + # second query. note the mock responses are in the order we + # expect the queries to be run, critpath first mock_greenwave.assert_called_once_with(config['greenwave_api_url'] + '/decision', expected_query) @patch.dict(config, [('greenwave_api_url', 'http://domain.local')]) def test_policies_unsatisfied_failed(self): """Assert correct behavior when the policies enforced by Greenwave are unsatisfied: - failed tests always means failed status. + failed tests always means failed status. This also tests that we behave correctly + even if the *first* query shows requirements satisfied, but the *second* query has + failed required tests. """ update = self.db.query(models.Update).all()[0] update.status = models.UpdateStatus.testing @@ -283,40 +356,56 @@ def test_policies_unsatisfied_failed(self): self.db.info['messages'] = [] self.db.commit() with patch('bodhi.server.models.util.greenwave_api_post') as mock_greenwave: - greenwave_response = { - 'policies_satisfied': False, - 'summary': '1 of 2 required tests failed, 1 result missing', - 'applicable_policies': [ - 'kojibuild_bodhipush_no_requirements', - 'kojibuild_bodhipush_remoterule', - 'bodhiupdate_bodhipush_no_requirements', - 'bodhiupdate_bodhipush_openqa' - ], - 'satisfied_requirements': [], - 'unsatisfied_requirements': [ - { - 'item': { - 'item': 'FEDORA-{}-a3bbe1a8f2'.format(datetime.datetime.utcnow().year), - 'type': 'bodhi_update' + # here, we're mocking the scenario from + # https://pagure.io/fedora-ci/general/issue/263 , where + # openQA tests passed, but a package in the update had a + # local gating config that only specified the context + # bodhi_update_push_stable (not _push_stable_critpath), + # and a test specified in that local policy failed + greenwave_responses = [ + { + 'policies_satisfied': True, + 'summary': 'All required tests passed', + 'applicable_policies': [ + 'kojibuild_bodhipush_no_requirements', + 'kojibuild_bodhipush_remoterule', + 'bodhiupdate_bodhipush_no_requirements', + 'bodhiupdate_bodhipush_openqa' + ], + 'satisfied_requirements': [ + { + 'result_id': 39603316, + 'subject_type': 'bodhi_update', + 'testcase': 'update.install_default_update_netinst', + 'type': 'test-result-passed' }, - 'scenario': 'fedora.updates-everything-boot-iso.x86_64.64bit', - 'subject_type': 'bodhi_update', - 'testcase': 'update.install_default_update_netinst', - 'type': 'test-result-failed' - }, - { - 'item': { - 'item': 'FEDORA-{}-a3bbe1a8f2'.format(datetime.datetime.utcnow().year), - 'type': 'bodhi_update' + ], + 'unsatisfied_requirements': [] + }, + { + 'policies_satisfied': False, + 'summary': '1 of 1 required tests failed', + 'applicable_policies': [ + 'kojibuild_bodhipush_no_requirements', + 'kojibuild_bodhipush_remoterule', + 'bodhiupdate_bodhipush_no_requirements' + ], + 'satisfied_requirements': [], + 'unsatisfied_requirements': [ + { + 'item': { + 'item': 'bodhi-2.0-1.fc17', + 'type': 'koji_build' + }, + 'scenario': None, + 'subject_type': 'koji_build', + 'testcase': 'fedora-ci.koji-build.tier0.functional', + 'type': 'test-result-failed' }, - 'scenario': 'fedora.updates-everything-boot-iso.x86_64.uefi', - 'subject_type': 'bodhi_update', - 'testcase': 'update.install_default_update_netinst', - 'type': 'test-result-missing' - }, - ] - } - mock_greenwave.return_value = greenwave_response + ], + } + ] + mock_greenwave.side_effect = greenwave_responses check_policies_main() update = self.db.query(models.Update).filter(models.Update.id == update.id).one() assert update.test_gating_status == models.TestGatingStatus.failed @@ -324,16 +413,20 @@ def test_policies_unsatisfied_failed(self): expected_comment = "This update's test gating status has been changed to 'failed'." assert update.comments[-1].text == expected_comment - expected_query = { - 'product_version': 'fedora-17', 'decision_context': 'bodhi_update_push_stable_critpath', - 'subject': [ - {'item': 'bodhi-2.0-1.fc17', 'type': 'koji_build'}, - {'item': 'FEDORA-{}-a3bbe1a8f2'.format(datetime.datetime.utcnow().year), - 'type': 'bodhi_update'}], - 'verbose': False - } - mock_greenwave.assert_called_once_with(config['greenwave_api_url'] + '/decision', - expected_query) + expected_queries = [ + { + 'product_version': 'fedora-17', 'decision_context': context, + 'subject': [ + {'item': 'bodhi-2.0-1.fc17', 'type': 'koji_build'}, + {'item': 'FEDORA-{}-a3bbe1a8f2'.format(datetime.datetime.utcnow().year), + 'type': 'bodhi_update'}], + 'verbose': False + } for context in ('bodhi_update_push_stable_critpath', 'bodhi_update_push_stable') + ] + expected_calls = [ + call(config['greenwave_api_url'] + '/decision', query) for query in expected_queries + ] + assert mock_greenwave.call_args_list == expected_calls @patch.dict(config, [('greenwave_api_url', 'http://domain.local')]) def test_no_policies_enforced(self): @@ -378,40 +471,54 @@ def test_pushed_update(self): update.pushed = True self.db.commit() with patch('bodhi.server.models.util.greenwave_api_post') as mock_greenwave: - greenwave_response = { - 'policies_satisfied': False, - 'summary': '1 of 2 required tests failed, 1 result missing', - 'applicable_policies': [ - 'kojibuild_bodhipush_no_requirements', - 'kojibuild_bodhipush_remoterule', - 'bodhiupdate_bodhipush_no_requirements', - 'bodhiupdate_bodhipush_openqa' - ], - 'satisfied_requirements': [], - 'unsatisfied_requirements': [ - { - 'item': { - 'item': 'FEDORA-{}-a3bbe1a8f2'.format(datetime.datetime.utcnow().year), - 'type': 'bodhi_update' + item = 'FEDORA-{}-a3bbe1a8f2'.format(datetime.datetime.utcnow().year) + greenwave_responses = [ + { + 'policies_satisfied': False, + 'summary': '1 of 2 required tests failed, 1 result missing', + 'applicable_policies': [ + 'kojibuild_bodhipush_no_requirements', + 'kojibuild_bodhipush_remoterule', + 'bodhiupdate_bodhipush_no_requirements', + 'bodhiupdate_bodhipush_openqa' + ], + 'satisfied_requirements': [], + 'unsatisfied_requirements': [ + { + 'item': { + 'item': item, + 'type': 'bodhi_update' + }, + 'scenario': 'fedora.updates-everything-boot-iso.x86_64.64bit', + 'subject_type': 'bodhi_update', + 'testcase': 'update.install_default_update_netinst', + 'type': 'test-result-failed' }, - 'scenario': 'fedora.updates-everything-boot-iso.x86_64.64bit', - 'subject_type': 'bodhi_update', - 'testcase': 'update.install_default_update_netinst', - 'type': 'test-result-failed' - }, - { - 'item': { - 'item': 'FEDORA-{}-a3bbe1a8f2'.format(datetime.datetime.utcnow().year), - 'type': 'bodhi_update' + { + 'item': { + 'item': item, + 'type': 'bodhi_update' + }, + 'scenario': 'fedora.updates-everything-boot-iso.x86_64.uefi', + 'subject_type': 'bodhi_update', + 'testcase': 'update.install_default_update_netinst', + 'type': 'test-result-missing' }, - 'scenario': 'fedora.updates-everything-boot-iso.x86_64.uefi', - 'subject_type': 'bodhi_update', - 'testcase': 'update.install_default_update_netinst', - 'type': 'test-result-missing' - }, - ] - } - mock_greenwave.return_value = greenwave_response + ] + }, + { + 'policies_satisfied': True, + 'summary': 'no tests are required', + 'applicable_policies': [ + 'kojibuild_bodhipush_no_requirements', + 'kojibuild_bodhipush_remoterule', + 'bodhiupdate_bodhipush_no_requirements' + ], + 'satisfied_requirements': [], + 'unsatisfied_requirements': [], + } + ] + mock_greenwave.side_effect = greenwave_responses check_policies_main() @@ -424,6 +531,8 @@ def test_pushed_update(self): 'type': 'bodhi_update'}], 'verbose': False } + # we only expect *one* call here, as with the earlier + # 'failed' test mock_greenwave.assert_called_once_with(config['greenwave_api_url'] + '/decision', expected_query) # Check for the comment diff --git a/bodhi/tests/server/test_models.py b/bodhi/tests/server/test_models.py index 1cf5b9ca10..095b49dde5 100644 --- a/bodhi/tests/server/test_models.py +++ b/bodhi/tests/server/test_models.py @@ -2992,6 +2992,52 @@ def test_greenwave_request_batches_multiple(self): ] ) + def test_greenwave_request_batches_multiple_critpath(self): + """ + Ensure that the greenwave_request_batches property returns the correct value + for critpath update with multiple batches. + """ + with mock.patch.dict('bodhi.server.models.config', {'greenwave_batch_size': 1}): + self.obj.critpath = True + assert self.obj.greenwave_subject_batch_size == 1 + assert self.obj.greenwave_request_batches(verbose=True) == ( + [ + { + 'product_version': 'fedora-11', + 'decision_context': 'bodhi_update_push_testing_critpath', + 'verbose': True, + 'subject': [ + {'item': 'TurboGears-1.0.8-3.fc11', 'type': 'koji_build'}, + ] + }, + { + 'product_version': 'fedora-11', + 'decision_context': 'bodhi_update_push_testing', + 'verbose': True, + 'subject': [ + {'item': 'TurboGears-1.0.8-3.fc11', 'type': 'koji_build'}, + ] + }, + { + 'product_version': 'fedora-11', + 'decision_context': 'bodhi_update_push_testing_critpath', + 'verbose': True, + 'subject': [ + {'item': self.obj.alias, 'type': 'bodhi_update'}, + ] + }, + { + 'product_version': 'fedora-11', + 'decision_context': 'bodhi_update_push_testing', + 'verbose': True, + 'subject': [ + {'item': self.obj.alias, 'type': 'bodhi_update'}, + ] + }, + + ] + ) + def test_greenwave_request_batches_json(self): """Ensure that the greenwave_request_batches_json property returns the correct value.""" requests = self.obj.greenwave_request_batches_json diff --git a/devel/ansible/roles/bodhi/tasks/main.yml b/devel/ansible/roles/bodhi/tasks/main.yml index f4382edf3b..a66df842f0 100644 --- a/devel/ansible/roles/bodhi/tasks/main.yml +++ b/devel/ansible/roles/bodhi/tasks/main.yml @@ -69,13 +69,6 @@ - zlib-devel state: present - -- name: Configure Cgroups v1 for docker in grub.cfg - command: sed -i '/^GRUB_CMDLINE_LINUX/ s/"$/ systemd.unified_cgroup_hierarchy=0"/' /etc/default/grub - -- name: Generate the new grub configuration with cgroups v1 - command: grub2-mkconfig -o /boot/grub2/grub.cfg - - name: Initialize PostgreSQL command: postgresql-setup initdb args: diff --git a/docs/user/release_notes.rst b/docs/user/release_notes.rst index 12d1cd8b5d..c107b360ef 100644 --- a/docs/user/release_notes.rst +++ b/docs/user/release_notes.rst @@ -8,6 +8,27 @@ v5.7.1 ====== This is a bugfix release. +Server upgrade instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This release contains database migrations. To apply them, run:: + + $ sudo -u apache /usr/bin/alembic -c /etc/bodhi/alembic.ini upgrade head + + +Summary of the migrations: + +* Add End of life (eol) field to the releases (:pr:`4241`). + +Backwards incompatible changes +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* Query on both relevant Greenwave decision contexts for critical-path updates. + `Update.get_test_gating_info()` now returns a list of decision dictionaries, + not a single decision dictionary. The API endpoint + `/updates/{id}/get-test-results` similarly now returns a single-key + dictionary whose value is a list of decisions, not a single decision + dictionary. (:issue:`4259`). Features ^^^^^^^^ @@ -24,6 +45,9 @@ Features Bug fixes ^^^^^^^^^ +======= +* Fix an issue that caused the builds in a side-tag update to not be tagged + correctly when the build list of the update was modified (:pr:`4161`). * Bodhi will now delete the side-tag in Koji when an update is pushed to stable. Builds that were tagged in the side-tag but were not pushed as part of the update will be untagged. This is required to make sure to not leave @@ -45,6 +69,10 @@ Bug fixes * For new packages submitted to repositories, the changelog was not generated and attached to the automatic Update. This prevented the bugs mentioned in the changelog to be closed by Bodhi (:issue:`4232`). +* Staging Bodhi now uses staging Bugzilla URL for bug links (:issue:`4238`). +* Fixed an issue where editing Updates always caused to set the request to + Testing (:issue:`4263`). + Development improvements ^^^^^^^^^^^^^^^^^^^^^^^^