Wie kann man ein Modul von einem Maven-Reaktor ausschließen?

98

Wir haben ein Maven 2-Projekt mit vielen Modulen. Beispiel:

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

Angenommen, die Erstellung des "Daten" -Moduls ist zeitaufwändig und wir möchten es ausschließen, wenn das Projekt von einem CI-Server erstellt wird. Derzeit verwenden wir zwei pom.xml-Dateien, um dies zu erreichen. Eines enthält alle Module und das andere enthält alle Module mit Ausnahme derjenigen, die für CI weggelassen werden können. Aber das ist ziemlich ärgerlich, weil wir manchmal vergessen, ein neues Modul in beide Dateien zu setzen.

Gibt es eine Lösung, die keine zwei separaten Modullisten benötigt?

Kayahr
quelle

Antworten:

73

Am einfachsten ist es, Folgendes zu verwenden profiles:

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

Sie sollten dann prüfen, wie Sie Profile aktivieren können

Sam
quelle
Was würden Sie tun, wenn Sie Daten benötigen, die vor dem Common auftreten? In diesem Fall werden die Profilmodule in der Reihenfolge der Reaktoren nach den Standardmodulen platziert. Gibt es ein Muster, um Ordnung zu erzwingen?
Peter Kahn
9
Die Reihenfolge der Module ist NICHT die Reihenfolge, in der sie im Reaktor erscheinen. Die einzige Möglichkeit, die Reihenfolge zu beeinflussen, besteht darin, Abhängigkeiten zwischen Modulen zu erstellen, dh das Tag <dependency> zu verwenden. Sie können sich hierfür nicht auf die Deklarationsreihenfolge verlassen.
SaM
7
@SaM Ab Maven 3.0.5 berücksichtigt der Reaktor die Reihenfolge in 'Modulen' , obwohl die durch Abhängigkeiten vorgegebene Reihenfolge eine höhere Priorität hat.
hellodanylo
Dies wird einige andere Plug-Ins
beschädigen
143

Mit Maven 3.2.1 können Sie jetzt -pl !<module_name>,!<module_name>bestimmte Module vom Reaktoraufbau ausschließen.

Siehe diese Funktionsanforderung: https://issues.apache.org/jira/browse/MNG-5230

Yogesh_D
quelle
Ist es sicher, von 3.0.4 auf 3.2.1 zu wechseln, oder gibt es größere Änderungen?
Januar
Ich war ohne Probleme von 3.1 auf 3.2.1 gewechselt. Aber um ehrlich zu sein, müsste man einen Build machen, um es herauszufinden.
Yogesh_D
30
Vergessen Sie nicht, das Ausrufezeichen in der Shell-Befehlszeile zu entfernen. Es hat eine ganz besondere Bedeutung, siehe zB unix.stackexchange.com/questions/3747/…
Pavel
5
Leider gibt es derzeit ein offenes Problem im Jenkins Maven-Projekt-Plugin, das den Ausschluss von Reaktormodulen
Nick Vanderhoven
@Pavel: oder verwenden Sie einfach -anstelle von !, dh-pl -<module_name>
msa
45

Die zu erstellenden Projekte können auch in der Befehlszeile von mvn angegeben werden. Dies würde die Notwendigkeit eines separaten POMs beseitigen, aber stattdessen müssten Sie die CI-Konfiguration jedes Mal ändern, wenn ein neues Modul vorhanden ist.

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

Vielleicht eine Kombination dieser Flagge und / --also-make-dependentsoder --also-makewürde diesen Wartungsaufwand wieder reduzieren.

-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
quelle
Dies hat die gleichen Probleme wie die Verwendung von zwei separaten Poms. Wir müssen Orte finden, an denen wir die Module definieren. Das versuche ich zu vermeiden.
Kayahr
Dies ist eine gute Lösung. Sie müssen den Pom nicht aktualisieren. mvn clean install -pl mysubproject
Nicole-F
22

Ich gehe davon aus, dass der Standard-Build unabhängig von der Geschwindigkeit immer alles erstellen soll, damit neue Entwickler schnell loslegen können, ohne viel über das POM verstehen zu müssen. Sie können folgende Profile verwenden:

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

Das Problem dabei ist, dass, wenn ein Entwickler ein anderes Profil in der Befehlszeile angibt, das expensive-modules-to-buildnicht enthalten ist (es sei denn, der Entwickler gibt es auch an). Dies macht es kompliziert, sich zu merken, welche Profile enthalten sein müssen.

Hier ist ein hackiger Weg, um das zu umgehen. Beide Profile sind immer enthalten, da die Datei pom.xml immer vorhanden ist. Um die teuren Module auszuschließen, können Sie sie -P!full-buildin der Befehlszeile verwenden.

<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
quelle
Gute Antwort. Aber brauchen Sie wirklich zwei Profile im 2. Codebeispiel? Würde das einzelne Profil aus dem 1. Codebeispiel mit einem geänderten Aktivierungselement nicht funktionieren?
Arend v. Reinersdorff
@ Arendv.Reinersdorff ja, das würde es, aber diese Antwort funktioniert auch mit anderen Profilen im Build, die Sie möglicherweise standardmäßig einschließen möchten. Insgesamt denke ich jedoch, dass die andere Antwort mit -pl !<module_name>,!<module_name>besser ist als diese alte
Artbristol
1
Guter Aktivierungstrick. Es hat mich die Probleme mit <activeByDefault> gelöst, die nicht immer aktiv sind!
Gab
7

Eine andere Idee: Reaktormodule können verschachtelt werden, daher sollte es möglich sein, Ihre schnell und langsam aufbauenden Module in separate Poms zu gruppieren und dann einen weiteren Aggregator-Pom hinzuzufügen, der diese beiden als Module enthält. Ihr CI-Server konnte dann nur auf den POM verweisen, der die Fast-Building-Module enthält.

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

Sie könnten Maven- Profile verwenden . In unserer Build-Umgebung haben wir ein Profil erstellt quick, das viele Plugins und die Testausführung deaktiviert.

Dies geschieht durch

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

Und dann rufen wir maven folgendermaßen auf

mvn groupId:artifactId:goal -P quick

Sie könnten möglicherweise die Kompilierung und andere Standard-Plugins im POM Ihres Moduls deaktivieren, um es zu beschleunigen.

Nr9
quelle
2
Ja, zum Deaktivieren von Tests funktioniert dies hervorragend. Aber wie kann ich Profile verwenden, um Module auszuschließen, ohne zwei separate Modullisten im POM zu haben? Soweit ich weiß, muss ich die vollständige Modulliste in einen Profilabschnitt und die schnell erstellte Modulliste in einen anderen Profilabschnitt einfügen. Das hat also das gleiche Problem wie die Verwendung von zwei separaten Poms: Ich muss zwei Modullisten pflegen.
Kayahr
Das Ausschließen von Modulen ist nicht wirklich die Art und Weise, Dinge in Maven zu tun, und meine Erfahrung mit Maven ist, dass es besser ist, sich an die Art und Weise zu halten, wie Dinge gemacht werden, sonst haben Sie so viele Probleme ... Also wirklich, was ich vorschlage, ist es nicht Entfernen Sie das Modul, um dieses Modul weniger zeitaufwändig zu machen.
Nr9
Das Problem mit Maven ist, dass „die Art und Weise, wie Dinge getan werden“ häufig nicht mit „der Art und Weise, wie Dinge in der realen Welt getan werden“ übereinstimmt, was die Erfahrung des Maven arm und schmerzhaft macht. Die Entwickler würden gut daran tun, eine Dosis UX-Training zu nehmen.
Ed Randall
0

Nicht genau die Antwort, nach der diese Leute fragten. Meine Situation war, dass ich nur den übergeordneten POM bereitstellen wollte. Ich benutze das spring-boot-thin-layoutin einem untergeordneten Modul. Dies erfordert, dass das übergeordnete Modul in Artifactory bereitgestellt wird. Ich habe folgendes in mein Projekt aufgenommen. Es ermöglicht das Überspringen installund / oder die deployPhase.

In meinem Eltern 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>

Und die in meinem Kind Pom (s) oder ein Modul, das Sie nicht mit Eltern bereitstellen möchten:

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

Wenn ich also mvn deployauf dem übergeordneten POM ausgeführt werde, werden alle Module kompiliert, keine Installation auf irgendetwas ausgeführt und am Ende alle Module bereitgestellt <maven.deploy.skip>${disable.deploy}</maven.deploy.skip>, deren Eigenschaften nicht vorhanden sind. In meinem Fall also nur das übergeordnete Element bereitstellen.

ranma2913
quelle