Blob Blame History Raw
From 3042a8de47ea73d3fe66e6faea6b87f41aa0053d Mon Sep 17 00:00:00 2001
Message-ID: <3042a8de47ea73d3fe66e6faea6b87f41aa0053d.1692514368.git.ce+ubuntuone@sicherha.de>
From: Christoph Erhardt <ce+ubuntuone@sicherha.de>
Date: Sat, 19 Aug 2023 11:31:27 +0200
Subject: [PATCH] Fix compatibility with setuptools >= 66

The Python world, including the `setuptools` package, has migrated to
the versioning scheme defined in PEP 440. Unfortunately, the versioning
of Jenkins plugins is less strict than that. As a consequence,
`pkg_resources.parse_version()` now rejects versions as invalid.

In a patch to the external `jenkins` Python module,
`jenkins.plugins.PluginVersion` has been adjusted accordingly. Hence,
replace all calls to `pkg_resources.parse_version()` with uses of
`jenkins.plugins.PluginVersion`.

Also revert parts of commits 97ad297610b3b5d6c320a02d91eaea1dfb8654f6
and 571df29fd752cf80570f9648e1502d4571f9aaa6, which introduced a
workaround that is no longer functional and breaks with setuptools 66
and later.
---
 jenkins_jobs/modules/builders.py            | 10 ++---
 jenkins_jobs/modules/helpers.py             |  6 +--
 jenkins_jobs/modules/hipchat_notif.py       | 10 ++---
 jenkins_jobs/modules/project_maven.py       |  8 ++--
 jenkins_jobs/modules/properties.py          | 16 +++----
 jenkins_jobs/modules/publishers.py          | 48 ++++++++++-----------
 jenkins_jobs/modules/triggers.py            | 30 ++++++-------
 jenkins_jobs/modules/wrappers.py            | 24 +++++------
 jenkins_jobs/registry.py                    | 23 ----------
 requirements.txt                            |  1 -
 tests/moduleregistry/test_moduleregistry.py |  6 +--
 11 files changed, 79 insertions(+), 103 deletions(-)

diff --git a/jenkins_jobs/modules/builders.py b/jenkins_jobs/modules/builders.py
index a85bad77..1b002e4c 100644
--- a/jenkins_jobs/modules/builders.py
+++ b/jenkins_jobs/modules/builders.py
@@ -42,13 +42,13 @@ import xml.etree.ElementTree as XML
 
 import six
 
+import jenkins.plugins
 from jenkins_jobs.errors import is_sequence
 from jenkins_jobs.errors import InvalidAttributeError
 from jenkins_jobs.errors import JenkinsJobsException
 from jenkins_jobs.errors import MissingAttributeError
 import jenkins_jobs.modules.base
 import jenkins_jobs.modules.helpers as helpers
-import pkg_resources
 from jenkins_jobs.modules import hudson_model
 from jenkins_jobs.modules.publishers import ssh
 from jenkins_jobs.modules.publishers import cifs
@@ -2888,9 +2888,9 @@ def cmake(registry, xml_parent, data):
 
     info = registry.get_plugin_info("CMake plugin")
     # Note: Assume latest version of plugin is preferred config format
-    version = pkg_resources.parse_version(info.get("version", str(sys.maxsize)))
+    version = jenkins.plugins.PluginVersion(info.get("version", str(sys.maxsize)))
 
-    if version >= pkg_resources.parse_version("2.0"):
+    if version >= jenkins.plugins.PluginVersion("2.0"):
         mapping_20 = [
             ("preload-script", "preloadScript", None),  # Optional parameter
             ("working-dir", "workingDir", ""),
@@ -4703,7 +4703,7 @@ def xunit(registry, xml_parent, data):
 
     """
     info = registry.get_plugin_info("xunit")
-    plugin_version = pkg_resources.parse_version(info.get("version", str(sys.maxsize)))
+    plugin_version = jenkins.plugins.PluginVersion(info.get("version", str(sys.maxsize)))
 
     logger = logging.getLogger(__name__)
     xunit = XML.SubElement(xml_parent, "org.jenkinsci.plugins.xunit.XUnitBuilder")
@@ -4745,7 +4745,7 @@ def xunit(registry, xml_parent, data):
 
     # Generate XML for each of the supported framework types
     # Note: versions 3+ are now using the 'tools' sub-element instead of 'types'
-    if plugin_version < pkg_resources.parse_version("3.0.0"):
+    if plugin_version < jenkins.plugins.PluginVersion("3.0.0"):
         types_name = "types"
     else:
         types_name = "tools"
diff --git a/jenkins_jobs/modules/helpers.py b/jenkins_jobs/modules/helpers.py
index a0c1e788..b14c172c 100644
--- a/jenkins_jobs/modules/helpers.py
+++ b/jenkins_jobs/modules/helpers.py
@@ -23,7 +23,7 @@ from jenkins_jobs.errors import JenkinsJobsException
 from jenkins_jobs.errors import MissingAttributeError
 from jenkins_jobs.modules import hudson_model
 
-import pkg_resources
+import jenkins.plugins
 
 
 def build_trends_publisher(plugin_name, xml_element, data):
@@ -516,7 +516,7 @@ def trigger_get_parameter_order(registry, plugin):
 def trigger_project(tconfigs, project_def, registry, param_order=None):
 
     info = registry.get_plugin_info("parameterized-trigger")
-    plugin_version = pkg_resources.parse_version(info.get("version", str(sys.maxsize)))
+    plugin_version = jenkins.plugins.PluginVersion(info.get("version", str(sys.maxsize)))
 
     logger = logging.getLogger("%s:trigger_project" % __name__)
     pt_prefix = "hudson.plugins.parameterizedtrigger."
@@ -554,7 +554,7 @@ def trigger_project(tconfigs, project_def, registry, param_order=None):
                 ("fail-on-missing", "failTriggerOnMissing", False),
             ]
 
-            if plugin_version >= pkg_resources.parse_version("2.35.2"):
+            if plugin_version >= jenkins.plugins.PluginVersion("2.35.2"):
                 property_file_mapping.append(
                     ("property-multiline", "textParamValueOnNewLine", False)
                 )
diff --git a/jenkins_jobs/modules/hipchat_notif.py b/jenkins_jobs/modules/hipchat_notif.py
index 0c9640f0..f3c69fd6 100644
--- a/jenkins_jobs/modules/hipchat_notif.py
+++ b/jenkins_jobs/modules/hipchat_notif.py
@@ -73,8 +73,8 @@ Example:
 # The global config object is therefore passed down to the registry object,
 # and this object is passed to the HipChat() class initialiser.
 
+import jenkins.plugins
 import logging
-import pkg_resources
 import sys
 import xml.etree.ElementTree as XML
 
@@ -138,9 +138,9 @@ class HipChat(jenkins_jobs.modules.base.Base):
                 hipchat["rooms"] = [hipchat["room"]]
 
         plugin_info = self.registry.get_plugin_info("Jenkins HipChat Plugin")
-        version = pkg_resources.parse_version(plugin_info.get("version", "0"))
+        version = jenkins.plugins.PluginVersion(plugin_info.get("version", "0"))
 
-        if version >= pkg_resources.parse_version("0.1.9"):
+        if version >= jenkins.plugins.PluginVersion("0.1.9"):
             publishers = xml_parent.find("publishers")
             if publishers is None:
                 publishers = XML.SubElement(xml_parent, "publishers")
@@ -173,7 +173,7 @@ class HipChat(jenkins_jobs.modules.base.Base):
             hipchat.get("notify-start", hipchat.get("start-notify", False))
         ).lower()
 
-        if version >= pkg_resources.parse_version("0.1.5"):
+        if version >= jenkins.plugins.PluginVersion("0.1.5"):
             mapping = [
                 ("notify-success", "notifySuccess", False),
                 ("notify-aborted", "notifyAborted", False),
@@ -191,7 +191,7 @@ class HipChat(jenkins_jobs.modules.base.Base):
             publishers = XML.SubElement(xml_parent, "publishers")
         hippub = XML.SubElement(publishers, "jenkins.plugins.hipchat.HipChatNotifier")
 
-        if version >= pkg_resources.parse_version("0.1.8"):
+        if version >= jenkins.plugins.PluginVersion("0.1.8"):
             XML.SubElement(hippub, "buildServerUrl").text = self.jenkinsUrl
             XML.SubElement(hippub, "sendAs").text = self.sendAs
         else:
diff --git a/jenkins_jobs/modules/project_maven.py b/jenkins_jobs/modules/project_maven.py
index 91178598..248953cd 100755
--- a/jenkins_jobs/modules/project_maven.py
+++ b/jenkins_jobs/modules/project_maven.py
@@ -82,7 +82,7 @@ CFP Example:
 
     .. literalinclude:: /../../tests/general/fixtures/project-maven003.yaml
 """
-import pkg_resources
+import jenkins.plugins
 import xml.etree.ElementTree as XML
 
 from jenkins_jobs.errors import InvalidAttributeError
@@ -107,7 +107,7 @@ class Maven(jenkins_jobs.modules.base.Base):
 
         # determine version of plugin
         plugin_info = self.registry.get_plugin_info("Maven Integration plugin")
-        version = pkg_resources.parse_version(plugin_info.get("version", "0"))
+        version = jenkins.plugins.PluginVersion(plugin_info.get("version", "0"))
 
         if "root-module" in data["maven"]:
             root_module = XML.SubElement(xml_parent, "rootModule")
@@ -160,9 +160,9 @@ class Maven(jenkins_jobs.modules.base.Base):
         XML.SubElement(xml_parent, "fingerprintingDisabled").text = str(
             not data["maven"].get("automatic-fingerprinting", True)
         ).lower()
-        if version > pkg_resources.parse_version(
+        if version > jenkins.plugins.PluginVersion(
             "0"
-        ) and version < pkg_resources.parse_version("2.0.1"):
+        ) and version < jenkins.plugins.PluginVersion("2.0.1"):
             XML.SubElement(xml_parent, "perModuleEmail").text = str(
                 data.get("per-module-email", True)
             ).lower()
diff --git a/jenkins_jobs/modules/properties.py b/jenkins_jobs/modules/properties.py
index 48aaa2a4..cefb7a1a 100644
--- a/jenkins_jobs/modules/properties.py
+++ b/jenkins_jobs/modules/properties.py
@@ -32,8 +32,8 @@ Example::
           url: https://github.com/openstack-infra/jenkins-job-builder/
 """
 
+import jenkins.plugins
 import logging
-import pkg_resources
 import xml.etree.ElementTree as XML
 
 from jenkins_jobs.errors import InvalidAttributeError
@@ -480,9 +480,9 @@ def inject(registry, xml_parent, data):
 
     # determine version of plugin
     plugin_info = registry.get_plugin_info("Groovy")
-    version = pkg_resources.parse_version(plugin_info.get("version", "0"))
+    version = jenkins.plugins.PluginVersion(plugin_info.get("version", "0"))
 
-    if version >= pkg_resources.parse_version("2.0.0"):
+    if version >= jenkins.plugins.PluginVersion("2.0.0"):
         secure_groovy_script = XML.SubElement(info, "secureGroovyScript")
         mapping = [
             ("groovy-content", "script", None),
@@ -655,16 +655,16 @@ def priority_sorter(registry, xml_parent, data):
        :language: yaml
     """
     plugin_info = registry.get_plugin_info("PrioritySorter")
-    version = pkg_resources.parse_version(plugin_info.get("version", "0"))
+    version = jenkins.plugins.PluginVersion(plugin_info.get("version", "0"))
 
-    if version >= pkg_resources.parse_version("3.0"):
+    if version >= jenkins.plugins.PluginVersion("3.0"):
         priority_sorter_tag = XML.SubElement(
             xml_parent,
             "jenkins.advancedqueue.jobinclusion." "strategy.JobInclusionJobProperty",
         )
 
         mapping = [("use", "useJobGroup", True), ("priority", "jobGroupName", None)]
-    elif version >= pkg_resources.parse_version("2.0"):
+    elif version >= jenkins.plugins.PluginVersion("2.0"):
         priority_sorter_tag = XML.SubElement(
             xml_parent, "jenkins.advancedqueue.priority." "strategy.PriorityJobProperty"
         )
@@ -955,9 +955,9 @@ def slack(registry, xml_parent, data):
     logger = logging.getLogger(__name__)
 
     plugin_info = registry.get_plugin_info("Slack Notification Plugin")
-    plugin_ver = pkg_resources.parse_version(plugin_info.get("version", "0"))
+    plugin_ver = jenkins.plugins.PluginVersion(plugin_info.get("version", "0"))
 
-    if plugin_ver >= pkg_resources.parse_version("2.0"):
+    if plugin_ver >= jenkins.plugins.PluginVersion("2.0"):
         logger.warning("properties section is not used with plugin version >= 2.0")
 
     mapping = (
diff --git a/jenkins_jobs/modules/publishers.py b/jenkins_jobs/modules/publishers.py
index e2f1219c..bd10f246 100755
--- a/jenkins_jobs/modules/publishers.py
+++ b/jenkins_jobs/modules/publishers.py
@@ -25,8 +25,8 @@ the build is complete.
   :Entry Point: jenkins_jobs.publishers
 """
 
+import jenkins.plugins
 import logging
-import pkg_resources
 import sys
 import xml.etree.ElementTree as XML
 
@@ -1843,7 +1843,7 @@ def xunit(registry, xml_parent, data):
 
     """
     info = registry.get_plugin_info("xunit")
-    plugin_version = pkg_resources.parse_version(info.get("version", str(sys.maxsize)))
+    plugin_version = jenkins.plugins.PluginVersion(info.get("version", str(sys.maxsize)))
 
     logger = logging.getLogger(__name__)
     xunit = XML.SubElement(xml_parent, "xunit")
@@ -1885,7 +1885,7 @@ def xunit(registry, xml_parent, data):
 
     # Generate XML for each of the supported framework types
     # Note: versions 3+ are now using the 'tools' sub-element instead of 'types'
-    if plugin_version < pkg_resources.parse_version("3.0.0"):
+    if plugin_version < jenkins.plugins.PluginVersion("3.0.0"):
         types_name = "types"
     else:
         types_name = "tools"
@@ -2476,20 +2476,20 @@ def base_email_ext(registry, xml_parent, data, ttype):
     )
 
     info = registry.get_plugin_info("email-ext")
-    plugin_version = pkg_resources.parse_version(info.get("version", str(sys.maxsize)))
+    plugin_version = jenkins.plugins.PluginVersion(info.get("version", str(sys.maxsize)))
 
     email = XML.SubElement(trigger, "email")
 
-    if plugin_version < pkg_resources.parse_version("2.39"):
+    if plugin_version < jenkins.plugins.PluginVersion("2.39"):
         XML.SubElement(email, "recipientList").text = ""
     XML.SubElement(email, "subject").text = "$PROJECT_DEFAULT_SUBJECT"
     XML.SubElement(email, "body").text = "$PROJECT_DEFAULT_CONTENT"
-    if plugin_version >= pkg_resources.parse_version("2.39"):
+    if plugin_version >= jenkins.plugins.PluginVersion("2.39"):
         XML.SubElement(email, "replyTo").text = "$PROJECT_DEFAULT_REPLYTO"
         XML.SubElement(email, "contentType").text = "project"
     if "send-to" in data:
         recipient_providers = None
-        if plugin_version < pkg_resources.parse_version("2.39"):
+        if plugin_version < jenkins.plugins.PluginVersion("2.39"):
             XML.SubElement(email, "sendToDevelopers").text = str(
                 "developers" in data["send-to"]
             ).lower()
@@ -2572,7 +2572,7 @@ def base_email_ext(registry, xml_parent, data, ttype):
                     "hudson.plugins.emailext.plugins.recipients.UpstreamComitterRecipientProvider",
                 ).text = ""
     else:
-        if plugin_version < pkg_resources.parse_version("2.39"):
+        if plugin_version < jenkins.plugins.PluginVersion("2.39"):
             XML.SubElement(email, "sendToRequester").text = "false"
             XML.SubElement(email, "sendToDevelopers").text = "false"
             XML.SubElement(email, "includeCulprits").text = "false"
@@ -2587,7 +2587,7 @@ def base_email_ext(registry, xml_parent, data, ttype):
     if ttype == "ScriptTrigger":
         XML.SubElement(trigger, "triggerScript").text = data["trigger-script"]
 
-    if plugin_version >= pkg_resources.parse_version("2.39"):
+    if plugin_version >= jenkins.plugins.PluginVersion("2.39"):
         mappings = [
             ("attachments", "attachmentsPattern", ""),
             ("attach-build-log", "attachBuildLog", False),
@@ -2688,7 +2688,7 @@ def email_ext(registry, xml_parent, data):
     )
 
     info = registry.get_plugin_info("email-ext")
-    plugin_version = pkg_resources.parse_version(info.get("version", str(sys.maxsize)))
+    plugin_version = jenkins.plugins.PluginVersion(info.get("version", str(sys.maxsize)))
 
     if "recipients" in data:
         XML.SubElement(emailext, "recipientList").text = data["recipients"]
@@ -2754,7 +2754,7 @@ def email_ext(registry, xml_parent, data):
         ("reply-to", "replyTo", "$DEFAULT_REPLYTO"),
     ]
 
-    if plugin_version >= pkg_resources.parse_version("2.39"):
+    if plugin_version >= jenkins.plugins.PluginVersion("2.39"):
         mappings.append(("from", "from", ""))
 
     helpers.convert_mapping_to_xml(emailext, data, mappings, fail_required=True)
@@ -3129,11 +3129,11 @@ def groovy_postbuild(registry, xml_parent, data):
     # There are incompatible changes, we need to know version
     info = registry.get_plugin_info("groovy-postbuild")
     # Note: Assume latest version of plugin is preferred config format
-    version = pkg_resources.parse_version(info.get("version", str(sys.maxsize)))
+    version = jenkins.plugins.PluginVersion(info.get("version", str(sys.maxsize)))
     # Version specific predicates
-    matrix_parent_support = version >= pkg_resources.parse_version("1.9")
-    security_plugin_support = version >= pkg_resources.parse_version("2.0")
-    extra_classpath_support = version >= pkg_resources.parse_version("1.6")
+    matrix_parent_support = version >= jenkins.plugins.PluginVersion("1.9")
+    security_plugin_support = version >= jenkins.plugins.PluginVersion("2.0")
+    extra_classpath_support = version >= jenkins.plugins.PluginVersion("1.6")
 
     root_tag = "org.jvnet.hudson.plugins.groovypostbuild.GroovyPostbuildRecorder"
     groovy = XML.SubElement(xml_parent, root_tag)
@@ -4497,14 +4497,14 @@ def postbuildscript(registry, xml_parent, data):
 
     info = registry.get_plugin_info("postbuildscript")
     # Note: Assume latest version of plugin is preferred config format
-    version = pkg_resources.parse_version(info.get("version", str(sys.maxsize)))
-    if version >= pkg_resources.parse_version("2.0"):
+    version = jenkins.plugins.PluginVersion(info.get("version", str(sys.maxsize)))
+    if version >= jenkins.plugins.PluginVersion("2.0"):
         pbs_xml = XML.SubElement(pbs_xml, "config")
 
     mapping = [("mark-unstable-if-failed", "markBuildUnstable", False)]
     helpers.convert_mapping_to_xml(pbs_xml, data, mapping, fail_required=True)
 
-    if version >= pkg_resources.parse_version("2.0"):
+    if version >= jenkins.plugins.PluginVersion("2.0"):
 
         def add_execute_on(bs_data, result_xml):
             valid_values = ("matrix", "axes", "both")
@@ -6758,11 +6758,11 @@ def conditional_publisher(registry, xml_parent, data):
 
     plugin_info = registry.get_plugin_info("Flexible Publish Plugin")
     # Note: Assume latest version of plugin is preferred config format
-    version = pkg_resources.parse_version(plugin_info.get("version", str(sys.maxsize)))
+    version = jenkins.plugins.PluginVersion(plugin_info.get("version", str(sys.maxsize)))
 
     # Support for MatrixAggregator was added in v0.11
     # See JENKINS-14494
-    has_matrix_aggregator = version >= pkg_resources.parse_version("0.11")
+    has_matrix_aggregator = version >= jenkins.plugins.PluginVersion("0.11")
 
     for cond_action in data:
         cond_publisher = XML.SubElement(publishers_tag, cond_publisher_tag)
@@ -6792,7 +6792,7 @@ def conditional_publisher(registry, xml_parent, data):
 
             # XML tag changed from publisher to publisherList in v0.13
             # check the plugin version to determine further operations
-            use_publisher_list = version >= pkg_resources.parse_version("0.13")
+            use_publisher_list = version >= jenkins.plugins.PluginVersion("0.13")
 
             if use_publisher_list:
                 action_parent = XML.SubElement(cond_publisher, "publisherList")
@@ -7705,7 +7705,7 @@ def slack(registry, xml_parent, data):
 
     plugin_info = registry.get_plugin_info("Slack Notification Plugin")
     # Note: Assume latest version of plugin is preferred config format
-    plugin_ver = pkg_resources.parse_version(
+    plugin_ver = jenkins.plugins.PluginVersion(
         plugin_info.get("version", str(sys.maxsize))
     )
 
@@ -7746,10 +7746,10 @@ def slack(registry, xml_parent, data):
 
     slack = XML.SubElement(xml_parent, "jenkins.plugins.slack.SlackNotifier")
 
-    if plugin_ver >= pkg_resources.parse_version("2.0"):
+    if plugin_ver >= jenkins.plugins.PluginVersion("2.0"):
         mapping = mapping + mapping_20
 
-    if plugin_ver < pkg_resources.parse_version("2.0"):
+    if plugin_ver < jenkins.plugins.PluginVersion("2.0"):
         for yaml_name, _, default_value in mapping:
             # All arguments that don't have a default value are mandatory for
             # the plugin to work as intended.
diff --git a/jenkins_jobs/modules/triggers.py b/jenkins_jobs/modules/triggers.py
index c071b9f3..bc880701 100644
--- a/jenkins_jobs/modules/triggers.py
+++ b/jenkins_jobs/modules/triggers.py
@@ -29,8 +29,8 @@ Example::
       - timed: '@daily'
 """
 
+import jenkins.plugins
 import logging
-import pkg_resources
 import re
 import sys
 import xml.etree.ElementTree as XML
@@ -198,7 +198,7 @@ def build_gerrit_triggers(xml_parent, data, plugin_ver):
                     ("exclude-private", "excludePrivateState", False),
                     ("exclude-wip", "excludeWipState", False),
                 ]
-                if plugin_ver >= pkg_resources.parse_version("2.32.0"):
+                if plugin_ver >= jenkins.plugins.PluginVersion("2.32.0"):
                     mapping.append(
                         (
                             "commit-message-contains-regex",
@@ -241,7 +241,7 @@ def build_gerrit_skip_votes(xml_parent, data, plugin_ver):
         ("unstable", "onUnstable"),
         ("notbuilt", "onNotBuilt"),
     ]
-    if plugin_ver >= pkg_resources.parse_version("2.32.0"):
+    if plugin_ver >= jenkins.plugins.PluginVersion("2.32.0"):
         outcomes.append(("aborted", "onAborted"))
 
     skip_vote_node = XML.SubElement(xml_parent, "skipVote")
@@ -252,7 +252,7 @@ def build_gerrit_skip_votes(xml_parent, data, plugin_ver):
 
 
 def build_cancellation_policy(xml_parent, data, plugin_ver):
-    if plugin_ver >= pkg_resources.parse_version("2.32.0"):
+    if plugin_ver >= jenkins.plugins.PluginVersion("2.32.0"):
         options = [
             ("abort-new-patchsets", "abortNewPatchsets"),
             ("abort-manual-patchsets", "abortManualPatchsets"),
@@ -272,7 +272,7 @@ def build_cancellation_policy(xml_parent, data, plugin_ver):
 
 
 def build_gerrit_parameter_modes(xml_parent, data, plugin_ver):
-    if plugin_ver < pkg_resources.parse_version("2.18.0"):
+    if plugin_ver < jenkins.plugins.PluginVersion("2.18.0"):
         for parameter_name in (
             "commit-message",
             "name-and-email",
@@ -662,7 +662,7 @@ def gerrit(registry, xml_parent, data):
     gerrit_handle_legacy_configuration(data)
 
     plugin_info = registry.get_plugin_info("Gerrit Trigger")
-    plugin_ver = pkg_resources.parse_version(
+    plugin_ver = jenkins.plugins.PluginVersion(
         plugin_info.get("version", str(sys.maxsize))
     )
 
@@ -797,8 +797,8 @@ def gerrit(registry, xml_parent, data):
     XML.SubElement(gtrig, "triggerInformationAction").text = str(
         data.get("trigger-information-action", "")
     )
-    if (plugin_ver >= pkg_resources.parse_version("2.11.0")) and (
-        plugin_ver < pkg_resources.parse_version("2.14.0")
+    if (plugin_ver >= jenkins.plugins.PluginVersion("2.11.0")) and (
+        plugin_ver < jenkins.plugins.PluginVersion("2.14.0")
     ):
         XML.SubElement(gtrig, "allowTriggeringUnreviewedPatches").text = str(
             data.get("trigger-for-unreviewed-patches", False)
@@ -848,7 +848,7 @@ def gerrit(registry, xml_parent, data):
             ),
         ]
 
-        if plugin_ver >= pkg_resources.parse_version("2.31.0"):
+        if plugin_ver >= jenkins.plugins.PluginVersion("2.31.0"):
             votes.append(
                 (
                     "gerrit-build-aborted-verified-value",
@@ -876,7 +876,7 @@ def gerrit(registry, xml_parent, data):
         ("custom-url", "customUrl", ""),
         ("server-name", "serverName", "__ANY__"),
     ]
-    if plugin_ver >= pkg_resources.parse_version("2.31.0"):
+    if plugin_ver >= jenkins.plugins.PluginVersion("2.31.0"):
         message_mappings.append(("aborted-message", "buildAbortedMessage", ""))
 
     helpers.convert_mapping_to_xml(gtrig, data, message_mappings, fail_required=True)
@@ -1576,11 +1576,11 @@ def gitlab_merge_request(registry, xml_parent, data):
     plugin_info = registry.get_plugin_info("Gitlab Merge Request Builder")
 
     # Note: Assume latest version of plugin is preferred config format
-    plugin_ver = pkg_resources.parse_version(
+    plugin_ver = jenkins.plugins.PluginVersion(
         plugin_info.get("version", str(sys.maxsize))
     )
 
-    if plugin_ver >= pkg_resources.parse_version("2.0.0"):
+    if plugin_ver >= jenkins.plugins.PluginVersion("2.0.0"):
         mapping = [
             ("cron", "spec", None),
             ("project-path", "projectPath", None),
@@ -1727,13 +1727,13 @@ def gitlab(registry, xml_parent, data):
 
     plugin_info = registry.get_plugin_info("GitLab Plugin")
     # Note: Assume latest version of plugin is preferred config format
-    plugin_ver = pkg_resources.parse_version(
+    plugin_ver = jenkins.plugins.PluginVersion(
         plugin_info.get("version", str(sys.maxsize))
     )
 
     valid_merge_request = ["never", "source", "both"]
 
-    if plugin_ver >= pkg_resources.parse_version("1.1.26"):
+    if plugin_ver >= jenkins.plugins.PluginVersion("1.1.26"):
         mapping = [
             (
                 "trigger-open-merge-request-push",
@@ -1749,7 +1749,7 @@ def gitlab(registry, xml_parent, data):
         ]
         helpers.convert_mapping_to_xml(gitlab, data, mapping, fail_required=True)
 
-    if plugin_ver < pkg_resources.parse_version("1.2.0"):
+    if plugin_ver < jenkins.plugins.PluginVersion("1.2.0"):
         if data.get("branch-filter-type", "") == "All":
             data["branch-filter-type"] = ""
         valid_filters = ["", "NameBasedFilter", "RegexBasedFilter"]
diff --git a/jenkins_jobs/modules/wrappers.py b/jenkins_jobs/modules/wrappers.py
index 361b32ad..a4ed30cf 100644
--- a/jenkins_jobs/modules/wrappers.py
+++ b/jenkins_jobs/modules/wrappers.py
@@ -22,8 +22,8 @@ Wrappers can alter the way the build is run as well as the build output.
 
 """
 
+import jenkins.plugins
 import logging
-import pkg_resources
 import sys
 import xml.etree.ElementTree as XML
 
@@ -341,7 +341,7 @@ def timeout(registry, xml_parent, data):
         plugin_info = registry.get_plugin_info("Jenkins build timeout plugin")
     version = plugin_info.get("version", None)
     if version:
-        version = pkg_resources.parse_version(version)
+        version = jenkins.plugins.PluginVersion(version)
 
     valid_strategies = [
         "absolute",
@@ -353,7 +353,7 @@ def timeout(registry, xml_parent, data):
 
     # NOTE(toabctl): if we don't know the version assume that we
     # use a newer version of the plugin
-    if not version or version >= pkg_resources.parse_version("1.14"):
+    if not version or version >= jenkins.plugins.PluginVersion("1.14"):
         strategy = data.get("type", "absolute")
         if strategy not in valid_strategies:
             InvalidAttributeError("type", strategy, valid_strategies)
@@ -438,7 +438,7 @@ def timeout(registry, xml_parent, data):
         all_actions = ["fail", "abort"]
         actions = []
 
-        if version is not None and version >= pkg_resources.parse_version("1.17"):
+        if version is not None and version >= jenkins.plugins.PluginVersion("1.17"):
             all_actions.append("abort-and-restart")
 
         for action in all_actions:
@@ -967,11 +967,11 @@ def rvm_env(registry, xml_parent, data):
     ro_class = "Jenkins::Plugin::Proxies::BuildWrapper"
 
     plugin_info = registry.get_plugin_info("RVM Plugin")
-    plugin_ver = pkg_resources.parse_version(
+    plugin_ver = jenkins.plugins.PluginVersion(
         plugin_info.get("version", str(sys.maxsize))
     )
 
-    if plugin_ver >= pkg_resources.parse_version("0.5"):
+    if plugin_ver >= jenkins.plugins.PluginVersion("0.5"):
         ro_class = "Jenkins::Tasks::BuildWrapperProxy"
 
     ro = XML.SubElement(rpo, "ruby-object", {"ruby-class": ro_class, "pluginid": "rvm"})
@@ -1822,7 +1822,7 @@ def pre_scm_buildstep(registry, xml_parent, data):
     """
     # Get plugin information to maintain backwards compatibility
     info = registry.get_plugin_info("preSCMbuildstep")
-    version = pkg_resources.parse_version(info.get("version", "0"))
+    version = jenkins.plugins.PluginVersion(info.get("version", "0"))
 
     bsp = XML.SubElement(
         xml_parent, "org.jenkinsci.plugins.preSCMbuildstep." "PreSCMBuildStepsWrapper"
@@ -1833,7 +1833,7 @@ def pre_scm_buildstep(registry, xml_parent, data):
     for step in stepList:
         for edited_node in create_builders(registry, step):
             bs.append(edited_node)
-    if version >= pkg_resources.parse_version("0.3"):
+    if version >= jenkins.plugins.PluginVersion("0.3"):
         mapping = [("failOnError", "failOnError", False)]
         helpers.convert_mapping_to_xml(bsp, data, mapping, fail_required=True)
 
@@ -2050,7 +2050,7 @@ def ssh_agent_credentials(registry, xml_parent, data):
     logger = logging.getLogger(__name__)
 
     plugin_info = registry.get_plugin_info("SSH Agent Plugin")
-    plugin_ver = pkg_resources.parse_version(
+    plugin_ver = jenkins.plugins.PluginVersion(
         plugin_info.get("version", str(sys.maxsize))
     )
 
@@ -2063,7 +2063,7 @@ def ssh_agent_credentials(registry, xml_parent, data):
     user_list = list()
     if "users" in data:
         user_list += data["users"]
-        if plugin_ver >= pkg_resources.parse_version("1.5.0"):
+        if plugin_ver >= jenkins.plugins.PluginVersion("1.5.0"):
             user_parent_entry_xml = XML.SubElement(entry_xml, "credentialIds")
             xml_key = "string"
         if "user" in data:
@@ -2603,9 +2603,9 @@ def artifactory_generic(registry, xml_parent, data):
     # Get plugin information to maintain backwards compatibility
     info = registry.get_plugin_info("artifactory")
     # Note: Assume latest version of plugin is preferred config format
-    version = pkg_resources.parse_version(info.get("version", str(sys.maxsize)))
+    version = jenkins.plugins.PluginVersion(info.get("version", str(sys.maxsize)))
 
-    if version >= pkg_resources.parse_version("2.3.0"):
+    if version >= jenkins.plugins.PluginVersion("2.3.0"):
         deploy_release_repo = XML.SubElement(details, "deployReleaseRepository")
         mapping = [
             ("key-from-text", "keyFromText", ""),
diff --git a/jenkins_jobs/registry.py b/jenkins_jobs/registry.py
index 2c73744b..c9e42e00 100644
--- a/jenkins_jobs/registry.py
+++ b/jenkins_jobs/registry.py
@@ -75,29 +75,6 @@ class ModuleRegistry(object):
                 r"(.*)-(?:SNAPSHOT|BETA).*", r"\g<1>.preview", version
             )
 
-            if isinstance(
-                pkg_resources.parse_version(plugin_info["version"]),
-                pkg_resources.extern.packaging.version.LegacyVersion,
-            ):
-                plugin_info["version"] = plugin_info["version"].replace("-", "+")
-            if isinstance(
-                pkg_resources.parse_version(plugin_info["version"]),
-                pkg_resources.extern.packaging.version.LegacyVersion,
-            ):
-                plugin_name = plugin_info.get(
-                    "shortName", plugin_info.get("longName", None)
-                )
-                if plugin_name:
-                    logger.warning(
-                        "Version %s for plugin %s is being treated as a LegacyVersion"
-                        % (plugin_info["version"], plugin_name)
-                    )
-                else:
-                    logger.warning(
-                        "Version %s is being treated as a LegacyVersion"
-                        % plugin_info["version"]
-                    )
-
             aliases = []
             for key in ["longName", "shortName"]:
                 value = plugin_info.get(key, None)
diff --git a/requirements.txt b/requirements.txt
index 1764e335..4555f140 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,7 +1,6 @@
 # The order of packages is significant, because pip processes them in the order
 # of appearance. Changing the order has an impact on the overall integration
 # process, which may cause wedges in the gate later.
-setuptools<=65.7.0
 six>=1.9.0 # MIT
 PyYAML>=3.13 # MIT
 pbr>=1.8 # Apache-2.0
diff --git a/tests/moduleregistry/test_moduleregistry.py b/tests/moduleregistry/test_moduleregistry.py
index 3be1967e..320e1597 100644
--- a/tests/moduleregistry/test_moduleregistry.py
+++ b/tests/moduleregistry/test_moduleregistry.py
@@ -1,4 +1,4 @@
-import pkg_resources
+import jenkins.plugins
 from collections import namedtuple
 from operator import attrgetter
 
@@ -137,8 +137,8 @@ def test_plugin_version_comparison(registry, scenario):
     plugin_info = registry.get_plugin_info(plugin_name)
     v1 = plugin_info.get("version")
 
-    op = getattr(pkg_resources.parse_version(v1), scenario.op)
-    test = op(pkg_resources.parse_version(scenario.v2))
+    op = getattr(jenkins.plugins.PluginVersion(v1), scenario.op)
+    test = op(jenkins.plugins.PluginVersion(scenario.v2))
 
     assert test, (
         f"Unexpectedly found {v1} {scenario.v2} {scenario.op} == False"
-- 
2.41.0