#347 Block retiring in released branches
Merged 4 years ago by onosek. Opened 4 years ago by onosek.
onosek/fedpkg retire_restriction  into  master

@@ -40,6 +40,7 @@ 

  [fedpkg-stage.bodhi]

  # Refer to fedpkg.conf

  staging = True

+ releases_service = https://bodhi.stg.fedoraproject.org/releases/%(release)s

  

  [fedpkg-stage.mbs]

  auth_method = oidc

@@ -42,6 +42,7 @@ 

  # different instance. Instead, --staging is available to switch to the stage

  # bodhi, and production is used without providing --staging.

  staging = False

+ releases_service = https://bodhi.fedoraproject.org/releases/%(release)s

  

  [fedpkg.mbs]

  auth_method = oidc

file modified
+16 -4
@@ -32,10 +32,9 @@ 

  from pyrpkg import rpkgError

  from fedpkg.bugzilla import BugzillaClient

  from fedpkg.utils import (

-     get_release_branches, sl_list_to_dict, verify_sls, new_pagure_issue,

-     get_pagure_token, is_epel, assert_valid_epel_package,

-     assert_new_tests_repo, get_dist_git_url, get_stream_branches,

-     expand_release)

+     get_fedora_release_state, get_release_branches, sl_list_to_dict, verify_sls,

+     new_pagure_issue, get_pagure_token, is_epel, assert_valid_epel_package,

+     assert_new_tests_repo, get_dist_git_url, get_stream_branches, expand_release)

  

  RELEASE_BRANCH_REGEX = r'^(f\d+|el\d+|epel\d+)$'

  LOCAL_PACKAGE_CONFIG = 'package.cfg'
@@ -1148,3 +1147,16 @@ 

          else:

              print('Fedora: {0}'.format(_join(releases['fedora'])))

              print('EPEL: {0}'.format(_join(releases['epel'])))

+ 

+     def retire(self):

+         """

+         Runs the rpkg retire command after check. Check includes reading the state

+         of Fedora release.

+         """

+         state = get_fedora_release_state(self.config, self.name, self.cmd.branch_merge)

+ 

+         if state is None or state == 'pending':

+             super(fedpkgClient, self).retire()

+         else:

+             self.log.error("Fedora release (%s) is in state '%s' - retire operation "

+                            "is not allowed." % (self.cmd.branch_merge, state))

file modified
+37
@@ -399,3 +399,40 @@ 

          return [rel]

      else:

          return None

+ 

+ 

+ def get_fedora_release_state(config, cli_name, release):

+     """

+     Queries service page for release state. Query result is returned as json dict.

+ 

+     :param config: ConfigParser object

+     :param cli_name: string of the CLI's name (e.g. fedpkg)

+     :param str release: short release name. Example: F29, F30, F29M, F30C, ...

+     :return: state of the release or None if there is no such release

+     :rtype: str

+     """

+     try:

+         # url of the release service. It needs to be expanded by release name

+         releases_service_url = config.get('{0}.bodhi'.format(cli_name),

+                                           'releases_service',

+                                           vars={'release': release})

+     except (ValueError, NoOptionError, NoSectionError) as e:

+         raise rpkgError('Could not get release state for Fedora '

+                         '({0}): {1}.'.format(release, str(e)))

+ 

+     try:

+         rv = requests.get(releases_service_url, timeout=60)

+     except ConnectionError as error:

+         error_msg = ('The connection to Bodhi failed while trying to get '

+                      'release state. The error was: {0}'.format(str(error)))

+         raise rpkgError(error_msg)

+ 

+     if rv.status_code == 404:

+         # release wasn't found

+         return None

+     elif not rv.ok:

+         base_error_msg = ('The following error occurred while trying to '

+                           'get the release state in Bodhi: {0}')

+         raise rpkgError(base_error_msg.format(rv.text))

+ 

+     return rv.json().get('state')

file modified
+1
@@ -12,6 +12,7 @@ 

  

  [fedpkg.bodhi]

  staging = False

+ releases_service = https://bodhi.fedoraproject.org/releases/%(release)s

  

  [fedpkg.bugzilla]

  url = https://bugzilla.example.com

file modified
+50
@@ -2311,3 +2311,53 @@ 

  

      def test_print_releases_in_default(self, mock_grb):

          self.assert_output_releases('Fedora: f29 f28\nEPEL: el6 epel7')

+ 

+ 

+ class TestRetire(CliTestCase):

+     """

+     Test retire operation with additional fedpkg Fedora release checking

+     """

+ 

+     @patch('requests.get')

+     def retire_release(self, release_state, mock_get):

+         mock_rv = Mock()

+         if release_state:

+             mock_rv.ok = True

+             mock_rv.json.return_value = {

+                 'state': release_state,

+             }

+         else:

+             mock_rv.status_code = 404

+         mock_get.return_value = mock_rv

+ 

+         with patch('sys.argv', ['fedpkg', '--release', 'f30', 'retire', 'retire_message']):

+             cli = self.new_cli(cfg='fedpkg-test.conf')

+             # retire method in rpkg would be called, but there is not environment configured

+             # therefore just Exception is catched

+             with self.assertRaises(Exception):

+                 cli.args.path = '/repo_path'

+                 cli.retire()

+ 

+     @patch('requests.get')

+     def do_not_retire_release(self, release_state, mock_get):

+         mock_rv = Mock()

+         mock_rv.ok = True

+         mock_rv.json.return_value = {

+             'state': release_state,

+         }

+         mock_get.return_value = mock_rv

+ 

+         with patch('sys.argv', ['fedpkg', '--release', 'f30', 'retire', 'retire_message']):

+             cli = self.new_cli(cfg='fedpkg-test.conf')

+             # retire is terminated after check

+             cli.args.path = '/repo_path'

+             cli.retire()

+ 

+     def test_retire_fedora_release(self):

+         self.do_not_retire_release("disabled")

+         self.retire_release("pending")

+         self.do_not_retire_release("frozen")

+         self.do_not_retire_release("current")

+         self.do_not_retire_release("archived")

+         # unknown fedora (or other) release

+         self.retire_release(None)

file modified
+42
@@ -510,3 +510,45 @@ 

      def test_expand_unknown_name(self):

          result = utils.expand_release('some_branch', self.releases)

          self.assertEqual(None, result)

+ 

+ 

+ class TestGetFedoraReleaseState(unittest.TestCase):

+ 

+     @patch('requests.get')

+     def test_release_exists_current(self, mock_get):

+         mock_rv = Mock()

+         mock_rv.ok = True

+         mock_rv.json.return_value = {

+             'name': 'F30',

+             'long_name': 'Fedora 30',

+             'version': '30',

+             'branch': 'f30',

+             'state': 'current',  # this item is only important for the test

+         }

+         mock_get.return_value = mock_rv

+ 

+         config = Mock()

+         config.get.return_value = 'https://service_url/releases/F30'

+ 

+         rv = utils.get_fedora_release_state(config, 'fedpkg', 'F30')

+         self.assertEqual(rv, 'current')

+ 

+     @patch('requests.get')

+     def test_release_does_not_exist(self, mock_get):

+         mock_rv = Mock()

+         mock_rv.ok = False

+         mock_rv.status_code = 404

+         mock_get.return_value = mock_rv

+ 

+         config = Mock()

+         config.get.return_value = 'https://service_url/releases/eng-fedora-29'

+ 

+         rv = utils.get_fedora_release_state(config, 'fedpkg', 'eng-fedora-29')

+         self.assertEqual(rv, None)

+ 

+     def test_config_does_not_have_option(self):

+         config = Mock()

+         config.get.side_effect = NoOptionError('releases_service', 'fedpkg.bodhi')

+         six.assertRaisesRegex(self, rpkgError, r"Could not get release state for Fedora \(F30M\): "

+                               "No option 'releases_service' in section: 'fedpkg.bodhi'.",

+                               utils.get_fedora_release_state, config, 'fedpkg', 'F30M')

It checks Fedora release state and it restricts retiring operation
for other states than 'pending'. States are obtained from service here:
https://bodhi.fedoraproject.org/releases/<release_name>
Unknown releases are allowed to be retired.

Fixes: #337
JIRA: COMPOSE-3690

Signed-off-by: Ondrej Nosek onosek@redhat.com

rebased onto e51e3e65f57397a6ec7f77ac060b1085dc0bc08e

4 years ago

rebased onto 873bc286aba5b869041cb977a62dcd59249341d7

4 years ago

rebased onto 868a3d8fc535a246bf8fa7060e143e9298632fe2

4 years ago

rebased onto 9e5aca6b609d070d36d255f23f0bfaa3793a14fc

4 years ago

rebased onto 27f4bfa793eb9ab193950d3c1647f8ab0a4e0513

4 years ago

rebased onto 27f4bfa793eb9ab193950d3c1647f8ab0a4e0513

4 years ago

rebased onto ebc3ac9ae52559f7d5a7309d07ee0f6027550aa2

4 years ago

Would it be nicer to move this to fedpkg.bodhi section?

rebased onto 4c5d4c6

4 years ago

Pull-Request has been merged by onosek

4 years ago