Can a maven build tell if it is multi-module - maven

I have a multi-module maven build, with a structure like
a/
pom.xml
b/
pom.xml
c/
pom.mxl
d/pom.xml
e/
pom.xml
Some of the analysis plugins are slow, so I would like to skip them when running building multiple modules (cd a; mvn install) but not a single module (cd a/b/c; mvn install). In the single module build, I might look at the generated warnings and fix them, but with the multi-module build, they I won't look at them, since the full build literally builds dozens of modules.
Is there a way to determine if I am building multiple modules from within the build?
I am hoping for something like reactor.build is defined in all modules when I run from /a but not defined when I run from /a/b/c.
All I was able to find when I googled was how to set up a multi-module build or only build some of the projects, which is not what I am looking for.
Goals
I understand the maven build cycle. I want to be able to add something like this to my pom root pom:
<properties>
<skipSlowPlugin>${multi.project.build}</skipSlowPlugin>
<properties>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.slow</groupId>
<artifactId>analysis-tool</artifactId>
<version>1.0.0</version>
<configuration>
<skip>${skipSlowPlugin}</skip>
</configuration>
</plugin>
</plugin>
</pluginManagement>
</build>
If I run the build from /a/b/c, multi.project.build will be false and the plugin will run. If I run from /a or /a/b, then multi.project.build will be true and the plugin will not run.
In every case, I want to build everything under the current directory, so --pm and --am are irrelevant.

Related

Version of parent module in child modules specified in profiles not getting updated by Maven-release-plugin

I have a multimodule project with one module that is slow to build and only used when releasing (release-only). In the an aggregate pom i have all modules specified besides the release-only module. The release-only module is specified in a seperate profile which i activate with the maven-release-plugin and it builds it and release it fine.
The problem is the version of the parent module in the release-only module does not get updated when i run release:prepare, meaning while all other modules build (in both prepare, and perform) with the parent artifact version set correctly, the release-only module still has -SNAPSHOT in the version.
I found this what seems to be related issue. But no sollution.
https://issues.apache.org/jira/browse/MRELEASE-843
Some simplyfied code from the aggregate pom, explaining the structure.
<profile>
<id>build-rpm</id>
<modules>
<module>release-only</module>
</modules>
</profile>
<plugin>
<artifactId>maven-release-plugin</artifactId>
<configuration>
<releaseProfiles>build-rpm</releaseProfiles>
</configuration>
</plugin>
<modules>
<module>module1</module>
<module>module2</module>
</modules>
When running mvn release:prepare i want the versions in all my modules to be updated. (Like the normal mvn versions:set -DnewVersion=xxx which work as expected)
neither mvn release:update-versions
and mvn release:prepare update the versions as expected.
The simple trick is not to exclude the module by a profile instead you should make a profile inside the module. That will prevent you from such issues.
I would suggest to remove the "slow module" from the multi-module build. Instead, create a pipeline in your build server (Jenkins, Bamboo, whatever) that first builds your multi-module project and then (in the case of a release) builds the "slow module".
This way, you avoid all the hassle with modules in profiles and switching modules off and on.

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 skip specific test [duplicate]

In my maven project I have a number of modules. Is it possible to turn off running unit test for some modules via command line options?
My project takes about 15 mins to run through all unit tests. I would like to speed up the overall build by running just the unit tests in the module I am working on. I do not want to go in and edit each individual pom.xml to achieve this.
I have tried a solution outlined here: Can I run a specific testng test group via maven? However the result is a lot of test failures in modules that I want to skip. I suppose 'group' is not the same concept of module?
To toggle unit tests on and off for an entire project use Maven Surefire Plugin's capability of skipping tests. There is a drawback with using skipTests from the command line. In a multi-module build scenario, this would disable all tests across all modules.
If you need more fine grain control of running a subset of tests for a module, look into using the Maven Surefire Plugin's test inclusion and exclusion capabilities.
To allow for command-line overrides, make use of POM properties when configuring the Surefire Plugin. Take for example the following POM segment:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.9</version>
<configuration>
<excludes>
<exclude>${someModule.test.excludes}</exclude>
</excludes>
<includes>
<include>${someModule.test.includes}</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<someModule.skip.tests>false</someModule.skip.tests>
<skipTests>${someModule.skip.tests}</skipTests>
<someModule.test.includes>**/*Test.java</someModule.test.includes>
<someModule.test.excludes>**/*Test.java.bogus</someModule.test.excludes>
</properties>
With a POM like the above you can execute tests in a variety of ways.
Run all tests (the above configuration includes all **/*Test.java test source files)
mvn test
Skip all tests across all modules
mvn -DskipTests=true test
Skip all tests for a particular module
mvn -DsomeModule.skip.tests=true test
Only run certain tests for a particular module (this example includes all **/*IncludeTest.java test source files)
mvn -DsomeModule.test.includes="**/*IncludeTest.java" test
Exclude certain tests for a particular module (this example excludes all **/*ExcludeTest.java source files)
mvn -DsomeModule.test.excludes="**/*ExcludeTest.java" test
Found a way to exclude on command line:
# Exclude one test class, by using the explanation mark (!)
mvn test -Dtest=!LegacyTest
# Exclude one test method
mvn verify -Dtest=!LegacyTest#testFoo
# Exclude two test methods
mvn verify -Dtest=!LegacyTest#testFoo+testBar
# Exclude a package with a wildcard (*)
mvn test -Dtest=!com.mycompany.app.Legacy*
This is from: https://blog.jdriven.com/2017/10/run-one-or-exclude-one-test-with-maven/
…and if you like to pass the parameter to maven release plugin in Hudson/Jenkins you have to use
-Darguments=-DskipTests
to get it work.
If you want to use Maven profiles:
http://maven.apache.org/guides/introduction/introduction-to-profiles.html
you might want to make it work doing something like this:
Skipping tests in some modules in Maven
I don't know if there is a supported command line option that does the same.
You also might try using environment properties directly, something as per this doc page:
http://maven.apache.org/plugins/maven-surefire-plugin/examples/skipping-test.html
i.e. something like:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12</version>
<configuration>
<skipTests>${moduleA.skipTests}</skipTests>
</configuration>
</plugin>
then using mvn -DmoduleA.skipTests=false test to test that one module.

How to use maven to publish multiple artifacts of an ivy project(with multiple modules) to a maven repository(nexus)

I'm working on a complex multi-module open source ivy project, which has ant's build.xml at the top level to kick off each ivy module's build. But the goal here is not to modify the original build scripts(both ivy.xml and build.xml), and using maven as an outer layer to kick off ant build, and then fetch the built results and publish them to nexus server.
The difficulty here is that, the built artifacts here are multiple jars, and we need to publish all these jars to nexus server with maven. Since one pom.xml only maps one maven artifafct, and in this case multiple artifacts are build not through maven but ivy. So I wonder if there's a feasible way to achieve my goal.
Currently, in the top level pom.xml, I'm using maven-antrun-plugin to invoke build.xml on top level, and using build-helper-maven-plugin to attache artifacts, but it doesont' work.
Currently I'm working on a similar task to yours. We have a huge, full of legacy system with whole build written in ant. That is how we handle this task:
No matter what, you will have to accept it, maven = jar per artifact (well, you can use attachments with qualifiers, but it's a real abuse and highly NOT recommended). It has it's philosophy after it: in the end of the day your system consists of (as you said yourself) modules, so each module has to have it's version, sources and (most important) the dependencies to other modules.
To reuse the existing ant code you can look on the antrun plugin. What we did, is "simply" separated all the common build code (i.e generators execution, attachments creation, assemblies and so on) to parent poms that are of type "pom". Then we execute the relevant targets simply by activating properties in children poms. Here is an example
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>EXECUTION_NAME</id>
<phase>generate-sources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target if="EXECUTION_TRIGGER_PROPERTY">
<taskdef resource="net/sf/antcontrib/antlib.xml"/>
</target>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
And in the child pom we simply define
<properties>
<EXECUTION_TRIGGER_PROPERTY>true</EXECUTION_TRIGGER_PROPERTY>
</properties>
remember to look at maven lifecycle guide to choose the proper phase for your execution.
Don't forget that you can use maven plugins to make things easier. E.g instead of running <javac> task in ant, breaking to artifacts with jar type do all the compile for you. You can also find plugins that generate javadoc, jaxws and so on.
As you can see it's not that simple to make your system work with maven. It will require you to rethink how your build works. On the other hand the ability to see and understand your dependencies, the ease of working in modern IDE's, binary repositories and so on are worth it in most of the cases.

Order of maven multi module is not maintained for eclipse plugins

We have a bunch of eclipse plugin projects, features and update sites. We have created a master pom where we define the modules:
<modules>
<module>bundles/b1</module>
<module>features/f1</module>
<module>p2/site1</module>
<module>bundles/b2</module>
</modules>
We wanted to preserve this order and as per Guide to working with Multiple Modules
As per the link above we assumed that the order will be preserved as per the order in which the module elements were listed.
Our requirement:
site1 produces a site_assembly.zip. We wanted to take this zip file and wrap into around into a bundle which is what "b2" bundle does.
Our observation:
Maven reactor order which is printed at the beginning of the multi-module build is proper, however the build for every module is forked.
Because of (1) the bundle b2 get built before the site1 project is build and is able to produce a site assembly zip.
We tried adding a dependency in "b2"'s pom.xml to site1 but the build failed as it tries to build b2 first which has dependency on site1 which has not been built till now.
We observed the same behavior when we had unit test as osgi fragment. In the order we clearly specified that the host comes before the test fragment but when the maven build is invoked then it always built the fragment before the host and it used to fail.
Plugins that are defined in master pom:
<plugin>
<!-- enable tycho build extension -->
<groupId>org.eclipse.tycho</groupId>
<artifactId>tycho-maven-plugin</artifactId>
<version>${tycho-version}</version>
<extensions>true</extensions>
</plugin>
<plugin>
<groupId>org.eclipse.tycho</groupId>
<artifactId>target-platform-configuration</artifactId>
<version>${tycho-version}</version>
<configuration>
<disableP2Mirrors>true</disableP2Mirrors>
<resolver>p2</resolver>
<target>
<artifact>
<groupId>com.x.y</groupId>
<artifactId>p2.build.target</artifactId>
<version>${project.version}</version>
<classifier>x</classifier>
</artifact>
</target>
</configuration>
</plugin>
We are not sure if maven-tycho-plugin interferes with the reactor order, so any help would be appreciated.
Tycho resolves the dependencies from the Eclipse descriptor files (MANIFEST.MF, feature.xml, etc.) and re-orders the modules so that required artifacts are built first.

Resources