Comment exclure un module d'une construction de réacteur Maven?

98

Nous avons un projet Maven 2 avec de nombreux modules. Exemple:

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

Disons que le module "data" prend du temps à construire et que nous voulons l'exclure lorsque le projet est construit par un serveur CI. Actuellement, nous utilisons deux fichiers pom.xml pour y parvenir. L'un contient tous les modules et l'autre contient tous les modules sauf ceux qui peuvent être laissés de côté pour CI. Mais c'est assez ennuyeux car parfois on oublie de mettre un nouveau module dans les deux fichiers.

Existe-t-il une solution qui ne nécessite pas deux listes de modules distinctes?

Kayahr
la source

Réponses:

73

Le plus simple pourrait être d'utiliser profilescomme ceci:

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

Vous devriez ensuite vérifier les moyens d'activer les profils

SaM
la source
Que feriez-vous si vous avez besoin de données avant le commun? Dans ce cas, les modules de profil seront placés après les modules par défaut dans l'ordre des réacteurs. Existe-t-il un modèle pour forcer l'ordre?
Peter Kahn
9
L'ordre des modules n'est PAS l'ordre dans lequel ils apparaîtront dans le réacteur. La seule façon d'affecter l'ordre est de créer des dépendances entre les modules, c'est-à-dire en utilisant la balise <dependency>. Vous ne pouvez pas vous fier à l'ordre de déclaration pour cela.
SaM du
7
@SaM En fait, à partir de Maven 3.0.5, le Reactor prendra en compte l'ordre des 'modules' , bien que l'ordre dicté par les dépendances soit d'une priorité plus élevée.
hellodanylo
Cela cassera certains autres plug-ins qui ne parviendront pas à détecter le module dans le profil même si le profil est activé
tribbloid
143

Avec Maven 3.2.1, vous pouvez désormais utiliser -pl !<module_name>,!<module_name>pour exclure certains modules de la construction du réacteur.

Voir cette demande de fonctionnalité: https://issues.apache.org/jira/browse/MNG-5230

Yogesh_D
la source
Est-il sûr de passer de 3.0.4 à 3.2.1 ou y a-t-il des changements plus importants?
jan
J'étais passé de 3.1 à 3.2.1 sans aucun problème. Mais pour être honnête, vous devrez faire un build pour le comprendre.
Yogesh_D
30
N'oubliez pas d'échapper le point d'exclamation sur la ligne de commande du shell. Il a une signification très particulière, voir par exemple unix.stackexchange.com/questions/3747/…
Pavel
5
Malheureusement, il existe actuellement un problème ouvert dans le plugin Jenkins maven-project qui ne prend pas en charge l'exclusion du module réacteur: issues.jenkins-ci.org/browse/JENKINS-26472
Nick Vanderhoven
@Pavel: ou utilisez simplement à la -place de !, ie-pl -<module_name>
msa
45

Les projets à construire peuvent également être spécifiés sur la ligne de commande mvn. Cela éliminerait le besoin d'un pom séparé, mais à la place, vous devrez changer la configuration du CI à chaque fois qu'il y a un nouveau module.

-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.

Peut-être qu'une combinaison de cet indicateur et / --also-make-dependentsou --also-makeréduirait à nouveau ce fardeau de maintenance.

-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
la source
Cela pose les mêmes problèmes que l'utilisation de deux poms séparés. Nous devons aux endroits où nous définissons les modules. C'est ce que j'essaye d'éviter.
kayahr
C'est une bonne solution. Pas besoin de mettre à jour le pom. mvn clean install -pl mysubproject
nicolas-f
22

Je suppose que vous voulez que la version par défaut construise toujours tout, quelle que soit la vitesse, afin que les nouveaux développeurs puissent démarrer rapidement sans avoir à en comprendre beaucoup sur le POM. Vous pouvez utiliser des profils comme celui-ci:

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

Le problème avec ceci est que si un développeur spécifie un autre profil sur la ligne de commande, alors le expensive-modules-to-buildn'est pas inclus (sauf si le développeur le spécifie également). Cela complique la mémorisation des profils à inclure.

Voici un moyen de contourner cela. Les deux profils sont toujours inclus, car le fichier pom.xml existe toujours. Donc, pour exclure les modules coûteux, vous pouvez utiliser -P!full-buildsur la ligne de commande.

<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
la source
Bonne réponse. Mais avez-vous vraiment besoin de deux profils dans le 2ème exemple de code? Le profil unique du premier exemple de code avec un élément d'activation modifié ne fonctionnerait-il pas?
Arend v. Reinersdorff
@ Arendv.Reinersdorff oui, mais cette réponse fonctionne également avec d'autres profils de la construction que vous voudrez peut-être inclure par défaut. Dans l'ensemble, je pense que l'autre réponse -pl !<module_name>,!<module_name>est meilleure que cette ancienne
artbristol
1
Bonne astuce d'activation. Cela m'a résolu les problèmes avec <activeByDefault> qui n'est pas toujours actif!
Gab
7

Une autre idée: les modules Reactor peuvent être imbriqués, il devrait donc être possible de regrouper vos modules à construction rapide et lente dans des poms séparés, puis d'ajouter un autre pom d'agrégateur contenant ces deux sous forme de modules. Votre serveur CI pourrait alors uniquement référencer le pom contenant les modules de construction rapide.

<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
la source
1

Vous pourriez utiliser des profils maven . Dans notre environnement de construction, nous avons créé un profilquick qui désactive de nombreux plugins et l'exécution de tests.

Ceci est fait par

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

Et puis nous invoquons maven de la manière suivante

mvn groupId:artifactId:goal -P quick

Vous pourriez peut-être désactiver la compilation et d'autres plugins standard dans le pom de votre module pour l'accélérer.

Nr9
la source
2
Oui, pour désactiver les tests, cela fonctionne très bien. Mais comment puis-je utiliser des profils pour exclure des modules SANS avoir deux listes de modules séparées dans le pom? Pour autant que je sache, je dois mettre la liste complète des modules dans une section de profil et la liste des modules à construction rapide dans une autre section de profil. Cela pose donc le même problème que l'utilisation de deux poms séparés: j'ai deux listes de modules à maintenir.
kayahr le
Exclure le module n'est pas vraiment la façon de faire les choses dans maven et mon expérience avec maven est qu'il vaut mieux s'en tenir à la façon dont les choses sont faites, sinon vous rencontrez tellement de problèmes ... Donc vraiment ce que je propose n'est pas de retirez le module, mais pour que ce module prenne moins de temps.
Nr9
Le problème avec les maven est que «la façon dont les choses sont faites» n'est souvent pas en accord avec «la façon dont les choses sont faites dans le monde réel», ce qui rend l'expérience des mavens pauvre et douloureuse. Les développeurs feraient bien de suivre une formation UX.
Ed Randall
0

Pas exactement la réponse que ces gens demandaient. Ma situation était que je voulais déployer uniquement le pom parent. J'utilise le spring-boot-thin-layoutdans un module enfant. Cela nécessite que le module parent soit déployé dans un artificiel. J'ai ajouté ce qui suit dans mon projet. Il permet de sauter installet / ou de deployphase.

Dans mon pom parent:

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

Et le (s) pom (s) de mon enfant ou tout module que vous ne voulez pas déployer avec le parent:

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

Donc, effectivement, lorsque je lance mvn deploysur le pom parent, il compilera tous les modules, ne lancera l'installation sur rien, puis à la fin, déploiera tout module n'ayant pas <maven.deploy.skip>${disable.deploy}</maven.deploy.skip>dans ses propriétés. Donc, dans mon cas, ne déployer que le parent.

ranma2913
la source