在Maven构建期间跳过子模块

我们需要能够在某些环境中跳过子模块。

有问题的模块包含集成测试,运行需要半个小时。因此,我们希望在CI服务器上构建时包含它,但当开发人员在本地构建(并运行测试)时,我们希望跳过该模块。

有没有一种方法可以通过配置文件设置来实现这一点?我在谷歌上搜索了一下,并查看了这里的其他问题/答案,但没有找到好的解决方案。

我认为一种选择是从父pom.xml中完全删除该子模块,然后在我们的CI服务器上添加另一个项目来构建该模块。

建议?

143122 次浏览

The notion of multi-module projects is there to service the needs of codependent segments of a project. Such a client depends on the services which in turn depends on say EJBs or data-access routines. You could group your continuous integration (CI) tests in this manner. I would rationalize that by saying that the CI tests need to be in lock-step with application logic changes.

Suppose your project is structured as:

project-root
|
+ --- ci
|
+ --- client
|
+ --- server

The project-root/pom.xml defines modules

<modules>
<module>ci</module>
<module>client</module>
<module>server</module>
</modules>

The ci/pom.xml defines profiles such as:

...
<profiles>
<profile>
<id>default</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</profile>
<profile>
<id>CI</id>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skip>false</skip>
</configuration>
</plugin>
</profile>
</profiles>

This will result in Maven skipping tests in this module except when the profile named CI is active. Your CI server must be instructed to execute mvn clean package -P CI. The Maven web site has an in-depth explanation of the profiling mechanism.

Sure, this can be done using profiles. You can do something like the following in your parent pom.xml.

  ...
<modules>
<module>module1</module>
<module>module2</module>
...
</modules>
...
<profiles>
<profile>
<id>ci</id>
<modules>
<module>module1</module>
<module>module2</module>
...
<module>module-integration-test</module>
</modules>
</profile>
</profiles>
...

In your CI, you would run maven with the ci profile, i.e. mvn -P ci clean install

It's possible to decide which reactor projects to build by specifying the -pl command line argument:

$ mvn --help
[...]
-pl,--projects <arg>                   Build specified reactor projects
instead of all projects
[...]

It accepts a comma separated list of parameters in one of the following forms:

  • relative path of the folder containing the POM
  • [groupId]:artifactId

Thus, given the following structure:

project-root [com.mycorp:parent]
|
+ --- server [com.mycorp:server]
|       |
|       + --- orm [com.mycorp.server:orm]
|
+ --- client [com.mycorp:client]

You can specify the following command line:

mvn -pl .,server,:client,com.mycorp.server:orm clean install

to build everything. Remove elements in the list to build only the modules you please.


EDIT: as blackbuild pointed out, as of Maven 3.2.1 you have a new -el flag that excludes projects from the reactor, similarly to what -pl does:

Maven version 3.2.1 added this feature, you can use the -pl switch (shortcut for --projects list) with ! or - (source) to exclude certain submodules.

mvn -pl '!submodule-to-exclude' install
mvn -pl -submodule-to-exclude install

Be careful in bash the character ! is a special character, so you either have to single quote it (like I did) or escape it with the backslash character.

The syntax to exclude multiple module is the same as the inclusion

mvn -pl '!submodule1,!submodule2' install
mvn -pl -submodule1,-submodule2 install

EDIT Windows does not seem to like the single quotes, but it is necessary in bash ; in Windows, use double quotes (thanks @awilkinson)

mvn -pl "!submodule1,!submodule2" install

there is now (from 1.1.1 version) a 'skip' flag in pit.

So you can do things like :

    <profile>
<id>pit</id>
<build>
<plugins>
<plugin>
<groupId>org.pitest</groupId>
<artifactId>pitest-maven</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</profile>

in your module, and pit will skip

[INFO] --- pitest-maven:1.1.3:mutationCoverage (default-cli) @ module-selenium --- [INFO] Skipping project

Given answers here for command line usage don't work currently on newer versions of maven (at least 3.8) You also need to add ':'

mvn -pl '!:mymodule' install