Maven Enforcer Plugin: Specify rules via command line - maven

I want to execute the Maven Enforcer plugin via the command line.
I've tried:
mvn enforcer:enforce -Drules=[requireReleaseDeps]
mvn enforcer:enforce -Drules=requireReleaseDeps
I am always getting this error:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-enforcer-plugin:1.4.1:enforce (default-cli) on project lkww-util-app-wurm-admin-rs-api: The parameters 'rules' for goal org.apache.maven.plugins:maven-enforcer-plugin:1.4.1:enforce are missing or invalid -> [He
lp 1]
How do I have to specify the rules parameter?

Rather than using profiles, as recommended in another answer, you can also pre-configure your <executions> in the main section of your POM and then use the <execution>’s <id> to invoke them from the command line (see the Guide to Configuring Plug-ins for more info on this syntax):
mvn enforcer:enforcer#my-execution-id
As any <execution> of the enforce goal by defaults binds the goal to the validate phase, however, the my-execution-id execution also runs on a normal mvn clean install. If that is not desired, configure the execution with <skip>true</true> and override this on the command-line:
mvn enforcer:enforcer#my-execution-id -Denforcer.skip=false
Whether this is clearer than spreading the maven-enforcer-plugin configuration across the POM’s main section and <profiles> is a matter of personal preference.

The enforcer plugin does not allow rules to be chosen/engaged via command line parameters.
There is an open issue against the plugin for this so you could vote for that.
In the meantime, if your choice of rules can be categorised into a small number of choices then you could perhaps create profiles and associate rules with profiles thereby allowing a build to be run for a selected subset of rules by specifying a profile. In the example below there are two profiles, each of which has a different enforcer rule:
<profiles>
<profile>
<id>EnforceBannedPlugins</id>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>enforce-banned-plugins</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<bannedPlugins>
...
</bannedPlugins>
</rules>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</profile>
<profile>
<id>EnforceMavenVersion</id>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>enforce-maven-version</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireMavenVersion>
...
</requireMavenVersion>
</rules>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</profile>
</profiles>
Of course, this is only a runner if your requirement to specify enforcer rules at runtime can be satisfied by a few canned configurations. If, however, the requirement is to support any possible enforcer rule then you're out of luck because the plugin does not support that.

Related

Maven maven-dependency-plugin copy-dependencies ignores outputDirectory

I'm try to use the maven-dependency-plugin's copy-dependencies goal.
I checked its official example with the snippet below.
My problem is: the dependencies are always copied to
target\dependency folder, even if I specify an <outputDirectory> node.
Here is the part of my pom.xml:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.10</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
</execution>
<configuration>
<outputDirectory>${project.build.directory}/aaa</outputDirectory>
<overWriteReleases>true</overWriteReleases>
<overWriteSnapshots>true</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</executions>
</plugin>
</plugins>
</build>
Question: What I'm doing wrong? Is it possible to declare the output directory outside of the project? For example: c:\temp ?
You configured an execution of the maven-dependency-plugin with a configuration only defined within its scope, hence it will only be picked up by the plugin during a mvn package invocation, that is, while performing the package phase and the plugin (executions) having a binding to it.
If you invoke the plugin from command line as following:
mvn dependency:copy-dependencies
It will indeed only use default values, since your configuration will be ignored.
In fact, the default value for the outputDirectory option is indeed:
Default: ${project.build.directory}/dependency
In maven, a plugin configuration can be defined as general configuration (outside of an execution section, applied to all executions and to command line invocations) or per execution (within an execution section, like in your case).
In your case, you probably want the configuration to be valid in both cases, so simply change your plugin section to the following:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.10</version>
<configuration>
<outputDirectory>${project.build.directory}/aaa</outputDirectory>
<overWriteReleases>true</overWriteReleases>
<overWriteSnapshots>true</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Note: we moved up the configuration, from execution scope to plugin (global) scope.
Also note, in the configuration above we kept the execution, which means maven will always execute this plugin goal at each an every mvn package invocation. If you don't want this behavior and only expect to use the command line execution, then you can remove the executions section at all.
Since Maven 3.3.1 it's also possible (see the note at the very end of Using the executions Tag section):
Since Maven 3.3.1 this is not the case anymore as you can specify on the command line the execution id for direct plugin goal invocation.
to execute copy-dependencies execution directly not modifying your pom at all:
mvn dependency:copy-dependencies#copy-dependencies
Note that of the two copy-dependencies separated by #, the former refers to the plugin goal and the latter refers to the execution id. And general direct invocation of an execution is:
mvn <plugin-prefix>:<goal>#<execution>
See also accepted answer to almost the same question

Remove -SNAPSHOT from project version in pom

I have a pom with the following GAV
<groupId>com.company.services</groupId>
<artifactId>test-branch-2</artifactId>
<version>1.0.21-SNAPSHOT</version>
I want to remove -SNAPSHOT from this using maven in batch mode, so I can do it with Jenkins and not have to specify anything manually.
I've looked at the documentation for version:set but all the options offer me an interactive prompt and ask me to type a name for the version.
I would prefer the versions plugin, not the release plugin.
Since version 2.10 of the Versions Maven Plugin you can simply do:
mvn versions:set -DremoveSnapshot
If you really don't want to use the Maven Release Plugin (for whatever reason), here is how I succeed on dropping the SNAPSHOT suffix (hanbdled as a classifier) from a maven POM in a standard way (that is, no scripting, no custom maven plugin).
Given the following profile:
<profile>
<id>drop-snapshot</id>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.11</version>
<executions>
<execution>
<id>parse-version</id>
<phase>validate</phase>
<goals>
<goal>parse-version</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>versions-maven-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<id>set-version</id>
<phase>validate</phase>
<goals>
<goal>set</goal>
</goals>
<configuration>
<newVersion>${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}</newVersion>
</configuration>
</execution>
<execution>
<id>upgrade-pom</id>
<phase>validate</phase>
<goals>
<goal>commit</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
And simply executing: mvn validate -Pdrop-snapshot
The version of an example pom passed from 0.0.1-SNAPSHOT to 0.0.1.
How it actually works:
The build-helper-maven-plugin, parse-version goal, will parse the current version of the POM and set it in a set of properties having by default parsedVersion as a prefix and majorVersion, minorVersion, incrementalVersion as suffixes (check the documentation, you will also have classifier and buildNumber). Hence, after its execution we can then use in our POM the properties like ${parsedVersion.majorVersion} and so on.
The versions-maven-plugin, set goal, will then use these properties to build the new version you actually want (in this case dropping the SNAPSHOT, because we excluded the ${parsedVersion.classifier} property).
Lastly, the versions-maven-plugin, commit goal, will make these changes effective.
Similar to A_Di-Matteo's approach with build-helper, but without the need for additional plugins configuration:
mvn build-helper:parse-version versions:set \
-DnewVersion=\${parsedVersion.majorVersion} \
.\${parsedVersion.minorVersion} \
.\${parsedVersion.incrementalVersion \
.\${parsedVersion.buildNumber} \
versions:commit
This will replace your 1.0.0.0-SNAPSHOT with 1.0.0.0 in the pom.xml.
Add the following to your POM:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.11</version>
<configuration>
<name>newVersion</name>
<value>${project.version}</value>
<regex>-SNAPSHOT</regex>
<failIfNoMatch>false</failIfNoMatch>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>versions-maven-plugin</artifactId>
<version>2.2</version>
</plugin>
</plugins>
</build>
You can now remove the -SNAPSHOT part of your project's version with:
mvn build-helper:regex-property versions:set -N
The -N tells Maven to only proces the root project in case you have modules defined in your POM. This is not strictly necessary but prevents the build-helper plugin from running unnecessarily against the submodules. The versions plugin runs only on the root project in any case, and traverses all modules automatically. Consider using the reactorModuleConvergence rule of the maven-enforcer plugin to make sure multi-module projects are handled correctly.
You can run mvn versions:commit to remove the backup POM(s) generated by versions:set. Alternatively you can add <generateBackupPoms>false</generateBackupPoms> to the configuration of the versions plugin.

maven release:prepare junit

I have a need to only run a specific jUnit when the mvn release:prepare is executed. I don't want this to run under mvn install or any other goal as this jUnit is designed to see if the developer has executed a database activity first.
Is there any way to either have the junit know, by parameter(?), that the process under execution is release:prepare?
Or, is there a way to define within the pom.xml that this jUnit only runs on that goal?
I've been doing some searching on this and I cannot seem to find a solution as I'm not that good at maven as of yet. Any help is appreciated!
I haven't done exactly what you want but the key is to use the <executions> section under the SureFire :
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
... exclude the test from normal execution ...
</configuration>
<executions>
<execution>
<id>release-phase</id>
<phase>release-prepare</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
... fill this in to include the tests you want ...
</configuration>
</execution>
</executions>
<plugin>
You will also want to exclude that test in the normal <configuration> section.
There is some related information HERE
Others are close... but no cigar.
When Maven runs a release, there are no special phases for the release process. What you want to do is add a profile that is configured to include the test you want, e.g.
<profiles>
<profile>
<id>release-preflight-checks</id>
<build>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<id>release-preflight-checks</id>
<goals>
<goal>test</goal>
</goals>
<configuration>
.. include your test here
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
Then you need to configure surefire by default to not execute your preflight check
<build>
<plugins>
...
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
.. exclude your test here
</configuration>
</plugin>
...
</plugins>
</build>
And then finally, you need to tell Maven that this profile should be active only during release:prepare's forked execution
<build>
<plugins>
...
<plugin>
<artifactId>maven-release-plugin</artifactId>
<configuration>
...
<preparationGoals>clean verify -P+release-preflight-checks</preparationGoals>
...
</configuration>
</plugin>
...
</plugins>
</build>
Note: it is vitally important to have the + in front of the profile name so that you are adding the profile to the list of active profiles otherwise your release:prepare step will not be validating that the build works with the release profile active and you can have a subsequent release:perform fail.
Note: A less complex route would be to just put the surefire configuration into the release profile that you are using (by default that has the id of release but that is more error prone as you could change that via the parent pom - e.g. if you decide to push your project to central, the sonatype-oss-parent changes the release profile to sonatype-release - and then you won't see the build being failed as the test would not be executed until you change your pom to match new the release profile's id... using the -P+release-preflight-checks ensures that the profile is always active for release:prepare and additionally has the benefit of meeting the requesters original requirement completely - i.e. only runs for release:prepare and doesn't run for release:perform which would be the case if the execution was added to the release profile)

Can maven sortpom plugin affect a project's build result?

Can the Maven Sortpom Plugin affect the result of a project's build ?
Is it possible to have a project build fail just because the sortpom plugin was added ?
Normally the order of the elements in a pom.xml file does not matter, so reordering elements should not affect the build.
But I know of two exceptions to this rule:
Maven reads dependencies according to the order in the pom-file when compiling. Rearranging that order may affect the compilation output.
If two plugins executes in the same phase, the order in pom-file will determine which plugin to execute first. Sorting the plugins may cause the compilation to fail if the result of one plugin is dependent on another.
The sortpom plugin does not sort either dependencies nor plugins by default. So I would say that the sortpom plugin should not affect the result of a projects build.
It can fail a build:
[ERROR] Failed to execute goal com.google.code.sortpom:maven-sortpom-plugin:2.3.0:sort (default) on project data-extractor: scm.team.company.corp: Unknown host scm.team-project.company.corp -> [Help 1]
The if the file isn't found due to network problems, even when running with -o
Yes.
For example, you use:
org.codehaus.mojo:build-helper-maven-plugin's reserve-network-port goal in phase pre-integration-test
org.apache.tomcat.maven:tomcat7-maven-plugin's run goal also in phase pre-integration-test
Now, sortpom:sort orders them around, and in maven-3, the order of the plugins are important. So if you configure a random port for tomcat through the portName feature of reserve-network-port, the system property won't be filled (at the point it is needed), as after the sort, the build-helper artifact is executed AFTER the run goal is invoked.
Example after a sorting:
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.0</version>
<executions>
<execution>
<id>start-tomcat</id>
<phase>pre-integration-test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<fork>true</fork>
</configuration>
</execution>
<!-- ... -->
</executions>
<configuration>
<fork>true</fork>
<port>${tomcat.http.port}</port><!-- Oops, not set (yet)! -->
</configuration>
</plugin>
<!-- ... -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>${build-helper.version}</version>
<executions>
<execution>
<id>reserve-tomcat-port</id>
<phase>pre-integration-test</phase>
<goals>
<goal>reserve-network-port</goal>
</goals>
<configuration>
<portNames>
<portName>tomcat.http.port</portName><!-- Too late -->
</portNames>
</configuration>
</execution>
</executions>
</plugin>

Plugin.xml configuration of phase doesn't seem to work for my custom maven plugin

I'm playing around with writing a maven plugin for the first time. I've written a simple plugin with a goal that writes a hello world message to the output. I've also used the #phase annotation to create a default binding to the install lifecycle phase. This shows up in my plugin.xml as install element of my mojo element.
My understanding is that I can now simply add this to my build.plugins section, without specifying any execution, and my plugin goal will execute during the install phase. This doesn't happen though. Here's the configuration that doesn't create any exeuction of my goal:
<build>
<plugins>
<plugin>
<groupId>com.emc.chad</groupId>
<artifactId>hello-plugin</artifactId>
<version>0.0.1-SNAPSHOT</version>
</plugin>
</plugins>
</build>
However, if I change this to specify an execution explicitly, it works:
<plugin>
<groupId>com.emc.chad</groupId>
<artifactId>hello-plugin</artifactId>
<version>0.0.1-SNAPSHOT</version>
<executions>
<execution>
<id>test</id>
<phase>install</phase>
<goals>
<goal>hello</goal>
</goals>
<configuration>
</configuration>
</execution>
</executions>
</plugin>
I understand why this works of course, but shouldn't the first work as well, considering my plugin.xml phase specification?

Resources