Override maven release goal defined in a parent POM from command-line - maven

I have a need to run alternative release goals instead of the default deploy as part of release:perform. Our company-wide parent POM defines something like the below under pluginManagement:
<plugin>
<artifactId>maven-release-plugin</artifactId>
<version>2.4.1</version>
<configuration>
<releaseProfiles>release</releaseProfiles>
<goals>deploy</goals>
</configuration>
</plugin>
I am trying to override this using -Dgoals option, but maven is ignoring this and running deploy. I tried also setting -DuseReleaseProfile=false and also changing -DreleaseProfiles and none of them seem to make any impact. I can't change the project POM as I would need to do this part of our CI framework and for arbitrary projects. I am able to override for a test project that doesn't use the above parent POM, so seems like the issue is with overriding what comes from parent POM. Are there other options I can make use of here?
Update:
This is the exact command-line: mvn -X -e -nsu release:perform -Dgoals=install -DlocalCheckout=true -Darguments="-DadditionalJOption=-Xdoclint:none -DskipTests"
I ran with mvnDebug instead of mvn and put a breakpoint in org.apache.maven.plugins.release.PerformReleaseMojo.createGoals(). When the breakpoint was hit I checked the value of goals:
main[1] stop in org.apache.maven.plugins.release.PerformReleaseMojo.createGoals
Deferring breakpoint org.apache.maven.plugins.release.PerformReleaseMojo.createGoals.
It will be set after the class is loaded.
main[1] run
> Set deferred breakpoint org.apache.maven.plugins.release.PerformReleaseMojo.createGoals
Breakpoint hit: "thread=main", org.apache.maven.plugins.release.PerformReleaseMojo.createGoals(), line=220 bci=0
main[1] print this.goals
this.goals = "deploy"
main[1] print java.lang.System.getProperty("goals")
java.lang.System.getProperty("goals") = "install"
By the time [createGoals][1] is called, goals must have been already injected, but I am not familiar with maven code to know from where.

Related

Maven release plugin executes tests twice

When release:clean release:prepare release:perform is executed , the tests are executed twice
Once at release:prepare , stage run-preparation-goals , task clean verify
And another time on release:perform ,stage run-perform-goals , task deploy
Is there any configuration option to make tests run only on first one and not being executed on perform?
BR
Yulian Oifa
That's because 2 full builds are run as part of the commands you issue.
The release:prepare section performs lots of checks on the code & repository, and does a full build to ensure all tests pass.
The release:perform section tags the repo, then pulls that tag. It performs a build based on that tag and the releases that build to your artefact store of choice (Nexus/Artifactory/wherever).
These steps are designed this way to ensure you don't pollute your repo with a tag on code that doesn't build, and tests are an integral part of your build. Once maven is happy your code is good to go, it creates the tag, and pulls it so it knows for sure that the code being released is the code referenced by the tag, and nothing else. Building that tag for release requires a full build, including the tests.
You can skip the tests on one or other of the steps, or on both, but you're missing the point of tests, and of the release plugin, if you do that.
You can override the goals parameter and add -DskipTests=true.
This parameter will skip the tests only on the perform part.
Eventually i had to change a logic.
I have executed mvn clean install release:clean release:prepare release:perform -Pmaven-release
and create a maven-release. As result the tests are executed only at install
BR
Yulian Oifa
<profile>
<id>maven-release</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<configuration>
<autoVersionSubmodules>true</autoVersionSubmodules>
<arguments>-Dmaven.test.skip</arguments>
</configuration>
</plugin>
</plugins>
</build>
</profile>
You can skip running the tests (managed by surefire plugin) with an explicitly specified parameter -DskipTests:
Something like this:
mvn release:perform -DskipTests
For intergration tests (managed by failsafe plugin) you can use a similar flag: -DskipITs
If you don't want even compile the tests you can use -Dmaven.test.skip=true (for both unit and integration tests)

Preventing non-src code module from running maven build cycle when a source file from another JVM module is run

I made a maven module that I use only to copy some files around and process them a bit. There is no java or kotlin in it, however it is a JVM-type module. For some reason though, after I did that now, the maven lifecycle runs (I think up to and including phase: package) when I try to jvm projects from other modules. Why is this happening? I just want to be able to run the MVN phases on that module manually. anyone know how to disable it for this module?
All phases are run against all modules. When you run mvn package in your root directory, it runs all the phases from Default lifecycle [1] up to package against every module that's described in your <modules>.
But phases don't do anything. They are just labels - and plugins are bound to these labels[2]. So what's done in a phase is determined by the list of plugins that are bound to that phase.
Things that you may try out:
Change packaging of your module to non-jar. Packaging determines the list of default plugins bindings. This seems to be the best option for you.
Remove the module from <modules> and run whichever plugins you need separately. Thus this module will be excluded completely from your root module.
Unbind the plugin from your module (if the plugin is inherited from the parent POM) by setting a non-existing phase to it (and all other plugins):
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>default-compile</id>
<phase>none</phase>
</execution>
</executions>
</plugin>

Maven: Define SuperPOM property project.build.directory over command line

I am building my maven project with GitLab CI on a docker file.
I would like to configure my pipeline with a "compile" stage and a "test" stage. To be able to do that, I need to set the property project.build.directory, which is defined in the maven super POM, to the docker cache so the compiled artefact does not get lost between the jobs.
project.build.directory is a predefined maven property. Therefore I would think that I am able define it with the CL parameter -Dproject.build.directory=anotherDir. This somehow does not work and my project still gets built to the default directory target.
If I modify my POM with
<properties>
<buildDir>target</buildDir>
</properties>
<build>
<directory>${buildDir}</directory>
</build>
and call mvn clean install -DbuildDir=customTargetDir, my project gets built to the customTargetDir as expected.
Why is that? I really don't see a difference. I both cases, I define the value of an existing property.

How to disable jar creation in commandline in a maven project?

I have a maven project for which I'm running two separate builds.
In one build I want to save the build time by disabling the jar creation of maven modules in it.(There are 45 maven modules). There is a Maven-Jar-Plugin that is being used to create the jars.
I want to conditionally disable the jar creation at the command line, that is, looking for something similar to -Dskiptests used to skip the unit tests though there is a surefire plugin by default.
The maven-jar-plugin does not provide any skip option.
However, several ways are possible to achieve your requirement.
You may just skip the phase which brings by default (via default mappings) the jar creation, that is, the package phase, and as such simply invoke
mvn clean test
The additional phases would not make sense if you do not create a jar file anyway: package, install, deploy would not have anything to process. Moreover, the additional integration phases may also be impacted depending on your strategy for integration tests, if any.
Alternatively, you can configure your pom as following:
<properties>
<jar.creation>package</jar.creation>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>default-jar</id>
<phase>${jar.creation}</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
As such, the default behavior would still provide a jar creation, while executing maven as following:
mvn clean install -Djar.creation=false
Would instead skip the creation of the jar.
What we are actually doing:
We are re-defining the default execution of the maven-jar-plugin
We are overriding its execution id, as such getting more control over it
We are placing its execution phase binding to a configurable (via property) phase
Default phase (property value) keeps on being package
At command line time you can still change it to any value different than a standard maven phase. That is, -Djar.creation=none would also work.

Maven: Let "mvn -Pjenkins" be the same as "mvn clean install pmd:pmd javadoc:aggregate"

We have a number of Maven jobs in our Jenkins instance, each with their own particular invocation string specified in the build configuration similar to
mvn clean install -DDISABLED="javadoc:aggregate" checkstyle:checkstyle pmd:pmd findbugs:findbugs
I would like to consolidate this so that the invocation string is stored somewhere in the POM along with suitable profile information so we can replace the invocation strings of all these slightly different jobs with a
mvn -Pjenkins
standard invocation. To my understanding the defaultGoal entry only supports a single goal which on first glance seems to be insufficient for representing our multiple goals, but might be enough if we can make it correspond to multiple entries instead. If at all possible I would like avoid setting up profile specific bindings to standard lifecycle phases if a simple invocation string will do.
You can configure additional mojos ina profile, and you can bind mojos to life cycle phases. These two things combined will allow you to run additional mojos when a certain profile is given.
This is a standard techniqued used throughout in Maven. For example, when you run "mvn release:perform", it runs a nested Maven session with "-Prelease" that does additional things, such as GPG-signing binaries.
<profile>
<id>jenkins</id>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>findbugs</goal>
</goals>
</execution>
</executions>
</plugin>
... other mojos ...
The findbugs mojo is bound by default to the compile phase, so this gets invoked automatically at the compilation phase. If you want to use a mojo that doesn't bind to any lifecycle phase by default, you add <phase>...</phase>.
See our POM in the Jenkins core for a complete example where we invoke FindBugs. The other mojos are the basically the same.
Note that for this to work, your default goal needs to invoke the life cycle phase to the certain point (say package or install.)
I don't think there's a direct way to give Maven an invocation string. As you say, you can add a custom 'jenkins' profile in which you configure the checkstyle, pmd, and findbugs plugins to be bound to a build phase (e.g. their default phase). You would still need to run mvn -Pjenkins clean install though. However this has the advantage that you can also add custom config to those plugins (e.g. to include test code in the PMD coverage).
I think you can add the settings for the checkstyle, pmd, findbugs and javadoc plugins in a profile's <build><plugins/></build> section along with a <properties> bit where you can define the javadoc property. Also, add an explicit invocation of the maven-clean-plugin attached to the clean phase. Then just invoke the build like:
mvn -Pjenkins site:site
You could even set the defaultGoal to site, if you like.

Resources