¿Cómo excluir un módulo de la construcción de un reactor Maven?

98

Tenemos un proyecto de Maven 2 con muchos módulos. Ejemplo:

<modules>
  <module>common</module>
  <module>foo</module>
  <module>data</module>
  <module>bar</module>
  ... more ...
</module>

Digamos que el módulo de "datos" requiere mucho tiempo de construcción y queremos excluirlo cuando el proyecto es construido por un servidor CI. Actualmente utilizamos dos archivos pom.xml para lograr esto. Uno tiene todos los módulos y el otro tiene todos los módulos excepto los que se pueden dejar fuera para CI. Pero eso es bastante molesto porque a veces nos olvidamos de poner un nuevo módulo en ambos archivos.

¿Existe una solución que no necesite dos listas de módulos independientes?

kayahr
fuente

Respuestas:

73

Lo más fácil podría ser usar profilesasí:

<project>
  ...
  <modules>
    <module>common</module>
    <module>foo</module>
    <module>bar</module>
  <modules>
  ...
  <profiles>
    <profile>
      <id>expensive-modules-to-build</id>
      <modules>
        <module>data</module>
      </modules>
    </profile>
  </profiles>
</project>

A continuación, debe consultar las formas en que puede activar perfiles

SaM
fuente
¿Qué haría usted si necesita que los datos sucedan antes de lo común? En este caso, los módulos de perfil se colocarán después de los módulos predeterminados en el orden del reactor. ¿Existe un patrón para forzar el orden?
Peter Kahn
9
El orden de los módulos NO es el orden en el que aparecerán en el reactor. La única forma de afectar el orden es crear dependencias entre módulos, es decir, utilizando la etiqueta <dependency>. No puede confiar en la orden de declaración para esto.
SaM
7
@SaM En realidad, a partir de Maven 3.0.5 el Reactor tendrá en cuenta el orden en 'módulos' , aunque el orden dictado por las dependencias es de mayor prioridad.
hellodanylo
Esto romperá algunos otros complementos que no detectan el módulo en el perfil, incluso si el perfil está habilitado
tribbloid
143

Con Maven 3.2.1, ahora puede usar -pl !<module_name>,!<module_name>para excluir ciertos módulos de la construcción del reactor.

Vea esta solicitud de función: https://issues.apache.org/jira/browse/MNG-5230

Yogesh_D
fuente
¿Es seguro cambiar de 3.0.4 a 3.2.1 o hay cambios mayores?
enero
Pasé de 3.1 a 3.2.1 sin ningún problema. Pero para ser honesto, tendrías que hacer una construcción para resolverlo.
Yogesh_D
30
No olvides escapar del signo de exclamación en la línea de comandos del shell. Tiene un significado muy especial, ver, por ejemplo, unix.stackexchange.com/questions/3747/…
Pavel
5
Desafortunadamente, actualmente hay un problema abierto en el complemento Jenkins maven-project que no admite la exclusión del módulo del reactor: issues.jenkins-ci.org/browse/JENKINS-26472
Nick Vanderhoven
@Pavel: o simplemente use en -lugar de !, es decir-pl -<module_name>
msa
45

Los proyectos a construir también se pueden especificar en la línea de comando mvn. Esto eliminaría la necesidad de un pom separado, pero en su lugar tendría que cambiar la configuración de CI cada vez que haya un nuevo módulo.

-pl,--projects <arg>                Comma-delimited list of specified
                                    reactor projects to build instead
                                    of all projects. A project can be
                                    specified by [groupId]:artifactId
                                    or by its relative path.

Quizás una combinación de esta bandera y / --also-make-dependentso --also-makereduciría esta carga de mantenimiento nuevamente.

-am,--also-make                     If project list is specified, also
                                    build projects required by the
                                    list
-amd,--also-make-dependents         If project list is specified, also
                                    build projects that depend on
                                    projects on the list
Jörn Horstmann
fuente
Esto tiene los mismos problemas que usar dos pompones separados. Tenemos lugares donde definimos los módulos. Eso es lo que intento evitar.
kayahr
Esta es una buena solución. No es necesario actualizar el pom. mvn clean install -pl mysubproject
nicolas-f
22

Supongo que desea que la compilación predeterminada siempre compile todo, independientemente de la velocidad, para que los nuevos desarrolladores puedan comenzar rápidamente sin tener que comprender mucho sobre el POM. Puedes usar perfiles como este:

<modules>
    <module>common</module>
    <module>foo</module>
    <module>bar</module>
  </modules>
  ...
  <profiles>
    <profile>
      <id>expensive-modules-to-build</id>
      <activation>
         <activeByDefault>true</activeByDefault>
      </activation>
      <modules>
        <module>data</module>
      </modules>
    </profile>
  </profiles>
</project>

El problema con esto es que si un desarrollador especifica otro perfil en la línea de comandos, expensive-modules-to-buildno se incluye (a menos que el desarrollador también lo especifique). Esto hace que sea complicado recordar qué perfiles deben incluirse.

Aquí hay una forma hacker de eso. Ambos perfiles siempre se incluyen, porque el archivo pom.xml siempre existe. Entonces, para excluir los costosos módulos, puede usarlos -P!full-builden la línea de comando.

<profiles>
    <profile>
        <id>full-build</id>
        <activation>
            <file>
                <exists>pom.xml</exists>
            </file>
        </activation>
        <modules>
            <module>data</module>
        </modules>
    </profile>
    <profile>
        <id>short-build</id>
        <activation>
            <file>
                <exists>pom.xml</exists>
            </file>
        </activation>
        <modules>
           <module>common</module>
           <module>foo</module>
           <module>bar</module>
        </modules>
    </profile>
</profiles>
Artbristol
fuente
Buena respuesta. ¿Pero realmente necesita dos perfiles en el segundo ejemplo de código? ¿No funcionaría el perfil único del primer ejemplo de código con un elemento de activación modificado?
Arend v. Reinersdorff
@ Arendv.Reinersdorff sí lo haría, sin embargo, esta respuesta también funciona con otros perfiles en la compilación que quizás desee incluir de forma predeterminada. Sin embargo, en general, creo que la otra respuesta -pl !<module_name>,!<module_name>es mejor que esta anterior
artbristol
1
Buen truco de activación. ¡Me resolvió los problemas con <activeByDefault> que no siempre está activo!
Gab
7

Otra idea: los módulos Reactor se pueden anidar, por lo que debería ser posible agrupar los módulos de construcción rápida y lenta en poms separados y luego agregar otro pom agregador que contenga estos dos como módulos. Su servidor CI solo podría hacer referencia al pom que contiene los módulos de construcción rápida.

<artifactId>fast</artifactId>
<modules>
    <module>fast-a</module>
    <module>fast-b</module>
    <module>fast-c</module>
</module>

<artifactId>all</artifactId>
<modules>
    <module>fast</module>
    <module>slow</module>
</module>
Jörn Horstmann
fuente
1

Podría utilizar perfiles de maven . En nuestro entorno de compilación, creamos un perfil quickque deshabilita muchos complementos y la ejecución de pruebas.

Esto es hecho por

    <profile>
        <id>quick</id>
        <properties>
            <skipTests>true</skipTests>
            <!-- others... -->
        </properties>   
        <build>
            <plugins>
                 <!-- configuration... -->
            </plugins>
        </build>
    </profile>

Y luego invocamos a maven de la siguiente manera

mvn groupId:artifactId:goal -P quick

Quizás podría deshabilitar la compilación y otros complementos estándar en el pom de su módulo para acelerarlo.

Nr9
fuente
2
Sí, para desactivar las pruebas, esto funciona muy bien. Pero, ¿cómo puedo usar perfiles para excluir módulos SIN tener dos listas de módulos separadas en el pom? Hasta donde yo sé, necesito poner la lista completa de módulos en una sección de perfil y la lista de módulos de creación rápida en otra sección de perfil. Entonces, esto tiene el mismo problema que usar dos pompones separados: tengo dos listas de módulos para mantener.
kayahr
Excluir el módulo no es realmente la forma de hacer las cosas en maven y mi experiencia con maven es que es mejor seguir con la forma en que se hacen las cosas, de lo contrario se producen tantos problemas ... Así que realmente lo que propongo es no retire el módulo, pero para que este módulo requiera menos tiempo.
N ° 9
El problema con maven es que 'la forma en que se hacen las cosas' frecuentemente no está alineada con 'la forma en que se hacen las cosas en el mundo real', lo que hace que la experiencia del maven sea mala y dolorosa. Los desarrolladores harían bien en tomar una dosis de entrenamiento UX.
Ed Randall
0

No es exactamente la respuesta que esta gente estaba pidiendo. Mi situación era que quería implementar solo el pom principal. Estoy usando el spring-boot-thin-layoutmódulo en un niño. Esto requiere que el módulo principal se implemente en artifactory. Agregué lo siguiente a mi proyecto. Permite saltar de instally / o deployfase.

En mi padre pom:

<properties>
    <disable.install>true</disable.install>
    <disable.deploy>true</disable.deploy>
    <enable.deployAtEnd>true</enable.deployAtEnd>
</properties>

<profiles>
    <profile>
        <id>deploy-parent</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <properties>
            <disable.install>true</disable.install>
            <disable.deploy>true</disable.deploy>
            <deployAtEnd>${enable.deployAtEnd}</deployAtEnd>
        </properties>
        <build>
            <finalName>${project.version}</finalName>
        </build>
    </profile>
</profiles>

Y en los pom (s) de mi hijo o cualquier módulo que no desee implementar con el padre:

<properties>
    <maven.install.skip>${disable.install}</maven.install.skip>
    <maven.deploy.skip>${disable.deploy}</maven.deploy.skip>
    <deployAtEnd>${enable.deployAtEnd}</deployAtEnd>
</properties>

Entonces, efectivamente, cuando ejecuto mvn deployen el pom principal, compilará todos los módulos, no ejecutará la instalación en nada, y luego, al final, implementará cualquier módulo que no tenga <maven.deploy.skip>${disable.deploy}</maven.deploy.skip>en sus propiedades. Entonces, en mi caso, solo implementando el padre.

ranma2913
fuente