Bagaimana cara mengecualikan modul dari reaktor Maven membangun?

98

Kami memiliki proyek Maven 2 dengan banyak modul di dalamnya. Contoh:

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

Misalkan pembuatan modul "data" memakan waktu dan kami ingin mengecualikannya saat proyek dibuat oleh server CI. Saat ini kami menggunakan dua file pom.xml untuk mencapai ini. Satu memiliki semua modul di dalamnya dan yang lainnya memiliki semua modul kecuali yang dapat ditinggalkan untuk CI. Namun hal tersebut cukup mengganggu karena terkadang kita lupa memasukkan modul baru ke kedua file tersebut.

Apakah ada solusi yang tidak memerlukan dua daftar modul terpisah?

kayahr
sumber

Jawaban:

73

Mungkin yang termudah untuk digunakan profilesseperti ini:

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

Anda kemudian harus mencari cara untuk mengaktifkan profil

SaM
sumber
Apa yang akan Anda lakukan jika Anda membutuhkan data terjadi sebelum kejadian umum? Dalam hal ini modul profil akan ditempatkan setelah modul default dalam urutan reaktor. Apakah ada pola untuk memaksa ketertiban?
Peter Kahn
9
Urutan modul BUKAN urutan kemunculannya di reaktor. Satu-satunya cara untuk memengaruhi urutan, adalah membuat dependensi antar modul, yaitu menggunakan tag <dependency>. Anda tidak dapat mengandalkan perintah deklarasi untuk ini.
SaM
7
@SaM Sebenarnya, pada Maven 3.0.5, Reaktor akan memperhitungkan urutan dalam 'modul' , meskipun urutan yang ditentukan oleh dependensi memiliki prioritas yang lebih tinggi.
hellodanylo
Ini akan merusak beberapa plug-in lain yang gagal mendeteksi modul di profil bahkan profil diaktifkan
tribbloid
143

Dengan Maven 3.2.1, Anda sekarang dapat menggunakan -pl !<module_name>,!<module_name>untuk mengecualikan modul tertentu dari build reaktor.

Lihat permintaan fitur ini: https://issues.apache.org/jira/browse/MNG-5230

Yogesh_D
sumber
Apakah aman untuk beralih dari 3.0.4 ke 3.2.1 atau adakah perubahan yang lebih besar?
Januari
Saya telah pindah dari 3.1 ke 3.2.1 tanpa masalah. Tapi jujur ​​saja, Anda harus melakukan build untuk mengetahuinya.
Yogesh_D
30
Jangan lupa untuk menghindari tanda seru di baris perintah shell. Ini memiliki arti yang sangat khusus, lihat misalnya unix.stackexchange.com/questions/3747/…
Pavel
5
Sayangnya, saat ini ada masalah terbuka di plugin proyek maven Jenkins yang tidak mendukung pengecualian modul reaktor: issues.jenkins-ci.org/browse/JENKINS-26472
Nick Vanderhoven
@Pavel: atau cukup gunakan -sebagai gantinya !, yaitu-pl -<module_name>
msa
45

Proyek yang akan dibangun juga dapat ditentukan di baris perintah mvn. Ini akan menghilangkan kebutuhan akan pom terpisah, tetapi sebaliknya Anda harus mengubah konfigurasi CI setiap kali ada modul baru.

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

Mungkin kombinasi dari bendera ini dan --also-make-dependentsatau --also-makeakan mengurangi beban pemeliharaan ini lagi.

-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
sumber
Ini memiliki masalah yang sama seperti menggunakan dua pom terpisah. Kita harus ke tempat di mana kita mendefinisikan modul. Itulah yang saya coba hindari.
kayahr
Ini adalah solusi yang bagus. Tidak perlu memperbarui pom. mvn clean install -pl mysubproject
nicolas-f
22

Saya berasumsi Anda ingin build default selalu membangun semuanya, berapa pun kecepatannya, sehingga developer baru dapat memulai dengan cepat tanpa harus banyak memahami tentang POM. Anda dapat menggunakan profil seperti ini:

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

Masalahnya adalah jika pengembang menentukan profil lain pada baris perintah, maka profil expensive-modules-to-buildtersebut tidak disertakan (kecuali pengembang juga menentukannya). Ini membuatnya rumit untuk mengingat profil mana yang perlu disertakan.

Berikut adalah cara hacky untuk itu. Kedua profil selalu disertakan, karena file pom.xml selalu ada. Jadi untuk mengecualikan modul mahal, Anda dapat menggunakan -P!full-buildbaris perintah.

<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
sumber
Jawaban bagus. Tetapi apakah Anda benar-benar membutuhkan dua profil dalam contoh kode ke-2? Bukankah satu profil dari contoh kode pertama dengan elemen aktivasi yang diubah akan berfungsi?
Arend v. Reinersdorff
@ Arendv.Reinersdorff ya, namun jawaban ini juga berfungsi dengan profil lain dalam build yang mungkin ingin Anda sertakan secara default. Secara keseluruhan, saya pikir jawaban lain dengan -pl !<module_name>,!<module_name>lebih baik daripada yang lama ini
artbristol
1
Trik aktivasi yang bagus. Ini memecahkan masalah saya dengan <activeByDefault> yang tidak selalu aktif!
Gab
7

Ide lain: Modul reaktor dapat disarangkan, jadi seharusnya mungkin untuk mengelompokkan modul cepat dan lambat Anda ke dalam pom terpisah dan kemudian menambahkan pom agregator lain yang berisi keduanya sebagai modul. CI Server Anda kemudian hanya dapat mereferensikan pom yang berisi modul pembangunan cepat.

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

Anda bisa menggunakan profil maven . Di lingkungan build kami, kami membuat profil quickyang menonaktifkan banyak plugin dan eksekusi uji.

Ini dilakukan oleh

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

Dan kemudian kita memanggil maven dengan cara berikut

mvn groupId:artifactId:goal -P quick

Anda mungkin dapat menonaktifkan kompilasi dan plugin standar lainnya di pom modul Anda untuk mempercepatnya.

Nr9
sumber
2
Ya, untuk menonaktifkan tes ini berfungsi dengan baik. Tetapi bagaimana saya dapat menggunakan profil untuk mengecualikan modul TANPA memiliki dua daftar modul terpisah di pom? Sejauh yang saya tahu, saya perlu memasukkan daftar modul lengkap ke dalam satu bagian profil dan daftar modul pembuatan cepat ke dalam bagian profil lainnya. Jadi ini memiliki masalah yang sama seperti menggunakan dua pom terpisah: Saya memiliki dua daftar modul untuk dipelihara.
kayahr
Mengecualikan modul sebenarnya bukanlah cara untuk melakukan sesuatu di maven dan pengalaman saya dengan maven adalah lebih baik tetap berpegang pada cara melakukan sesuatu, jika tidak Anda akan mengalami begitu banyak masalah ... Jadi sebenarnya yang saya usulkan bukanlah lepaskan modul, tetapi untuk membuat modul ini lebih menghemat waktu.
Nr9
Masalah dengan maven adalah bahwa 'cara melakukan sesuatu' seringkali tidak sejalan dengan 'cara melakukan sesuatu di dunia nyata', membuat pengalaman pakar tersebut menjadi miskin dan menyakitkan. Pengembang sebaiknya mengambil dosis pelatihan UX.
Ed Randall
0

Bukan jawaban yang diminta orang-orang ini. Situasi saya adalah saya hanya ingin menerapkan pom induk. Saya menggunakan spring-boot-thin-layoutmodul dalam anak. Ini membutuhkan modul induk untuk diterapkan ke artifactory. Saya menambahkan yang berikut ini ke dalam proyek saya. Ini memungkinkan melewatkan installdan / atau deployfase.

Di pom orang tua saya:

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

Dan di pom anak saya atau modul apa pun yang tidak ingin Anda gunakan dengan orang tua:

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

Jadi secara efektif ketika saya berjalan mvn deploydi pom induk, itu akan mengkompilasi semua modul, tidak menjalankan instalasi pada apa pun, dan kemudian pada akhirnya menerapkan modul apa pun yang tidak ada <maven.deploy.skip>${disable.deploy}</maven.deploy.skip>di propertinya. Jadi dalam kasus saya hanya menerapkan orang tua.

ranma2913
sumber