176
votes

We have a need to be able to skip a submodule in certain environments.

The module in question contains integration tests and takes half an hour to run. So we want to include it when building on the CI server, but when developers build locally (and tests get run), we want to skip that module.

Is there a way to do this with a profile setting? I've done some googling and looked at the other questions/answers here and haven't found a good solution.

I suppose one option is to remove that submodule from the parent pom.xml entirely, and just add another project on our CI server to just build that module.

Suggestions?

6
Why not Maven Way? It's a perfectly valid claim to me.MaDa
Hmm. Now I can't find the places where people seemed to be arguing against this... so I've updated my original question to remove my claim that this doesn't seem to be "The Maven Way".denishaskin

6 Answers

273
votes

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
157
votes

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

39
votes

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:

4
votes

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.

2
votes

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

0
votes

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