Jak wykluczyć moduł z kompilacji reaktora Maven?

98

Mamy projekt Maven 2 z wieloma modułami. Przykład:

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

Załóżmy, że tworzenie modułu danych jest czasochłonne i chcemy go wykluczyć, gdy projekt jest budowany przez serwer CI. Obecnie używamy do tego dwóch plików pom.xml. Jeden zawiera wszystkie moduły, a drugi ma wszystkie moduły oprócz tych, które można pominąć dla CI. Ale to dość denerwujące, ponieważ czasami zapominamy o umieszczeniu nowego modułu w obu plikach.

Czy istnieje rozwiązanie, które nie wymaga dwóch oddzielnych list modułów?

kayahr
źródło

Odpowiedzi:

73

Najłatwiej byłoby użyć w profilesten sposób:

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

Następnie sprawdź, jak możesz aktywować profile

SaM
źródło
Co byś zrobił, gdybyś potrzebował danych przed wspólnym? W takim przypadku moduły profilu zostaną umieszczone za modułami domyślnymi w kolejności reaktora. Czy istnieje wzór wymuszania porządku?
Peter Kahn
9
Kolejność modułów NIE jest kolejnością, w jakiej pojawią się w reaktorze. Jedynym sposobem, aby wpłynąć na kolejność, jest stworzenie zależności między modułami, czyli użycie tagu <dependency>. Nie możesz w tym celu polegać na kolejności deklaracji.
sobota,
7
@SaM Właściwie od Maven 3.0.5 Reactor weźmie pod uwagę kolejność w 'modułach' , chociaż kolejność podyktowana zależnościami ma wyższy priorytet.
hellodanylo
Spowoduje to zerwanie innych wtyczek, które nie wykryją modułu w profilu, nawet jeśli profil jest włączony
tribbloid
143

Dzięki Maven 3.2.1 możesz teraz użyć, -pl !<module_name>,!<module_name>aby wykluczyć niektóre moduły z kompilacji reaktora.

Zobacz tę prośbę o funkcję: https://issues.apache.org/jira/browse/MNG-5230

Yogesh_D
źródło
Czy przejście z 3.0.4 na 3.2.1 jest bezpieczne, czy też są większe zmiany?
sty
Przeszedłem z 3.1 do 3.2.1 bez żadnych problemów. Ale szczerze mówiąc, musiałbyś zrobić kompilację, aby to rozgryźć.
Yogesh_D
30
Nie zapomnij pominąć znaku wykrzyknika w linii poleceń powłoki. Ma bardzo szczególne znaczenie, patrz np. Unix.stackexchange.com/questions/3747/…
Pavel
5
Niestety, obecnie we wtyczce Jenkins maven-project jest otwarty problem, który nie obsługuje wykluczania modułów reaktora: Issues.jenkins-ci.org/browse/JENKINS-26472
Nick Vanderhoven
@Pavel: lub po prostu użyj -zamiast !, np.-pl -<module_name>
msa
45

Projekty do zbudowania można również określić w wierszu poleceń mvn. To wyeliminowałoby potrzebę oddzielnego pom, ale zamiast tego musiałbyś zmieniać konfigurację CI za każdym razem, gdy pojawia się nowy moduł.

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

Może połączenie tej flagi i --also-make-dependentslub --also-makezmniejszyłoby to obciążenie związane z utrzymaniem.

-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
źródło
Ma to takie same problemy, jak użycie dwóch oddzielnych pompek. Mamy miejsca, w których definiujemy moduły. Tego właśnie staram się uniknąć.
kayahr
To jest dobre rozwiązanie. Nie musisz aktualizować pliku pom. mvn clean install -pl mysubproject
nicolas-f
22

Zakładam, że chcesz, aby domyślna kompilacja zawsze tworzyła wszystko, niezależnie od szybkości, aby nowi programiści mogli szybko rozpocząć pracę bez konieczności rozumienia POM. Możesz używać takich profili:

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

Problem polega na tym, że jeśli programista określi inny profil w wierszu poleceń, plik expensive-modules-to-build to nie jest on uwzględniany (chyba że programista również go określi). To sprawia, że ​​zapamiętanie, które profile należy uwzględnić, jest skomplikowane.

Oto hacky sposób obejścia tego. Oba profile są zawsze uwzględniane, ponieważ plik pom.xml zawsze istnieje. Aby wykluczyć drogie moduły, możesz użyć -P!full-buildw wierszu poleceń.

<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
źródło
Niezła odpowiedź. Ale czy naprawdę potrzebujesz dwóch profili w drugim przykładzie kodu? Czy pojedynczy profil z pierwszego przykładu kodu ze zmienionym elementem aktywacyjnym nie zadziała?
Arend przeciwko Reinersdorff,
@ Arendv.Reinersdorff tak, ale ta odpowiedź działa również z innymi profilami w kompilacji, które możesz chcieć uwzględnić domyślnie. Ogólnie rzecz biorąc, myślę, że druga odpowiedź -pl !<module_name>,!<module_name>jest lepsza niż ta stara
artbristol
1
Dobra sztuczka aktywacyjna. Rozwiązało mi to problemy z <activeByDefault>, które nie zawsze jest aktywne!
Gab
7

Inny pomysł: moduły Reactor można zagnieżdżać, więc powinno być możliwe zgrupowanie szybko i wolno budujących się modułów w oddzielne poms, a następnie dodanie kolejnego agregatora pom zawierającego te dwa jako moduły. Twój serwer CI mógłby wtedy odnosić się tylko do pom zawierającego moduły szybkiego budowania.

<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
źródło
1

Możesz użyć profili maven . W naszym środowisku kompilacji stworzyliśmy profil, quickktóry wyłącza wiele wtyczek i wykonywanie testów.

Odbywa się to przez

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

A potem wywołujemy maven w następujący sposób

mvn groupId:artifactId:goal -P quick

Możesz wyłączyć kompilację i inne standardowe wtyczki w pomie swojego modułu, aby przyspieszyć ten proces.

Nr9
źródło
2
Tak, w przypadku wyłączania testów działa to świetnie. Ale jak mogę używać profili do wykluczania modułów BEZ dwóch oddzielnych list modułów w pom? O ile wiem, muszę umieścić pełną listę modułów w jednej sekcji profilu, a listę modułów szybkiego budowania w drugiej sekcji profilu. Więc to ma ten sam problem, co używanie dwóch oddzielnych pomów: mam dwie listy modułów do utrzymania.
kayahr
Wykluczanie modułu nie jest tak naprawdę sposobem na robienie rzeczy w maven, a moje doświadczenie z maven jest takie, że lepiej trzymać się sposobu, w jaki się robi, inaczej napotkasz tak wiele problemów ... Więc tak naprawdę proponuję, aby tego nie robić wyjmij moduł, ale aby ten moduł był mniej czasochłonny.
Nr9
Problem z maven polega na tym, że „sposób załatwiania rzeczy” często nie jest zgodny ze „sposobem, w jaki robi się rzeczy w prawdziwym świecie”, co sprawia, że ​​maven jest biedny i bolesny. Deweloperzy dobrze by zrobili, gdyby wzięli dawkę szkolenia UX.
Ed Randall,
0

Nie do końca odpowiedź, o którą prosili ci ludzie. Moja sytuacja była taka, że ​​chciałem wdrożyć tylko macierzysty pom. Używam spring-boot-thin-layoutw module podrzędnym. Wymaga to wdrożenia modułu nadrzędnego w artefaktorze. Dodałem do mojego projektu: Umożliwia pominięcie installi / lubdeploy fazę.

W moim pompie rodzica:

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

A w moich podrzędnych pom (ach) lub dowolnym module, którego nie chcesz wdrożyć z rodzicem:

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

Tak więc efektywnie, gdy uruchomię mvn deployna pom-nadrzędnym pom, skompiluje on wszystkie moduły, nie uruchomi instalacji na niczym, a na koniec wdroży każdy moduł, który nie ma <maven.deploy.skip>${disable.deploy}</maven.deploy.skip>w swoich właściwościach. Więc w moim przypadku wdrażam tylko rodzica.

ranma2913
źródło