This is an automated email from the ASF dual-hosted git repository. gnodet pushed a commit to branch fix-milestone-version-comparison in repository https://gitbox.apache.org/repos/asf/maven.git
commit 2dc04e08ee7a2550d5b8c79afac45d348ac7eeac Author: Guillaume Nodet <[email protected]> AuthorDate: Mon May 18 08:45:28 2026 +0200 Use ComparableVersion for mvnup plugin version comparison Replace hand-rolled version comparison with ComparableVersion which correctly handles milestone/pre-release qualifiers. The previous implementation stripped qualifiers (e.g., 3.0.0-M1 → 3.0.0) causing pre-release versions to be incorrectly considered sufficient. This fixes 19 projects (flink-connectors, sling) using enforcer 3.0.0-M1 that mvnup failed to upgrade to 3.0.0. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> --- .../invoker/mvnup/goals/PluginUpgradeStrategy.java | 29 ++-------------- .../mvnup/goals/PluginUpgradeStrategyTest.java | 39 ++++++++++++++++++++++ 2 files changed, 41 insertions(+), 27 deletions(-) diff --git a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/PluginUpgradeStrategy.java b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/PluginUpgradeStrategy.java index e9d145bdc5..188405cfdb 100644 --- a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/PluginUpgradeStrategy.java +++ b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/PluginUpgradeStrategy.java @@ -51,6 +51,7 @@ import org.apache.maven.api.services.ModelBuilderResult; import org.apache.maven.api.services.RepositoryFactory; import org.apache.maven.api.services.Sources; +import org.apache.maven.artifact.versioning.ComparableVersion; import org.apache.maven.cling.invoker.mvnup.UpgradeContext; import org.apache.maven.impl.standalone.ApiRunner; import org.codehaus.plexus.components.secdispatcher.Dispatcher; @@ -378,33 +379,7 @@ private boolean isVersionBelow(String currentVersion, String minVersion) { if (currentVersion == null || minVersion == null) { return false; } - - // Remove any qualifiers like -SNAPSHOT, -alpha, etc. for comparison - String cleanCurrent = currentVersion.split("-")[0]; - String cleanMin = minVersion.split("-")[0]; - - try { - String[] currentParts = cleanCurrent.split("\\."); - String[] minParts = cleanMin.split("\\."); - - int maxLength = Math.max(currentParts.length, minParts.length); - - for (int i = 0; i < maxLength; i++) { - int currentPart = i < currentParts.length ? Integer.parseInt(currentParts[i]) : 0; - int minPart = i < minParts.length ? Integer.parseInt(minParts[i]) : 0; - - if (currentPart < minPart) { - return true; - } else if (currentPart > minPart) { - return false; - } - } - - return false; // Versions are equal - } catch (NumberFormatException e) { - // Fallback to string comparison if parsing fails - return currentVersion.compareTo(minVersion) < 0; - } + return new ComparableVersion(currentVersion).compareTo(new ComparableVersion(minVersion)) < 0; } /** diff --git a/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/PluginUpgradeStrategyTest.java b/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/PluginUpgradeStrategyTest.java index 49abdf2be5..b577036539 100644 --- a/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/PluginUpgradeStrategyTest.java +++ b/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/PluginUpgradeStrategyTest.java @@ -184,6 +184,45 @@ void shouldNotModifyPluginWhenVersionAlreadySufficient() throws Exception { // POM might still be marked as modified due to other plugin management additions } + @Test + @DisplayName("should upgrade milestone version below release minimum") + void shouldUpgradeMilestoneVersionBelowRelease() throws Exception { + String pomXml = """ + <?xml version="1.0" encoding="UTF-8"?> + <project xmlns="http://maven.apache.org/POM/4.0.0"> + <modelVersion>4.0.0</modelVersion> + <groupId>test</groupId> + <artifactId>test</artifactId> + <version>1.0.0</version> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-enforcer-plugin</artifactId> + <version>3.0.0-M1</version> + </plugin> + </plugins> + </build> + </project> + """; + + Document document = Document.of(pomXml); + Map<Path, Document> pomMap = Map.of(Paths.get("pom.xml"), document); + + UpgradeContext context = createMockContext(); + UpgradeResult result = strategy.doApply(context, pomMap); + + assertTrue(result.success(), "Plugin upgrade should succeed"); + assertTrue(result.modifiedCount() > 0, "Should have upgraded 3.0.0-M1 to 3.0.0"); + + Editor editor = new Editor(document); + String version = editor.root() + .path("build", "plugins", "plugin", "version") + .map(Element::textContentTrimmed) + .orElse(null); + assertEquals("3.0.0", version, "3.0.0-M1 should be upgraded to 3.0.0"); + } + @Test @DisplayName("should upgrade plugin in pluginManagement") void shouldUpgradePluginInPluginManagement() throws Exception {
