You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by gn...@apache.org on 2026/09/15 09:53:40 UTC
(maven) branch master updated: Externalize default lifecycle plugin versions to POM properties (#13080)
This is an automated email from the ASF dual-hosted git repository.
gnodet pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven.git
The following commit(s) were added to refs/heads/master by this push:
new a58de000b9 Externalize default lifecycle plugin versions to POM properties (#13080)
a58de000b9 is described below
commit a58de000b9ac556d6cfac368ed8014df24852b81
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Tue Sep 15 11:53:33 2026 +0200
Externalize default lifecycle plugin versions to POM properties (#13080)
Move the 13 hardcoded plugin version constants from Java source into
POM properties in impl/maven-core/pom.xml. The values are filtered at
build time into plugin-versions.properties and loaded at runtime by a
new PluginVersions utility class.
This makes the default lifecycle plugin versions visible to
dependency-update bots (Dependabot, Renovate) that scan POM files for
version properties, enabling automated version bump PRs.
No behavioral change: all version values are identical to the previous
hardcoded constants.
---
impl/maven-core/pom.xml | 88 ++++++++++++++++++++++
.../internal/impl/DefaultLifecycleRegistry.java | 5 +-
.../org/apache/maven/lifecycle/PluginVersions.java | 81 ++++++++++++++++++++
.../AbstractLifecycleMappingProvider.java | 45 ++++++++---
.../maven/lifecycle/plugin-versions.properties | 35 +++++++++
.../apache/maven/lifecycle/PluginVersionsTest.java | 54 +++++++++++++
6 files changed, 295 insertions(+), 13 deletions(-)
diff --git a/impl/maven-core/pom.xml b/impl/maven-core/pom.xml
index 07ffa6662b..fe8f6d10de 100644
--- a/impl/maven-core/pom.xml
+++ b/impl/maven-core/pom.xml
@@ -31,6 +31,26 @@ under the License.
<name>Maven 4 Core</name>
<description>Maven Core classes.</description>
+ <properties>
+ <!-- Default lifecycle plugin versions.
+ Maintained here so that dependency-update bots (Dependabot, Renovate)
+ can propose version bumps automatically. Values are filtered into
+ plugin-versions.properties at build time and loaded at runtime. -->
+ <version.maven-clean-plugin>3.4.0</version.maven-clean-plugin>
+ <version.maven-compiler-plugin>3.13.0</version.maven-compiler-plugin>
+ <version.maven-deploy-plugin>3.1.3</version.maven-deploy-plugin>
+ <version.maven-ear-plugin>3.3.0</version.maven-ear-plugin>
+ <version.maven-ejb-plugin>3.2.1</version.maven-ejb-plugin>
+ <version.maven-install-plugin>3.1.3</version.maven-install-plugin>
+ <version.maven-jar-plugin>3.4.2</version.maven-jar-plugin>
+ <version.maven-plugin-plugin>3.15.1</version.maven-plugin-plugin>
+ <version.maven-rar-plugin>3.0.0</version.maven-rar-plugin>
+ <version.maven-resources-plugin>3.3.1</version.maven-resources-plugin>
+ <version.maven-site-plugin>3.21.0</version.maven-site-plugin>
+ <version.maven-surefire-plugin>3.5.2</version.maven-surefire-plugin>
+ <version.maven-war-plugin>3.4.0</version.maven-war-plugin>
+ </properties>
+
<dependencies>
<!-- Maven4 API -->
<dependency>
@@ -260,6 +280,74 @@ under the License.
</resources>
<pluginManagement>
<plugins>
+ <!-- Default lifecycle plugins declared here so that dependency-update bots
+ (Dependabot, Renovate) see the version.maven-*-plugin properties as
+ actual plugin version references and can propose automated bumps. -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-clean-plugin</artifactId>
+ <version>${version.maven-clean-plugin}</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>${version.maven-compiler-plugin}</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-deploy-plugin</artifactId>
+ <version>${version.maven-deploy-plugin}</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-ear-plugin</artifactId>
+ <version>${version.maven-ear-plugin}</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-ejb-plugin</artifactId>
+ <version>${version.maven-ejb-plugin}</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-install-plugin</artifactId>
+ <version>${version.maven-install-plugin}</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>${version.maven-jar-plugin}</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-plugin-plugin</artifactId>
+ <version>${version.maven-plugin-plugin}</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-rar-plugin</artifactId>
+ <version>${version.maven-rar-plugin}</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>${version.maven-resources-plugin}</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-site-plugin</artifactId>
+ <version>${version.maven-site-plugin}</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>${version.maven-surefire-plugin}</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-war-plugin</artifactId>
+ <version>${version.maven-war-plugin}</version>
+ </plugin>
<plugin>
<groupId>org.apache.rat</groupId>
<artifactId>apache-rat-plugin</artifactId>
diff --git a/impl/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLifecycleRegistry.java b/impl/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLifecycleRegistry.java
index c2006cb732..39e0c77d12 100644
--- a/impl/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLifecycleRegistry.java
+++ b/impl/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLifecycleRegistry.java
@@ -46,6 +46,7 @@
import org.apache.maven.api.services.LookupException;
import org.apache.maven.api.spi.ExtensibleEnumProvider;
import org.apache.maven.api.spi.LifecycleProvider;
+import org.apache.maven.lifecycle.PluginVersions;
import org.apache.maven.lifecycle.mapping.LifecyclePhase;
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
@@ -416,7 +417,7 @@ static class SiteLifecycleProvider extends BaseLifecycleProvider {
static class CleanLifecycle implements Lifecycle {
- private static final String MAVEN_CLEAN_PLUGIN_VERSION = "3.4.0";
+ private static final String MAVEN_CLEAN_PLUGIN_VERSION = PluginVersions.CLEAN;
@Override
public String id() {
@@ -529,7 +530,7 @@ public Collection<Alias> aliases() {
static class SiteLifecycle implements Lifecycle {
- private static final String MAVEN_SITE_PLUGIN_VERSION = "3.21.0";
+ private static final String MAVEN_SITE_PLUGIN_VERSION = PluginVersions.SITE;
private static final String MAVEN_SITE_PLUGIN =
MAVEN_PLUGINS + "maven-site-plugin:" + MAVEN_SITE_PLUGIN_VERSION + ":";
private static final String PHASE_SITE = "site";
diff --git a/impl/maven-core/src/main/java/org/apache/maven/lifecycle/PluginVersions.java b/impl/maven-core/src/main/java/org/apache/maven/lifecycle/PluginVersions.java
new file mode 100644
index 0000000000..0a1e4a7ee9
--- /dev/null
+++ b/impl/maven-core/src/main/java/org/apache/maven/lifecycle/PluginVersions.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.lifecycle;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+/**
+ * Provides default plugin versions for the built-in lifecycle bindings.
+ * <p>
+ * Versions are read from {@code plugin-versions.properties}, which is filtered
+ * at build time from POM properties ({@code version.maven-<name>-plugin}).
+ * Centralising them in the POM makes them visible to dependency-update bots
+ * such as Dependabot and Renovate.
+ *
+ * @since 4.1.0
+ */
+public final class PluginVersions {
+
+ private static final Properties VERSIONS = new Properties();
+
+ static {
+ try (InputStream in = PluginVersions.class.getResourceAsStream("plugin-versions.properties")) {
+ if (in == null) {
+ throw new ExceptionInInitializerError("plugin-versions.properties not found on classpath");
+ }
+ VERSIONS.load(in);
+ } catch (IOException e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ private PluginVersions() {}
+
+ private static String version(String pluginArtifactId) {
+ String key = "version." + pluginArtifactId;
+ String version = VERSIONS.getProperty(key);
+ if (version == null) {
+ throw new IllegalArgumentException("No default version defined for " + pluginArtifactId + "; add " + key
+ + " to plugin-versions.properties");
+ }
+ if (version.startsWith("${")) {
+ throw new ExceptionInInitializerError("plugin-versions.properties was not filtered at build time; " + key
+ + " still contains placeholder: " + version);
+ }
+ return version;
+ }
+
+ // --- convenience constants used by lifecycle mapping providers ---
+
+ public static final String CLEAN = version("maven-clean-plugin");
+ public static final String COMPILER = version("maven-compiler-plugin");
+ public static final String DEPLOY = version("maven-deploy-plugin");
+ public static final String EAR = version("maven-ear-plugin");
+ public static final String EJB = version("maven-ejb-plugin");
+ public static final String INSTALL = version("maven-install-plugin");
+ public static final String JAR = version("maven-jar-plugin");
+ public static final String PLUGIN = version("maven-plugin-plugin");
+ public static final String RAR = version("maven-rar-plugin");
+ public static final String RESOURCES = version("maven-resources-plugin");
+ public static final String SITE = version("maven-site-plugin");
+ public static final String SUREFIRE = version("maven-surefire-plugin");
+ public static final String WAR = version("maven-war-plugin");
+}
diff --git a/impl/maven-core/src/main/java/org/apache/maven/lifecycle/providers/packaging/AbstractLifecycleMappingProvider.java b/impl/maven-core/src/main/java/org/apache/maven/lifecycle/providers/packaging/AbstractLifecycleMappingProvider.java
index ed841bcccd..3802905b43 100644
--- a/impl/maven-core/src/main/java/org/apache/maven/lifecycle/providers/packaging/AbstractLifecycleMappingProvider.java
+++ b/impl/maven-core/src/main/java/org/apache/maven/lifecycle/providers/packaging/AbstractLifecycleMappingProvider.java
@@ -23,6 +23,7 @@
import java.util.Collections;
import java.util.HashMap;
+import org.apache.maven.lifecycle.PluginVersions;
import org.apache.maven.lifecycle.mapping.DefaultLifecycleMapping;
import org.apache.maven.lifecycle.mapping.Lifecycle;
import org.apache.maven.lifecycle.mapping.LifecycleMapping;
@@ -35,29 +36,51 @@
*/
public abstract class AbstractLifecycleMappingProvider implements Provider<LifecycleMapping> {
// START SNIPPET: versions
- protected static final String RESOURCES_PLUGIN_VERSION = "3.3.1";
+ /** @deprecated Use {@link PluginVersions#RESOURCES} instead. */
+ @Deprecated(since = "4.1.0", forRemoval = true)
+ protected static final String RESOURCES_PLUGIN_VERSION = PluginVersions.RESOURCES;
- protected static final String COMPILER_PLUGIN_VERSION = "3.13.0";
+ /** @deprecated Use {@link PluginVersions#COMPILER} instead. */
+ @Deprecated(since = "4.1.0", forRemoval = true)
+ protected static final String COMPILER_PLUGIN_VERSION = PluginVersions.COMPILER;
- protected static final String SUREFIRE_PLUGIN_VERSION = "3.5.2";
+ /** @deprecated Use {@link PluginVersions#SUREFIRE} instead. */
+ @Deprecated(since = "4.1.0", forRemoval = true)
+ protected static final String SUREFIRE_PLUGIN_VERSION = PluginVersions.SUREFIRE;
- protected static final String INSTALL_PLUGIN_VERSION = "3.1.3";
+ /** @deprecated Use {@link PluginVersions#INSTALL} instead. */
+ @Deprecated(since = "4.1.0", forRemoval = true)
+ protected static final String INSTALL_PLUGIN_VERSION = PluginVersions.INSTALL;
- protected static final String DEPLOY_PLUGIN_VERSION = "3.1.3";
+ /** @deprecated Use {@link PluginVersions#DEPLOY} instead. */
+ @Deprecated(since = "4.1.0", forRemoval = true)
+ protected static final String DEPLOY_PLUGIN_VERSION = PluginVersions.DEPLOY;
// packaging
- protected static final String JAR_PLUGIN_VERSION = "3.4.2";
+ /** @deprecated Use {@link PluginVersions#JAR} instead. */
+ @Deprecated(since = "4.1.0", forRemoval = true)
+ protected static final String JAR_PLUGIN_VERSION = PluginVersions.JAR;
- protected static final String EAR_PLUGIN_VERSION = "3.3.0";
+ /** @deprecated Use {@link PluginVersions#EAR} instead. */
+ @Deprecated(since = "4.1.0", forRemoval = true)
+ protected static final String EAR_PLUGIN_VERSION = PluginVersions.EAR;
- protected static final String EJB_PLUGIN_VERSION = "3.2.1";
+ /** @deprecated Use {@link PluginVersions#EJB} instead. */
+ @Deprecated(since = "4.1.0", forRemoval = true)
+ protected static final String EJB_PLUGIN_VERSION = PluginVersions.EJB;
- protected static final String PLUGIN_PLUGIN_VERSION = "3.15.1";
+ /** @deprecated Use {@link PluginVersions#PLUGIN} instead. */
+ @Deprecated(since = "4.1.0", forRemoval = true)
+ protected static final String PLUGIN_PLUGIN_VERSION = PluginVersions.PLUGIN;
- protected static final String RAR_PLUGIN_VERSION = "3.0.0";
+ /** @deprecated Use {@link PluginVersions#RAR} instead. */
+ @Deprecated(since = "4.1.0", forRemoval = true)
+ protected static final String RAR_PLUGIN_VERSION = PluginVersions.RAR;
- protected static final String WAR_PLUGIN_VERSION = "3.4.0";
+ /** @deprecated Use {@link PluginVersions#WAR} instead. */
+ @Deprecated(since = "4.1.0", forRemoval = true)
+ protected static final String WAR_PLUGIN_VERSION = PluginVersions.WAR;
// END SNIPPET: versions
private final LifecycleMapping lifecycleMapping;
diff --git a/impl/maven-core/src/main/resources/org/apache/maven/lifecycle/plugin-versions.properties b/impl/maven-core/src/main/resources/org/apache/maven/lifecycle/plugin-versions.properties
new file mode 100644
index 0000000000..701d8a30fc
--- /dev/null
+++ b/impl/maven-core/src/main/resources/org/apache/maven/lifecycle/plugin-versions.properties
@@ -0,0 +1,35 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Default lifecycle plugin versions.
+# Values are substituted by Maven resource filtering at build time from
+# POM properties (version.maven-<name>-plugin), making them visible to
+# dependency-update bots such as Dependabot and Renovate.
+
+version.maven-clean-plugin=${version.maven-clean-plugin}
+version.maven-compiler-plugin=${version.maven-compiler-plugin}
+version.maven-deploy-plugin=${version.maven-deploy-plugin}
+version.maven-ear-plugin=${version.maven-ear-plugin}
+version.maven-ejb-plugin=${version.maven-ejb-plugin}
+version.maven-install-plugin=${version.maven-install-plugin}
+version.maven-jar-plugin=${version.maven-jar-plugin}
+version.maven-plugin-plugin=${version.maven-plugin-plugin}
+version.maven-rar-plugin=${version.maven-rar-plugin}
+version.maven-resources-plugin=${version.maven-resources-plugin}
+version.maven-site-plugin=${version.maven-site-plugin}
+version.maven-surefire-plugin=${version.maven-surefire-plugin}
+version.maven-war-plugin=${version.maven-war-plugin}
diff --git a/impl/maven-core/src/test/java/org/apache/maven/lifecycle/PluginVersionsTest.java b/impl/maven-core/src/test/java/org/apache/maven/lifecycle/PluginVersionsTest.java
new file mode 100644
index 0000000000..0f28b90297
--- /dev/null
+++ b/impl/maven-core/src/test/java/org/apache/maven/lifecycle/PluginVersionsTest.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.lifecycle;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Verifies that {@link PluginVersions} constants are properly loaded
+ * from the filtered {@code plugin-versions.properties} resource.
+ */
+class PluginVersionsTest {
+
+ @Test
+ void allConstantsAreResolvedAndNotPlaceholders() throws Exception {
+ int count = 0;
+ for (Field field : PluginVersions.class.getFields()) {
+ if (field.getType() == String.class
+ && Modifier.isStatic(field.getModifiers())
+ && Modifier.isFinal(field.getModifiers())) {
+ String value = (String) field.get(null);
+ assertNotNull(value, field.getName() + " is null");
+ assertFalse(value.startsWith("${"), field.getName() + " contains unfiltered placeholder: " + value);
+ assertFalse(value.isEmpty(), field.getName() + " is empty");
+ count++;
+ }
+ }
+ // Ensure we actually tested something — catches the case where
+ // all constants are accidentally removed or made non-public.
+ assertTrue(count >= 13, "Expected at least 13 plugin version constants, found " + count);
+ }
+}