#261 koji_block_retired: Add playtime call to block all retired
Merged 12 days ago by lenkaseg. Opened 2 months ago by lenkaseg.
fedora-infra/ lenkaseg/toddlers block_all  into  main

@@ -11,6 +11,19 @@ 

  import toddlers.plugins.koji_block_retired as koji_block_retired

  

  

+ @pytest.fixture

+ def config():

+     """Test configuration for toddler fixture."""

+     return {

+         "dist_git_url": "https://src.fedoraproject.org",

+         "koji_url": "https://example.koji.org",

+         "principal": "principal",

+         "keytab": "keytab",

+         "pagure_url": "https://src.fedoraproject.org",

+         "pagure_api_key": "pagure_api_key",

+     }

+ 

+ 

  class TestAcceptTopic:

      """

      Test class for `toddler.plugins.koji_block_retired.KojiBlockRetired.accepts_topic`
@@ -31,6 +44,9 @@ 

              "org.fedoraproject.*.git.receive",

              "org.fedoraproject.prod.git.receive",

              "org.fedoraproject.stg.git.receive",

+             "org.fedoraproject.prod.toddlers.trigger.koji_block_retired",

+             "org.fedoraproject.*.toddlers.trigger.koji_block_retired",

+             "org.fedoraproject.stg.toddlers.trigger.koji_block_retired",

          ],

      )

      def test_accepts_topic_valid(self, topic, toddler):
@@ -57,14 +73,14 @@ 

          config = {"key": "value"}

          message = "Example message"

  

-         self.toddler_cls.process_block_retired = MagicMock()

+         self.toddler_cls.process = MagicMock()

          self.toddler_cls.process(config, message)

-         self.toddler_cls.process_block_retired.assert_called_once_with(config, message)

+         self.toddler_cls.process.assert_called_once_with(config, message)

  

  

  class TestProcessBlockRetired:

      """

-     Test class for `toddler.plugins.koji_block_retired.KojiBlockRetired.process_block_retired`

+     Test class for `toddler.plugins.koji_block_retired.KojiBlockRetired.process`

      method.

      """

  
@@ -73,21 +89,24 @@ 

          self.toddler_cls = koji_block_retired.KojiBlockRetired()

          self.toddler_cls.koji_session = MagicMock()

  

-     def test_no_dead_package_file(self, caplog):

+     @patch("toddlers.plugins.koji_block_retired.KojiBlockRetired._create_session")

+     def test_no_dead_package_file(self, mock_session, caplog):

          """

          Assert that if no dead package was added the plugin stops.

          """

          caplog.set_level(logging.INFO)

          message = MagicMock()

          message.body = {"commit": {"stats": {"files": {}}}}

+         message.topic = "git.receive"

          config = MagicMock()

          config = {

              "koji_url": "https://example.koji.org",

              "principal": "principal",

              "keytab": "keytab",

          }

-         self.toddler_cls.process_block_retired(config, message)

+         self.toddler_cls.process(config, message)

          assert caplog.records[-1].message == "No dead.package in the commit, bailing"

+         self.toddler_cls._create_session.assert_not_called()

  

      def test_dead_package_not_added(self, caplog):

          """
@@ -100,24 +119,25 @@ 

                  "stats": {"files": {"dead.package": {"additions": 0, "deletions": 1}}}

              }

          }

+         message.topic = "git.receive"

          config = MagicMock()

          config = {

              "koji_url": "https://example.koji.org",

              "principal": "principal",

              "keytab": "keytab",

          }

-         self.toddler_cls.process_block_retired(config, message)

+         self.toddler_cls.process(config, message)

          assert caplog.records[-1].message == "dead.package file was not added, bailing"

  

-     @patch("toddlers.plugins.koji_block_retired.KojiBlockRetired._create_session")

-     @patch("toddlers.plugins.koji_block_retired.KojiBlockRetired.get_tag_from_target")

-     def test_dead_package_added_to_main_branch(self, mock_get_tag_from_target, caplog):

+     @patch("toddlers.plugins.koji_block_retired.pagure.set_pagure")

+     def test_dead_package_not_in_distgit(self, mock_pagure, caplog):

          """

-         Assert that that main branch will be changed to rawhide tag

+         Assert if dead.package not present in distgit, the plugin stops.

          """

-         mock_get_tag_from_target.return_value = "f41"

+         mock_dist_git = MagicMock()

+         mock_dist_git.has_dead_package_on_branch.return_value = False

+         mock_pagure.return_value = mock_dist_git

          caplog.set_level(logging.INFO)

- 

          message = MagicMock()

          message.body = {

              "commit": {
@@ -128,27 +148,73 @@ 

                  "date": "2024-09-16T12:12:46+01:00",

              }

          }

-         message._headers = {"sent-at": "2024-09-16T12:12:46+01:00"}

+         message.topic = "git.receive"

          config = MagicMock()

          config = {

              "koji_url": "https://example.koji.org",

              "principal": "principal",

              "keytab": "keytab",

          }

+         self.toddler_cls.process(config, message)

+         assert (

+             caplog.records[-1].message

+             == "Package example-repo is not retired on the distgit branch main, "

+             "probably new branch creation, bailing"

+         )

+ 

+     @patch("toddlers.plugins.koji_block_retired.pagure.set_pagure")

+     @patch("toddlers.plugins.koji_block_retired.KojiBlockRetired._create_session")

+     @patch("toddlers.plugins.koji_block_retired.KojiBlockRetired.get_tag_from_target")

+     def test_dead_package_added_to_main_branch(

+         self,

+         mock_get_tag_from_target,

+         mock_session,

+         mock_pagure,

+         config,

+         caplog,

+     ):

+         """

+         Assert that that main branch will be changed to rawhide tag

+         """

+         mock_get_tag_from_target.return_value = "f41"

+         caplog.set_level(logging.INFO)

+         mock_dist_git = MagicMock()

+         mock_dist_git.has_dead_package_on_branch.return_value = True

+         mock_pagure.return_value = mock_dist_git

+ 

+         message = MagicMock()

+         message.body = {

+             "commit": {

+                 "stats": {"files": {"dead.package": {"additions": 1, "deletions": 0}}},

+                 "branch": "main",

+                 "repo": "example-repo",

+                 "namespace": "example_ns",

+                 "date": "2024-09-16T12:12:46+01:00",

+             }

+         }

+         message.topic = "git.receive"

+         self.toddler_cls.koji_session.packageListBlock.__name__ = "packageListBlock"

          with patch.object(

              self.toddler_cls, "get_tag_from_target", MagicMock(return_value="f41")

          ):

-             self.toddler_cls.process_block_retired(config, message)

+             self.toddler_cls.process(config, message)

          self.toddler_cls.koji_session.packageListBlock.assert_called_once_with(

              taginfo="f41",

              pkginfo="example-repo",

          )

  

+     @patch("toddlers.plugins.koji_block_retired.pagure.set_pagure")

      @patch("toddlers.plugins.koji_block_retired.KojiBlockRetired._create_session")

-     def test_dead_package_added_to_different_branch(self, mock_session, caplog):

+     def test_dead_package_added_to_different_branch(

+         self, mock_session, mock_pagure, config, caplog

+     ):

          """

          Assert that method will process correctly with different branches.

          """

+         mock_dist_git = MagicMock()

+         mock_dist_git.has_dead_package_on_branch.return_value = True

+         mock_pagure.return_value = mock_dist_git

+ 

          caplog.set_level(logging.INFO)

          message = MagicMock()

          message.body = {
@@ -160,24 +226,24 @@ 

                  "date": "2024-09-16T12:12:46+01:00",

              }

          }

-         message._headers = {"sent-at": "2024-09-16T12:12:46+01:00"}

-         config = MagicMock()

-         config = {

-             "koji_url": "https://example.koji.org",

-             "principal": "principal",

-             "keytab": "keytab",

-         }

-         self.toddler_cls.process_block_retired(config, message)

+         message.topic = "git.receive"

+         self.toddler_cls.koji_session.packageListBlock.__name__ = "packageListBlock"

+         self.toddler_cls.process(config, message)

          self.toddler_cls.koji_session.packageListBlock.assert_called_once_with(

              taginfo="f38",

              pkginfo="example-repo",

          )

  

+     @patch("toddlers.plugins.koji_block_retired.pagure.set_pagure")

      @patch("toddlers.plugins.koji_block_retired.KojiBlockRetired._create_session")

-     def test_koji_generic_error_prod(self, mock_session, caplog):

+     def test_koji_generic_error_prod(self, mock_session, mock_pagure, config, caplog):

          """

          Assert that Koji generic error will be handled correctly.

          """

+         mock_dist_git = MagicMock()

+         mock_dist_git.has_dead_package_on_branch.return_value = True

+         mock_pagure.return_value = mock_dist_git

+ 

          message = MagicMock()

          message.body = {

              "commit": {
@@ -188,27 +254,31 @@ 

                  "date": "2024-09-16T12:12:46+01:00",

              }

          }

-         message._headers = {"sent-at": "2024-09-16T12:12:46+01:00"}

-         config = MagicMock()

-         config = {

-             "koji_url": "https://example.koji.org",

-             "principal": "principal",

-             "keytab": "keytab",

-         }

+         message.topic = "git.receive"

+         self.toddler_cls.koji_session.packageListBlock.__name__ = "packageListBlock"

          self.toddler_cls.koji_session.packageListBlock.side_effect = koji.GenericError(

              "Failed"

          )

-         self.toddler_cls.process_block_retired(config, message)

+         self.toddler_cls.process(config, message)

+         assert (

+             caplog.records[-2].message

+             == "Unable to create koji ClientSession for call packageListBlock: Failed"

+         )

          assert (

              caplog.records[-1].message

-             == "Failed to block retired package example-repo on branch f38: Failed"

+             == "Failed, recreating koji_session and trying again"

          )

  

+     @patch("toddlers.plugins.koji_block_retired.pagure.set_pagure")

      @patch("toddlers.plugins.koji_block_retired.KojiBlockRetired._create_session")

-     def test_koji_generic_error_stg(self, mock_session, caplog):

+     def test_koji_generic_error_stg(self, mock_session, mock_pagure, config, caplog):

          """

          Assert that Koji generic error will be handled correctly.

          """

+         mock_dist_git = MagicMock()

+         mock_dist_git.has_dead_package_on_branch.return_value = True

+         mock_pagure.return_value = mock_dist_git

+ 

          message = MagicMock()

          message.body = {

              "commit": {
@@ -219,48 +289,57 @@ 

                  "date": "2024-09-16T12:12:46+01:00",

              }

          }

-         message._headers = {"sent-at": "2024-09-16T12:12:46+01:00"}

-         config = MagicMock()

-         config = {

-             "koji_url": "https://example.koji.org",

-             "principal": "principal",

-             "keytab": "keytab",

-         }

+         message.topic = "git.receive"

+         self.toddler_cls.koji_session.packageListBlock.__name__ = "packageListBlock"

          self.toddler_cls.koji_session.packageListBlock.side_effect = koji.GenericError(

              "Failed"

          )

-         self.toddler_cls.process_block_retired(config, message)

+         self.toddler_cls.process(config, message)

+         assert (

+             caplog.records[-2].message

+             == "Unable to create koji ClientSession for call packageListBlock: Failed"

+         )

          assert (

              caplog.records[-1].message

-             == "Failed to block retired package example-epel-repo on branch f38: Failed"

+             == "Failed, recreating koji_session and trying again"

          )

  

-     def test_timedelta_of_commit_bigger_than_one_day(self, caplog):

+     @patch("toddlers.plugins.koji_block_retired.pagure.set_pagure")

+     @patch("toddlers.plugins.koji_block_retired.KojiBlockRetired._create_session")

+     def test_koji_generic_error_epel_unblock(

+         self, mock_session, mock_pagure, config, caplog

+     ):

          """

-         Assert if in commit dead package wasn't added the plugin stops.

+         Assert that Koji generic error will be handled correctly.

          """

-         caplog.set_level(logging.INFO)

+         mock_dist_git = MagicMock()

+         mock_dist_git.has_dead_package_on_branch.return_value = True

+         mock_pagure.return_value = mock_dist_git

+ 

          message = MagicMock()

          message.body = {

              "commit": {

                  "stats": {"files": {"dead.package": {"additions": 1, "deletions": 0}}},

-                 "branch": "f38",

+                 "branch": "epel9",

                  "repo": "example-epel-repo",

                  "namespace": "example_ns",

                  "date": "2024-09-16T12:12:46+01:00",

-             },

-         }

-         message._headers = {"sent-at": "2024-09-18T12:12:46+01:00"}

-         config = MagicMock()

-         config = {

-             "koji_url": "https://example.koji.org",

-             "principal": "principal",

-             "keytab": "keytab",

+             }

          }

-         self.toddler_cls.process_block_retired(config, message)

+         message.topic = "git.receive"

+         self.toddler_cls.koji_session.packageListUnblock.__name__ = "packageListUnblock"

+         self.toddler_cls.koji_session.packageListBlock.__name__ = "packageListBlock"

+         self.toddler_cls.koji_session.packageListUnblock.side_effect = (

+             koji.GenericError("Failed")

+         )

+         self.toddler_cls.process(config, message)

+         assert (

+             caplog.records[-2].message

+             == "Unable to create koji ClientSession for call packageListUnblock: Failed"

+         )

          assert (

              caplog.records[-1].message

-             == "Commit is older than 1 day, probably new branch creation, bailing."

+             == "Failed, recreating koji_session and trying again"

          )

  

      @pytest.mark.parametrize(
@@ -307,8 +386,13 @@ 

              caplog.records[-1].message == f"Failed to get {branch} tag in koji: Failed"

          )

  

+     @patch("toddlers.plugins.koji_block_retired.pagure.set_pagure")

      @patch("toddlers.plugins.koji_block_retired.KojiBlockRetired._create_session")

-     def test_branch_with_container(self, mock_session, caplog):

+     def test_branch_with_container(self, mock_session, mock_pagure, config, caplog):

+         mock_dist_git = MagicMock()

+         mock_dist_git.has_dead_package_on_branch.return_value = True

+         mock_pagure.return_value = mock_dist_git

+ 

          caplog.set_level(logging.INFO)

          message = MagicMock()

          message.body = {
@@ -320,22 +404,25 @@ 

                  "date": "2024-09-16T12:12:46+01:00",

              }

          }

-         message._headers = {"sent-at": "2024-09-16T12:12:46+01:00"}

-         config = MagicMock()

-         config = {

-             "koji_url": "https://example.koji.org",

-             "principal": "principal",

-             "keytab": "keytab",

-         }

-         self.toddler_cls.process_block_retired(config, message)

+         message.topic = MagicMock()

+         message.topic = "git.receive"

+         self.toddler_cls.koji_session.packageListBlock.__name__ = "packageListBlock"

+         self.toddler_cls.process(config, message)

          self.toddler_cls.koji_session.packageListBlock.assert_called_once_with(

              taginfo="f38-container",

              pkginfo="example-repo",

          )

  

+     @patch("toddlers.plugins.koji_block_retired.pagure.set_pagure")

      @patch("toddlers.plugins.koji_block_retired.KojiBlockRetired._create_session")

      @patch("toddlers.plugins.koji_block_retired.KojiBlockRetired.get_tag_from_target")

-     def test_branch_epel(self, mock_get_tag_from_target, mock_session, caplog):

+     def test_branch_epel(

+         self, mock_get_tag_from_target, mock_session, mock_pagure, config, caplog

+     ):

+         mock_dist_git = MagicMock()

+         mock_dist_git.has_dead_package_on_branch.return_value = True

+         mock_pagure.return_value = mock_dist_git

+ 

          mock_get_tag_from_target.return_value = "epel10.2"

          caplog.set_level(logging.INFO)

          message = MagicMock()
@@ -348,16 +435,412 @@ 

                  "date": "2024-09-16T12:12:46+01:00",

              }

          }

-         message._headers = {"sent-at": "2024-09-16T12:12:46+01:00"}

-         config = MagicMock()

+         message.topic = MagicMock()

+         message.topic = "git.receive"

  

-         config = {

-             "koji_url": "https://example.koji.org",

-             "principal": "principal",

-             "keytab": "keytab",

-         }

-         self.toddler_cls.process_block_retired(config, message)

+         self.toddler_cls.koji_session.packageListBlock.__name__ = "packageListBlock"

+         self.toddler_cls.koji_session.packageListUnblock.__name__ = "packageListUnblock"

+         self.toddler_cls.process(config, message)

          self.toddler_cls.koji_session.packageListBlock.assert_called_once_with(

              taginfo="epel10.2",

              pkginfo="example-repo",

          )

+ 

+     def mocked_requests_get(*args, **kwargs):

+         class MockResponse:

+             def __init__(self, json_data, status_code):

+                 self.json_data = json_data

+                 self.status_code = status_code

+ 

+             def json(self):

+                 return self.json_data

+ 

+         if args[0] == "https://src.fedoraproject.org/lookaside/retired_in_epel9.json":

+             return MockResponse(

+                 {

+                     "epel9": [

+                         "epel_pkg",

+                         "epel_pkg1",

+                         "epel_pkg2",

+                     ]

+                 },

+                 200,

+             )

+ 

+         return MockResponse(None, 404)

+ 

+     @patch("requests.get")

+     @patch("toddlers.plugins.koji_block_retired.KojiBlockRetired.get_tag_from_target")

+     @patch("toddlers.plugins.koji_block_retired.bodhi.set_bodhi")

+     @patch("toddlers.plugins.koji_block_retired.KojiBlockRetired._create_session")

+     def test_playtime_call_epel_not_blocked(

+         self,

+         mock_create_session,

+         mock_set_bodhi,

+         mock_tag,

+         mock_req,

+         config,

+         caplog,

+     ):

+         mock_bodhi = MagicMock()

+         mock_bodhi.get_active_branches.return_value = [

+             "epel9",

+         ]

+         mock_set_bodhi.return_value = mock_bodhi

+         mock_tag.return_value = "epel9"

+         caplog.set_level(logging.INFO)

+         message = MagicMock()

+         message.topic = "toddlers.trigger.koji_block_retired"

+         mock_response = MagicMock()

+         mock_response.status_code = 200

+         mock_response.json.return_value = {

+             "epel9": [

+                 "epel_pkg",

+             ]

+         }

+ 

+         def req(*args, **kwargs):

+             if (

+                 args[0]

+                 == "https://src.fedoraproject.org/lookaside/retired_in_epel9.json"

+             ):

+                 return mock_response

+ 

+         mock_req.side_effect = req

+ 

+         self.toddler_cls.koji_session.listPackages.__name__ = "listPackages"

+         self.toddler_cls.koji_session.listPackages.return_value = [

+             {

+                 "blocked": False,

+             }

+         ]

+         self.toddler_cls.process(config, message)

+         self.toddler_cls.koji_session.listPackages.assert_called_with(

+             pkgID="epel_pkg",

+             tagID="epel9",

+         )

+         self.toddler_cls.koji_session.packageListBlock.assert_called_with(

+             taginfo="epel9", pkginfo="epel_pkg"

+         )

+         assert caplog.records[-2].message == "Blocking package epel_pkg, tag: epel9"

+         assert (

+             caplog.records[-1].message

+             == "All packages that should be blocked: {'epel9': ['epel_pkg']}"

+         )

+ 

+     @patch("requests.get")

+     @patch("toddlers.plugins.koji_block_retired.KojiBlockRetired.get_tag_from_target")

+     @patch("toddlers.plugins.koji_block_retired.bodhi.set_bodhi")

+     @patch("toddlers.plugins.koji_block_retired.KojiBlockRetired._create_session")

+     def test_playtime_call_epel_blocked(

+         self,

+         mock_create_session,

+         mock_set_bodhi,

+         mock_tag,

+         mock_req,

+         config,

+         caplog,

+     ):

+         mock_bodhi = MagicMock()

+         mock_bodhi.get_active_branches.return_value = [

+             "epel9",

+         ]

+         mock_set_bodhi.return_value = mock_bodhi

+         mock_tag.return_value = "epel9"

+         caplog.set_level(logging.INFO)

+         message = MagicMock()

+         message.topic = "toddlers.trigger.koji_block_retired"

+         mock_response = MagicMock()

+         mock_response.status_code = 200

+         mock_response.json.return_value = {

+             "epel9": [

+                 "epel_pkg",

+             ]

+         }

+ 

+         def req(*args, **kwargs):

+             if (

+                 args[0]

+                 == "https://src.fedoraproject.org/lookaside/retired_in_epel9.json"

+             ):

+                 return mock_response

+ 

+         mock_req.side_effect = req

+         self.toddler_cls.koji_session.listPackages.__name__ = "listPackages"

+         self.toddler_cls.koji_session.packageListBlock.__name__ = "packageListBlock"

+         self.toddler_cls.koji_session.listPackages.return_value = [

+             {

+                 "blocked": True,

+             }

+         ]

+         self.toddler_cls.process(config, message)

+         self.toddler_cls.koji_session.listPackages.assert_called_once_with(

+             pkgID="epel_pkg",

+             tagID="epel9",

+         )

+         self.toddler_cls.koji_session.packageListBlock.assert_not_called()

+         assert caplog.records[-1].message == "All packages that should be blocked: {}"

+ 

+     @patch("requests.get")

+     @patch("toddlers.plugins.koji_block_retired.KojiBlockRetired.get_tag_from_target")

+     @patch("toddlers.plugins.koji_block_retired.bodhi.set_bodhi")

+     @patch("toddlers.plugins.koji_block_retired.KojiBlockRetired._create_session")

+     def test_playtime_call_rawhide_blocked(

+         self,

+         mock_create_session,

+         mock_set_bodhi,

+         mock_rawhide,

+         mock_req,

+         config,

+         caplog,

+     ):

+         mock_bodhi = MagicMock()

+         mock_bodhi.get_active_branches.return_value = [

+             "rawhide",

+         ]

+         mock_set_bodhi.return_value = mock_bodhi

+         caplog.set_level(logging.INFO)

+         message = MagicMock()

+         message.topic = "toddlers.trigger.koji_block_retired"

+         mock_response = MagicMock()

+         mock_response.status_code = 200

+         mock_response.json.return_value = {

+             "rawhide": [

+                 "fedora_pkg",

+             ]

+         }

+ 

+         def req(*args, **kwargs):

+             if (

+                 args[0]

+                 == "https://src.fedoraproject.org/lookaside/retired_in_rawhide.json"

+             ):

+                 return mock_response

+ 

+         mock_req.side_effect = req

+         mock_rawhide.return_value = "f42"

+         self.toddler_cls.koji_session.listPackages.__name__ = "listPackages"

+         self.toddler_cls.koji_session.packageListBlock.__name__ = "packageListBlock"

+         self.toddler_cls.koji_session.listPackages.return_value = [

+             {

+                 "blocked": True,

+             }

+         ]

+         self.toddler_cls.process(config, message)

+         self.toddler_cls.koji_session.listPackages.assert_called_with(

+             pkgID="fedora_pkg",

+             tagID="f42",

+         )

+         self.toddler_cls.koji_session.packageListBlock.assert_not_called()

+ 

+     @patch("requests.get")

+     @patch("toddlers.plugins.koji_block_retired.KojiBlockRetired.get_tag_from_target")

+     @patch("toddlers.plugins.koji_block_retired.bodhi.set_bodhi")

+     @patch("toddlers.plugins.koji_block_retired.KojiBlockRetired._create_session")

+     def test_playtime_call_rawhide_block_pkg_error(

+         self,

+         mock_create_session,

+         mock_set_bodhi,

+         mock_rawhide,

+         mock_req,

+         config,

+         caplog,

+     ):

+         mock_bodhi = MagicMock()

+         mock_bodhi.get_active_branches.return_value = [

+             "rawhide",

+         ]

+         mock_set_bodhi.return_value = mock_bodhi

+         caplog.set_level(logging.INFO)

+         message = MagicMock()

+         message.topic = "toddlers.trigger.koji_block_retired"

+         mock_response = MagicMock()

+         mock_response.status_code = 200

+         mock_response.json.return_value = {

+             "rawhide": [

+                 "fedora_pkg",

+             ]

+         }

+ 

+         def req(*args, **kwargs):

+             if (

+                 args[0]

+                 == "https://src.fedoraproject.org/lookaside/retired_in_rawhide.json"

+             ):

+                 return mock_response

+ 

+         mock_req.side_effect = req

+         mock_rawhide.return_value = "f42"

+         self.toddler_cls.koji_session.listPackages.__name__ = "listPackages"

+         self.toddler_cls.koji_session.packageListBlock.__name__ = "packageListBlock"

+         self.toddler_cls.koji_session.listPackages.return_value = [

+             {

+                 "blocked": False,

+             }

+         ]

+         self.toddler_cls.koji_session.packageListBlock.side_effect = koji.GenericError(

+             "fail"

+         )

+ 

+         self.toddler_cls.process(config, message)

+         self.toddler_cls.koji_session.listPackages.assert_called_with(

+             pkgID="fedora_pkg",

+             tagID="f42",

+         )

+         self.toddler_cls.koji_session.packageListBlock.assert_called_with(

+             taginfo="f42", pkginfo="fedora_pkg"

+         )

+         assert (

+             caplog.records[-6].message

+             == "Checking if package fedora_pkg is blocked in koji for release f42"

+         )

+         assert caplog.records[-5].message == "Blocking package fedora_pkg, tag: f42"

+         assert (

+             caplog.records[-4].message

+             == "fail, recreating koji_session and trying again"

+         )

+         assert (

+             caplog.records[-3].message

+             == "Unable to create koji ClientSession for call packageListBlock: fail"

+         )

+         assert (

+             caplog.records[-2].message

+             == "fail, recreating koji_session and trying again"

+         )

+         assert (

+             caplog.records[-1].message

+             == "All packages that should be blocked: {'f42': ['fedora_pkg']}"

+         )

+ 

+     @patch("requests.get")

+     @patch("toddlers.plugins.koji_block_retired.KojiBlockRetired.get_tag_from_target")

+     @patch("toddlers.plugins.koji_block_retired.bodhi.set_bodhi")

+     @patch("toddlers.plugins.koji_block_retired.KojiBlockRetired._create_session")

+     def test_playtime_call_rawhide_list_pkg_error(

+         self,

+         mock_create_session,

+         mock_set_bodhi,

+         mock_rawhide,

+         mock_req,

+         config,

+         caplog,

+     ):

+         mock_bodhi = MagicMock()

+         mock_bodhi.get_active_branches.return_value = [

+             "rawhide",

+         ]

+         mock_set_bodhi.return_value = mock_bodhi

+         caplog.set_level(logging.INFO)

+         message = MagicMock()

+         message.topic = "toddlers.trigger.koji_block_retired"

+         mock_response = MagicMock()

+         mock_response.status_code = 200

+         mock_response.json.return_value = {

+             "rawhide": [

+                 "fedora_pkg",

+             ]

+         }

+ 

+         def req(*args, **kwargs):

+             if (

+                 args[0]

+                 == "https://src.fedoraproject.org/lookaside/retired_in_rawhide.json"

+             ):

+                 return mock_response

+ 

+         mock_req.side_effect = req

+         mock_rawhide.return_value = "f42"

+         self.toddler_cls.koji_session.listPackages.__name__ = "listPackages"

+         self.toddler_cls.koji_session.packageListBlock.__name__ = "packageListBlock"

+         self.toddler_cls.koji_session.listPackages.side_effect = koji.GenericError(

+             "fail"

+         )

+         self.toddler_cls.process(config, message)

+         self.toddler_cls.koji_session.listPackages.assert_called_with(

+             pkgID="fedora_pkg",

+             tagID="f42",

+         )

+         assert (

+             caplog.records[-5].message

+             == "Checking if package fedora_pkg is blocked in koji for release f42"

+         )

+         assert (

+             caplog.records[-4].message

+             == "fail, recreating koji_session and trying again"

+         )

+         assert (

+             caplog.records[-3].message

+             == "Unable to create koji ClientSession for call listPackages: fail"

+         )

+         assert (

+             caplog.records[-2].message

+             == "fail, recreating koji_session and trying again"

+         )

+         assert caplog.records[-1].message == "Not able to get data from koji, bailing."

+ 

+         self.toddler_cls.koji_session.packageListBlock.assert_not_called()

+ 

+     @patch("requests.get")

+     @patch("toddlers.plugins.koji_block_retired.KojiBlockRetired.get_tag_from_target")

+     @patch("toddlers.plugins.koji_block_retired.bodhi.set_bodhi")

+     @patch("toddlers.plugins.koji_block_retired.KojiBlockRetired._create_session")

+     def test_playtime_call_rawhide_not_blocked(

+         self,

+         mock_create_session,

+         mock_set_bodhi,

+         mock_rawhide,

+         mock_req,

+         config,

+         caplog,

+     ):

+         mock_bodhi = MagicMock()

+         mock_bodhi.get_active_branches.return_value = [

+             "rawhide",

+         ]

+         mock_set_bodhi.return_value = mock_bodhi

+         caplog.set_level(logging.INFO)

+         message = MagicMock()

+         message.topic = "toddlers.trigger.koji_block_retired"

+         mock_response = MagicMock()

+         mock_response.status_code = 200

+         mock_response.json.return_value = {

+             "rawhide": [

+                 "fedora_pkg",

+             ]

+         }

+ 

+         def req(*args, **kwargs):

+             if (

+                 args[0]

+                 == "https://src.fedoraproject.org/lookaside/retired_in_rawhide.json"

+             ):

+                 return mock_response

+ 

+         mock_req.side_effect = req

+         mock_rawhide.return_value = "f42"

+         self.toddler_cls.koji_session.listPackages.return_value = [

+             {

+                 "blocked": False,

+             }

+         ]

+         self.toddler_cls.koji_session.listPackages.__name__ = "listPackages"

+         self.toddler_cls.koji_session.packageListBlock.__name__ = "packageListBlock"

+         self.toddler_cls.process(config, message)

+         self.toddler_cls.koji_session.listPackages.assert_called_with(

+             pkgID="fedora_pkg",

+             tagID="f42",

+         )

+         self.toddler_cls.koji_session.packageListBlock.assert_called_with(

+             taginfo="f42", pkginfo="fedora_pkg"

+         )

+ 

+     def test_adjust_releases_for_lookaside(self):

+         releases = ["epel8", "epel9", "epel10", "f40", "f41", "f42"]

+         assert self.toddler_cls.adjust_releases_for_lookaside(releases) == [

+             "epel10",

+             "epel8",

+             "epel9",

+             "f40",

+             "f41",

+             "rawhide",

+         ]

@@ -1832,6 +1832,95 @@ 

          self.pagure.get_retired_packages.assert_called_with(branch)

  

  

+ class TestPagureHasDeadPackageOnBranch:

+     """

+     Test class for `toddlers.utils.pagure.Pagure.has_dead_package_on_branch` method.

+     """

+ 

+     def setup_method(self):

+         """

+         Setup method for the test class.

+         """

+         config = {

+             "pagure_url": "https://pagure.io",

+             "pagure_api_key": "Very secret key",

+         }

+         self.pagure = pagure.set_pagure(config)

+         self.pagure._requests_session = Mock()

+ 

+     def test_is_retired_on_branch_true(self):

+         """

+         Assert that retired package is correctly processed.

+         """

+         # Prepare

+         branch = "f40"

+         package = "package01"

+ 

+         response_mock = MagicMock()

+         response_mock.ok = True

+         response_mock.json.return_value = {

+             "content_url": "https://src.fedoraproject.org/api",

+             "name": "dead.package",

+             "type": "file",

+         }

+ 

+         self.pagure._requests_session.get.return_value = response_mock

+ 

+         # Run test

+         result = self.pagure.has_dead_package_on_branch(package, branch)

+ 

+         # Asserts

+         assert result is True

+ 

+     def test_is_retired_on_branch_false(self):

+         """

+         Assert that non-retired package is correctly processed.

+         """

+         # Prepare

+         branch = "f40"

+         package = "package01"

+ 

+         response_mock = MagicMock()

+         response_mock.ok = False

+         response_mock.json.return_value = {

+             "error": "File not found in this git repository",

+             "error_code": "EFILENOTFOUND",

+         }

+         response_mock.status_code = 404

+ 

+         self.pagure._requests_session.get.return_value = response_mock

+ 

+         # Run test

+         result = self.pagure.has_dead_package_on_branch(package, branch)

+ 

+         # Asserts

+         assert result is False

+ 

+     def test_is_retired_on_branch_error(self):

+         """

+         Assert that non-retired package is correctly processed.

+         """

+         # Prepare

+         branch = "f40"

+         package = "package01"

+ 

+         response_mock = MagicMock()

+         response_mock.ok = False

+         response_mock.json.return_value = {

+             "error": "File not found in this git repository",

+             "error_code": "EFILENOTFOUND",

+         }

+         response_mock.status_code = 501

+ 

+         self.pagure._requests_session.get.return_value = response_mock

+ 

+         # Run test

+         result = self.pagure.has_dead_package_on_branch(package, branch)

+ 

+         # Asserts

+         assert result is False

+ 

+ 

  class TestPagureOrphanPackage:

      """

      Test class for `toddlers.utils.pagure.Pagure.orphan_package` method.

@@ -5,18 +5,21 @@ 

  """

  

  import argparse

- import datetime

+ from collections import defaultdict

  import json

  import logging

  import re

  import sys

+ import time

  

  from fedora_messaging_git_hook_messages import CommitV1

  import koji

+ import requests

  import toml

  

+ from toddlers.base import ToddlerBase

+ from toddlers.utils import bodhi, pagure

  

- from ..base import ToddlerBase

  

  _log = logging.getLogger(__name__)

  
@@ -30,15 +33,34 @@ 

  

      amqp_topics = [

          "org.fedoraproject.*.git.receive",

+         "org.fedoraproject.*.toddlers.trigger.koji_block_retired",

      ]

  

      def __init__(self):

          self.koji_session = None

+         self.koji_url = None

+         self.koji_principal = None

+         self.koji_keytab = None

+         self.bodhi = None

+         self.distgit = None

  

-     def _create_session(self, koji_url, principal, keytab):

+     def accepts_topic(self, topic):

+         """Returns a boolean whether this toddler is interested in messages

+         from this specific topic.

+         """

+         if topic.startswith("org.fedoraproject."):

+             if topic.endswith("git.receive"):

+                 return True

+             if topic.endswith("toddlers.trigger.koji_block_retired"):

+                 return True

+         return False

+ 

+     def _create_session(self):  # pragma: no cover

          """Makes a koji session, that handles logging in"""

-         self.koji_session = koji.ClientSession(koji_url)

-         self.koji_session.gssapi_login(principal=principal, keytab=keytab)

+         self.koji_session = koji.ClientSession(self.koji_url)

+         self.koji_session.gssapi_login(

+             principal=self.koji_principal, keytab=self.koji_keytab

+         )

  

      def get_tag_from_target(self, branch):

          try:
@@ -50,111 +72,168 @@ 

              _log.exception(f"Failed to get {branch} tag in koji: {e}")

          return None

  

-     def accepts_topic(self, topic):

-         """Returns a boolean whether this toddler is interested in messages

-         from this specific topic.

-         """

-         return topic.startswith("org.fedoraproject.") and topic.endswith("git.receive")

+     def adjust_releases_for_lookaside(self, releases):

+         releases = list(set(releases))  # Let's remove duplicates

+         if any(re.match(r"^f\d{2,}$", regex) for regex in releases):

+             # Remove the highest value, which should be the rawhide

+             releases.remove(max(releases))

+             # And add rawhide instead

+             releases.append("rawhide")

+         releases.sort()

+         return releases

+ 

+     def find_and_block(self, config):

+         self.bodhi = bodhi.set_bodhi(config)

+         active_releases = self.bodhi.get_active_branches()

+         adjusted = self.adjust_releases_for_lookaside(active_releases)

+         base_url = f"{config['dist_git_url']}/lookaside"

+         needs_blocking = defaultdict(list)

+         for active_release in adjusted:

+             retired_url = f"{base_url}/retired_in_{active_release}.json"

+             response = requests.get(retired_url)

+             packages = response.json()[active_release]

+             for package in packages:

+                 if active_release == "rawhide":

+                     active_release = self.get_tag_from_target("rawhide")

+                 elif "epel" in active_release:

+                     active_release = self.get_tag_from_target(active_release)

+                 _log.info(

+                     f"Checking if package {package} is blocked "

+                     f"in koji for release {active_release}"

+                 )

+                 try:

+                     (resp,) = self.execute_koji_call(

+                         self.koji_session.listPackages.__name__,

+                         pkgID=package,

+                         tagID=active_release,

+                     )

+                 except TypeError:

+                     _log.error("Not able to get data from koji, bailing.")

+                     return

+ 

+                 if not resp["blocked"]:

+                     _log.info(f"Blocking package {package}, tag: {active_release}")

+                     needs_blocking[active_release].append(package)

+                     self.execute_koji_call(

+                         "packageListBlock",

+                         taginfo=active_release,

+                         pkginfo=package,

+                     )

+         _log.info(f"All packages that should be blocked: {dict(needs_blocking)}")

  

      def process(self, config, message):

-         """Process a given message."""

-         self.process_block_retired(config, message)

- 

-     def process_block_retired(self, config, message):

          """

          Blocks the package on Koji

  

          This step will check if commit has dead.package file added and block package on Koji.

          """

+         topic = message.topic

          msg = message.body

-         header = message._headers

- 

-         koji_url = f"{config['koji_url']}/kojihub"

-         principal = config["principal"]

-         keytab = config["keytab"]

- 

-         # If there is no dead.package file in commit, then it can be ignored

-         if "dead.package" not in msg["commit"]["stats"]["files"]:

-             _log.info("No dead.package in the commit, bailing")

-             return

- 

-         dead_package_commit = msg["commit"]["stats"]["files"]["dead.package"]

-         if (

-             dead_package_commit["additions"] == 0

-             and dead_package_commit["deletions"] != 0

-         ):

-             _log.info("dead.package file was not added, bailing")

-             return

- 

-         # HOTFIX: don't process messages of very old commits,

-         # those are probably resent when a new branch is created

-         commit_date = datetime.datetime.strptime(

-             msg["commit"]["date"], "%Y-%m-%dT%H:%M:%S%z"

-         )

-         sent_at = datetime.datetime.strptime(header["sent-at"], "%Y-%m-%dT%H:%M:%S%z")

  

-         delta = sent_at - commit_date

-         if delta > datetime.timedelta(days=1):

-             _log.info(

-                 "Commit is older than 1 day, probably new branch creation, bailing."

+         self.config = config

+ 

+         self.koji_url = f"{self.config}/kojihub"

+         self.principal = config["principal"]

+         self.keytab = config["keytab"]

+ 

+         if topic.endswith("toddlers.trigger.koji_block_retired"):

+             if self.koji_session is None:

+                 self._create_session()  # pragma: no cover

+             self.find_and_block(config)

+ 

+         if topic.endswith("git.receive"):

+             # If there is no dead.package file in commit, then it can be ignored

+             if "dead.package" not in msg["commit"]["stats"]["files"]:

+                 _log.info("No dead.package in the commit, bailing")

+                 return

+ 

+             dead_package_commit = msg["commit"]["stats"]["files"]["dead.package"]

+             if (

+                 dead_package_commit["additions"] == 0

+                 and dead_package_commit["deletions"] != 0

+             ):

+                 _log.info("dead.package file was not added, bailing")

+                 return

+ 

+             repo = msg["commit"]["repo"]

+             branch = msg["commit"]["branch"]

+ 

+             # Filter out cases when a new branch with a history of retiring is created.

+             # In that case the commit with a dead.package will be re-sent and would make the toddler

+             # do the blocking even when not desired.

+             # Check if the package is really retired on distgit.

+             self.dist_git = pagure.set_pagure(

+                 {

+                     "pagure_url": config.get("dist_git_url"),

+                     "pagure_api_key": config.get("dist_git_token"),

+                 }

              )

-             return

+             if not self.dist_git.has_dead_package_on_branch(repo, branch):

+                 _log.info(

+                     f"Package {repo} is not retired on the distgit branch "

+                     f"{branch}, probably new branch creation, bailing"

+                 )

+                 return

+ 

+             if self.koji_session is None:

+                 self._create_session()  # pragma: no cover

+ 

+             if branch in ["main", "rawhide"]:

+                 tag_name = self.get_tag_from_target("rawhide")

+             elif "container" in msg["commit"]["namespace"]:

+                 tag_name = (

+                     "".join([branch, "-container"])

+                     if "container" not in branch

+                     else branch

+                 )

+             elif re.match(r"^epel\d{2,}$", branch):

+                 tag_name = self.get_tag_from_target(branch)

+             else:

+                 tag_name = branch

+ 

+             _log.info("Processing Koji block retired for %s", repo)

  

-         repo = msg["commit"]["repo"]

-         branch = msg["commit"]["branch"]

- 

-         self._create_session(koji_url, principal, keytab)

- 

-         if branch in ["main", "rawhide"]:

-             tag_name = self.get_tag_from_target("rawhide")

-         elif "container" in msg["commit"]["namespace"]:

-             tag_name = (

-                 "".join([branch, "-container"]) if "container" not in branch else branch

-             )

-         elif re.match(r"^epel\d{2,}$", branch):

-             tag_name = self.get_tag_from_target(branch)

-         else:

-             tag_name = branch

- 

-         _log.info("Processing Koji block retired for %s", repo)

- 

-         # Untag builds first due to koji/mash bug:

-         # https://fedorahosted.org/koji/ticket/299

-         # FIXME: This introduces a theoretical race condition when a package is

-         # built after all builds were untagged and before the package is blocked

-         try:

-             _log.info(f"Untagging package {repo}, tag: {tag_name}")

-             self.koji_session.untagBuild(tag=tag_name, build=repo)

-         except koji.GenericError as e:

-             _log.exception(f"Failed to untag build in koji: {e}")

- 

-         try:

              _log.info(f"Blocking package {repo}, tag: {tag_name}")

-             self.koji_session.packageListBlock(taginfo=tag_name, pkginfo=repo)

-         except (koji.GenericError, koji.ActionNotAllowed) as e:

-             _log.exception(

-                 f"Failed to block retired package {repo} on branch {tag_name}: {e}"

+             self.execute_koji_call(

+                 self.koji_session.packageListBlock.__name__,

+                 taginfo=tag_name,

+                 pkginfo=repo,

              )

  

-         # TODO: In case of exception while blocking a package in koji,

-         # send email with the list of packages that failed to block

- 

-         # If a package moves from EPEL to RHEL it can only be built if it is unblocked

-         # in the epel build tag. Therefore unblock all retired EPEL packages in the

-         # built tag since it does not hurt if the package does not move to RHEL.

-         if "stg" not in koji_url:

-             if "epel" in tag_name:

-                 tag_name = "".join([tag_name, "-build"])

-                 try:

+             # If a package moves from EPEL to RHEL it can only be built if it is unblocked

+             # in the epel build tag. Therefore unblock all retired EPEL packages in the

+             # built tag since it does not hurt if the package does not move to RHEL.

+             if "stg" not in self.koji_url:

+                 if "epel" in tag_name:

+                     tag_name = "".join([tag_name, "-build"])

                      _log.info(

                          f"Unblocking EPEL tag for package: {repo}, tag: {tag_name}"

                      )

-                     self.koji_session.packageListUnblock(taginfo=tag_name, pkginfo=repo)

-                 except koji.GenericError as e:

-                     _log.exception(f"Failed unblocking epel build tag: {e}")

+                     self.execute_koji_call(

+                         self.koji_session.packageListUnblock.__name__,

+                         taginfo=tag_name,

+                         pkginfo=repo,

+                     )

+ 

+     def execute_koji_call(self, action, num_of_attempts=2, **kwargs):

+         raw_data = None

+         for i in range(num_of_attempts):

+             try:

+                 raw_data = getattr(self.koji_session, action)(**kwargs)

+                 break

+             except (koji.GenericError, koji.ActionNotAllowed) as e:

+                 if i >= num_of_attempts - 1:

+                     _log.exception(

+                         f"Unable to create koji ClientSession for call {action}: {e}"

+                     )

+                 _log.error(f"{e}, recreating koji_session and trying again")

+                 self._create_session()

+                 # Wait a bit and try again

+                 time.sleep(5)

+         return raw_data

  

  

- def get_arguments(args):

+ def get_arguments(args):  # pragma: no cover

      """Load and parse the CLI arguments."""

      parser = argparse.ArgumentParser(

          description="Checks that packagers have a valid bugzilla account"

file modified
+34
@@ -1192,6 +1192,40 @@ 

          else:

              return False

  

+     def has_dead_package_on_branch(self, package: str, branch: str) -> bool:

+         """

+         Check if the given package has dead.package in distgit on particular

+         branch. Might look the same as the function `is_retired_on_branch`.

+         The difference is that the json files in lookaside reflects the status

+         of the packages with a small delay (up to 1 day).

+ 

+         Works only with distgit.

+ 

+         Params:

+           package: Package name

+           branch: Branch name

+         """

+         distgit_url = "https://src.fedoraproject.org/api/0/rpms"

+         endpoint_url = f"{distgit_url}/{package}/tree/{branch}/f/dead.package"

+ 

+         headers = self.get_auth_header()

+ 

+         log.debug(f"Checking if the dead.package is present on branch {branch}")

+         response = self._requests_session.get(endpoint_url, headers=headers)

+ 

+         if response.ok and response.json()["name"] == "dead.package":

+             return True

+         elif response.status_code == 404:

+             return False

+         else:

+             log.error(

+                 "Error when checking for dead.package in distgit for '%s'. "

+                 "Got status_code '%s'.",

+                 branch,

+                 response.status_code,

+             )

+             return False

+ 

      def orphan_package(

          self, namespace: str, package: str, reason: str, info: str

      ) -> None:

Related issue: https://pagure.io/releng/issue/12335

First draft of how the mass blocking could look like.
It needs some polishing, so ignore the repeated functions with calls to bodhi, failing tests and general not-prettiness.
Could the logic be something like this?

@kevin @jnsamyak @humaton

Build failed. More information on how to proceed and troubleshoot errors available at https://fedoraproject.org/wiki/Zuul-based-ci
https://fedora.softwarefactory-project.io/zuul/buildset/823a82691808417697e789469bb3947c

Does anyone know what this bug is? We no longer use mash for... many many years.

I don't thnk we need to untag builds here. We want to keep around builds we distributed, and garbage collection should slowly move those off...

Does anyone know what this bug is? We no longer use mash for... many many years.

I don't thnk we need to untag builds here. We want to keep around builds we distributed, and garbage collection should slowly move those off...

Delighted to drop the untag. It was in the old releng script, so I just copied the logic. It will be much simpler now.

rebased onto c7b7479

a month ago
  • dropped the untag
  • fixed some of the tests

needs to be done: improve coverage

Build failed. More information on how to proceed and troubleshoot errors available at https://fedoraproject.org/wiki/Zuul-based-ci
https://fedora.softwarefactory-project.io/zuul/buildset/4a2dc52ce9db4730936d5aac24f7754a

Running the script, there are some retired packages unblocked in koji:

f39:
['celestia-data', 'celestia', 'ephemeral', 'infoblox-client', 'libksane', 'lorax-templates-rhel', 'nodejs-epel', 'python3.11-requests_ntlm-epel', 'python39-zstd-epel', 'python-jsonschema-epel', 'qqc2-desktop-style', 'rust-quick-xml0.22', 'wolfssl']

f40:
['anaconda-liveinst', 'golang-github-cpuguy83-md2man-epel', 'infoblox-client', 'ktp-contact-runner', 'libmetalink', 'lorax-templates-rhel', 'nodejs-epel', 'parsertl14', 'python3.11-requests_ntlm-epel', 'python39-zstd-epel', 'python-jsonschema-epel', 'qqc2-desktop-style', 'rocm-device-libs', 'telepathy-logger-qt', 'wolfssl']

epel8:
['infoblox-client', 'webextension-token-signing']

epel9:
['cxxopts', 'infoblox-client', 'wolfssl']

epel10:
['wolfssl']

rawhide and f41 are up-to-date

rebased onto b6e1024

a month ago

Still needs to improve coverage, working on it.

Build failed. More information on how to proceed and troubleshoot errors available at https://fedoraproject.org/wiki/Zuul-based-ci
https://fedora.softwarefactory-project.io/zuul/buildset/ee5ea753dd644f78a458a7b8fe612231

I think the packages you are seeing are indeed things that were retired and didn't get properly blocked, so I think that looks correct to me at least

Should I add something like dry run, that would output only the list of packages eligible for blocking, without the action of blocking them?

2 new commits added

  • koji_block_retired: fix tests
  • koji_block_retired: Add playtime call to block all retired
a month ago

Merge Failed.

This change or one of its cross-repo dependencies was unable to be automatically merged with the current state of its repository. Please rebase the change and upload a new patchset.
Warning:
Error merging pagure.io/fedora-infra/toddlers for 261,0915c6e

rebased onto bac1f97

a month ago

One more function to cover with tests and should be god to go.

Build failed. More information on how to proceed and troubleshoot errors available at https://fedoraproject.org/wiki/Zuul-based-ci
https://fedora.softwarefactory-project.io/zuul/buildset/152a36503e7045a4a9616c79687e65a9

rebased onto 239edbb

a month ago

Build failed. More information on how to proceed and troubleshoot errors available at https://fedoraproject.org/wiki/Zuul-based-ci
https://fedora.softwarefactory-project.io/zuul/buildset/c100c8b2355c4f648bb7d2a0829b8422

2 new commits added

  • koji_block_retired: fix tests
  • koji_block_retired: Add playtime call to block all retired
a month ago

Build succeeded.
https://fedora.softwarefactory-project.io/zuul/buildset/07389ff4f96347628501df08450f31a1

Ready for review.
I think it does what it should do, but it's roughly written, so there's a lot of room for improvement.
Especially
- not too happy about the get_active_releases list manipulation: https://pagure.io/fedora-infra/toddlers/pull-request/261#_2__61
- the tests would deserve parametrization

Build succeeded.
https://fedora.softwarefactory-project.io/zuul/buildset/2e602c97d3564420976d347a620001d7

1 new commit added

  • koji_block_retired: Add epel tag to playtime call
a month ago

Build succeeded.
https://fedora.softwarefactory-project.io/zuul/buildset/85cb76897ee84e0a9676c747afd057dc

I assume this is removing f<whatever_rawhide_is>, but it would be good to comment why using max for that and how that works.

This should be moved to separate method to make the code more readable.

I would rather see this in pagure utils module.

1 new commit added

  • koji_block_retired: Move playtime call to separate function
a month ago

Build succeeded.
https://fedora.softwarefactory-project.io/zuul/buildset/15b7e11595e64e87ac639670e6d5479d

1 new commit added

  • Recreate koji session in case it expires
a month ago

Removed koji_session enforcement on every request avoiding mass session creation at a theoretical event of mass blocking.
Instead renew the koji session only in case of koji error, but limit the tries to two.

Build failed. More information on how to proceed and troubleshoot errors available at https://fedoraproject.org/wiki/Zuul-based-ci
https://fedora.softwarefactory-project.io/zuul/buildset/25f643ad135b43589fb5da92cf921f4e

rebased onto d0ee330

a month ago

Build succeeded.
https://fedora.softwarefactory-project.io/zuul/buildset/b168ccd19b264f1ea1169cb65e4dd16c

Don't hardcode this value, rather make it configurable. Also naming variables x is not helpful when debugging.

This comment should be before except as this is where the session is created.

This should be probably logged just once, not for every retry > 1.

Same as above. I would maybe think about doing some kind of wrapper function as the handling is same for both places. For inspiration look at the bugzilla module and execute_bugzilla_call function

1 new commit added

  • koji_block_retired: Make use of bodhi module
a month ago

Made use of bodhi module in utils for retrieving active releases => reduced code duplication.
Improved the release list manipulation for lookaside url => now removes highest fedora release and appends "rawhide" only in case the list contains item with "f"+ two or more digits.

Thanks for the review @zlopez , working on it!

Build succeeded.
https://fedora.softwarefactory-project.io/zuul/buildset/ce0ef211d1c840b3a52f863e7f35eb87

2 new commits added

  • koji_block_retired: Solve the new branch creation by checking on distgit, not time restricting
  • koji_block_retired: Add koji_session recreator
19 days ago

Build failed. More information on how to proceed and troubleshoot errors available at https://fedoraproject.org/wiki/Zuul-based-ci
https://fedora.softwarefactory-project.io/zuul/buildset/48e1619a6c5340aea3f7f426e9eddf99

1 new commit added

  • koji_block_retired: Adjust tests to the last changes
16 days ago

Build failed. More information on how to proceed and troubleshoot errors available at https://fedoraproject.org/wiki/Zuul-based-ci
https://fedora.softwarefactory-project.io/zuul/buildset/3c6c38e71a06473584da37e5e762af5a

9 new commits added

  • koji_block_retired: Adjust tests to the last changes
  • koji_block_retired: Solve the new branch creation by checking on distgit, not time restricting
  • koji_block_retired: Add koji_session recreator
  • koji_block_retired: Make use of bodhi module
  • Recreate koji session in case it expires
  • koji_block_retired: Move playtime call to separate function
  • koji_block_retired: Add epel tag to playtime call
  • koji_block_retired: fix tests
  • koji_block_retired: Add playtime call to block all retired
16 days ago

Build failed. More information on how to proceed and troubleshoot errors available at https://fedoraproject.org/wiki/Zuul-based-ci
https://fedora.softwarefactory-project.io/zuul/buildset/7853d27ffb104efcbda3492493676b8c

Mmm...I wonder how to fix the error on python3.11...

The failure is something with the zuul dependencies, it's not related to this PR.

You should remove /api/0/rpms as this is not an API call.

Not sure if the package also contains a namespace. If not this will fail.

Docstring is missing parameters and return value descriptions. Look at the other methods in pagure.py to see how that should be written.

Few small things, otherwise looks good to merge.

rebased onto b9efe92

13 days ago

Build succeeded.
https://fedora.softwarefactory-project.io/zuul/buildset/699402673a354fdbbdd9e47c158cfe45

I fixed the zuul failure as well, it was just missing python-devel dependency.

Not sure if the package also contains a namespace. If not this will fail.

Should not contain a namespace, only package.

You should remove /api/0/rpms as this is not an API call.

I tried in ipython, it does not work without api/0/rpms nor without only api/0:

Works:

In [84]: distgit_url = "https://src.fedoraproject.org/api/0/rpms/capstone/tree/epel9/f/dead.package"

In [85]: r = requests.get(distgit_url)

In [86]: r.json()
Out[86]: 
{'content_url': 'https://src.fedoraproject.org/rpms/capstone/raw/epel9/f/dead.package',
 'name': 'dead.package',
 'type': 'file'}

Does not work:

In [87]: distgit_url = "https://src.fedoraproject.org/capstone/tree/epel9/f/dead.package"

In [88]: r = requests.get(distgit_url)

In [89]: r.json()
---------------------------------------------------------------------------
JSONDecodeError                           Traceback (most recent call last)

Does not work:

In [90]: distgit_url = "https://src.fedoraproject.org/rpms/capstone/tree/epel9/f/dead.package"

In [91]: r = requests.get(distgit_url)

In [92]: r.json()
---------------------------------------------------------------------------
JSONDecodeError                           Traceback (most recent call last)

In that case I only have some requests for docstring of the new method.

rebased onto b9efe92

13 days ago

Thanks for the review @zlopez !
Now curious to see how many things will not work in staging :)

rebased onto b9efe92

13 days ago

Build succeeded.
https://fedora.softwarefactory-project.io/zuul/buildset/a6d8a519931f4b119fa3e877f806a673

Pull-Request has been merged by lenkaseg

12 days ago