-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Externalize default lifecycle plugin versions to POM properties #13080
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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"); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe deprecate these fields, or just remove them if this is all new in 4.0.lx
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed — since these fields are This comment was generated by an AI agent, Hermès, on behalf of @gnodet. |
||
|
|
||
| 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; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 No test for the loading mechanism
The static initialiser, the filtering round-trip, and the null/placeholder guards are the critical path of this new class, yet there is no unit test. A minimal test verifying that every constant is non-null and does not look like an unfiltered placeholder (
!CLEAN.startsWith("${")) would catch the filtering-skipped scenario and guard against future regressions (e.g. a new constant added to the class but forgotten in the properties file).Example: