Bagaimana Anda menangani snapshot maven-3 dengan cap waktu secara efisien?


87

Sekarang setelah maven-3 memberikan dukungan untuk <uniqueVersion> false </uniqueVersion> untuk artefak snapshot, tampaknya Anda benar-benar perlu menggunakan SNAPSHOTS yang diberi stempel waktu. Terutama m2eclipse, yang menggunakan maven 3 secara internal tampaknya terpengaruh dengannya, update-snapshot tidak berfungsi jika SNAPSHOTS tidak unik.

Tampaknya praktik terbaik sebelum menyetel semua snapshot ke uniqueVersion = false

Sekarang, tampaknya tidak ada masalah besar untuk beralih ke versi timestamped, bagaimanapun juga mereka dikelola oleh repositori nexus pusat, yang mampu menghapus snapshot lama di intervalls biasa.

Masalahnya adalah workstation pengembang lokal. Repositori lokal mereka dengan cepat tumbuh sangat besar dengan snapshot unik.

Bagaimana cara mengatasi masalah ini?

Sekarang saya melihat kemungkinan solusi berikut:

  • Minta pengembang untuk membersihkan repositori secara berkala (yang menyebabkan banyak fustration, karena butuh waktu lama untuk menghapus dan bahkan lebih lama untuk mengunduh semua yang diperlukan)
  • Siapkan beberapa skrip yang menghapus semua direktori SNAPSHOT dari repositori lokal dan minta pengembang untuk menjalankan skrip itu dari waktu ke waktu (lebih baik dari yang pertama, tetapi masih membutuhkan waktu untuk menjalankan dan mengunduh snapshot saat ini)
  • gunakan dependensi: plugin purge-local-repository (Apakah mengalami masalah saat dijalankan dari eclipse, karena file yang terbuka, perlu dijalankan dari setiap proyek)
  • mengatur nexus di setiap workstation dan mengatur pekerjaan untuk membersihkan snapshot lama (hasil terbaik, tetapi saya tidak ingin mempertahankan 50+ server nexus, ditambah memori selalu ketat pada workstation pengembang)
  • berhenti menggunakan SNAPSHOTS sama sekali

Apa cara terbaik untuk mencegah repositori lokal Anda mengisi ruang hard drive Anda?

Memperbarui:

Untuk memverifikasi perilaku dan untuk memberikan info lebih lanjut, saya menyiapkan server nexus kecil, membangun dua proyek (a dan b) dan mencoba:

Sebuah:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>de.glauche</groupId>
  <artifactId>a</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <distributionManagement>
    <snapshotRepository>
        <id>nexus</id>
        <name>nexus</name>
        <url>http://server:8081/nexus/content/repositories/snapshots</url>
    </snapshotRepository>
  </distributionManagement>

</project>

b:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>de.glauche</groupId>
  <artifactId>b</artifactId>
  <version>0.0.1-SNAPSHOT</version>
    <distributionManagement>
    <snapshotRepository>
        <id>nexus</id>
        <name>nexus</name>
        <url>http://server:8081/nexus/content/repositories/snapshots/</url>
    </snapshotRepository>
  </distributionManagement>
 <repositories>
    <repository>
        <id>nexus</id>
        <name>nexus</name>
        <snapshots>
            <enabled>true</enabled>
        </snapshots>
        <url>http://server:8081/nexus/content/repositories/snapshots/</url>
    </repository>
 </repositories>
  <dependencies>
    <dependency>
        <groupId>de.glauche</groupId>
        <artifactId>a</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
  </dependencies>
</project>

Sekarang, ketika saya menggunakan maven dan menjalankan "deploy" pada "a", saya akan melakukannya

a-0.0.1-SNAPSHOT.jar
a-0.0.1-20101204.150527-6.jar
a-0.0.1-SNAPSHOT.pom
a-0.0.1-20101204.150527-6.pom

di repositori lokal. Dengan versi stempel waktu baru setiap kali saya menjalankan target penerapan. Hal yang sama terjadi ketika saya mencoba memperbarui Snapshot dari server nexus (tutup Project "a", hapus dari repositori lokal, build "b")

Dalam lingkungan di mana banyak snapshot dibangun (pikirkan server hudson ...), reposioty lokal terisi dengan versi lama dengan cepat

Perbarui 2:

Untuk menguji bagaimana dan mengapa ini gagal, saya melakukan beberapa tes lagi. Setiap pengujian dijalankan terhadap semua yang bersih (de / glauche dihapus dari mesin dan nexus)

  • mvn menyebarkan dengan maven 2.2.1:

repositori lokal pada mesin A memang berisi snapshot.jar + snapshot-timestamp.jar

TAPI: hanya satu botol dengan stempel waktu di nexus, metadata terbaca:

<?xml version="1.0" encoding="UTF-8"?>
<metadata>
  <groupId>de.glauche</groupId>
  <artifactId>a</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <versioning>
    <snapshot>
      <timestamp>20101206.200039</timestamp>

      <buildNumber>1</buildNumber>
    </snapshot>
    <lastUpdated>20101206200039</lastUpdated>
  </versioning>
</metadata>
  • jalankan dependensi pembaruan (pada mesin B) di m2eclipse (m3 final tertanam) -> repositori lokal memiliki snapshot.jar + snapshot-timestamp.jar :(
  • menjalankan tujuan paket dengan maven 2.2.1 eksternal -> repositori lokal memiliki snapshot.jar + snapshot-timestamp.jar :(

Ok, selanjutnya coba dengan maven 3.0.1 (setelah menghapus semua jejak proyek a)

  • repositori lokal pada mesin A terlihat lebih baik, hanya satu botol non-timestamped

  • hanya satu botol dengan stempel waktu di nexus, metadata berbunyi:

    de.glauche a 0.0.1-SNAPSHOT

    <snapshot>
      <timestamp>20101206.201808</timestamp>
      <buildNumber>3</buildNumber>
    </snapshot>
    <lastUpdated>20101206201808</lastUpdated>
    <snapshotVersions>
      <snapshotVersion>
        <extension>jar</extension>
        <value>0.0.1-20101206.201808-3</value>
        <updated>20101206201808</updated>
      </snapshotVersion>
      <snapshotVersion>
        <extension>pom</extension>
        <value>0.0.1-20101206.201808-3</value>
        <updated>20101206201808</updated>
      </snapshotVersion>
    </snapshotVersions>
    

  • jalankan dependensi pembaruan (pada mesin B) di m2eclipse (m3 final tertanam) -> repositori lokal memiliki snapshot.jar + snapshot-timestamp.jar :(

  • menjalankan tujuan paket dengan maven 2.2.1 eksternal -> repositori lokal memiliki snapshot.jar + snapshot-timestamp.jar :(

Jadi, untuk rekap: Tujuan "menyebarkan" di maven3 bekerja lebih baik daripada di 2.2.1, repositori lokal pada mesin pembuat terlihat baik-baik saja. Namun, receiver selalu mendapatkan banyak versi dengan waktu ...

Apa yang saya lakukan salah?

Perbarui 3

Saya juga menguji berbagai konfigurasi lain, pertama-tama ganti nexus dengan artifactory -> perilaku yang sama. Kemudian gunakan klien linux maven 3 untuk mengunduh snapshot dari manajer repositori -> repositori lokal masih memiliki snapshot yang diberi stempel waktu :(


Pertanyaan terkait, tentang hanya bagian .m2 \ repositori lokal, difokuskan pada repositori lokal pada server build (Jenkins): stackoverflow.com/q/9729076/223837 .
MarnixKlooster ReinstateMonica

- Berikut ini adalah link ke Apcahe Maven comptability Catatan bekerja cwiki.apache.org/confluence/display/MAVEN/...
aka_sh

Jawaban:


36

The <uniqueVersion>konfigurasi diterapkan pada artefak yang dikerahkan (via menyebarkan mvn) ke Maven repositori seperti Nexus.

Untuk menghapus ini dari Nexus, Anda dapat dengan mudah membuat pekerjaan otomatis untuk membersihkan repositori SNAPSHOT setiap hari. Ini dapat dikonfigurasi untuk mempertahankan sejumlah shapshots atau menyimpannya untuk jangka waktu tertentu. Ini sangat mudah dan berfungsi dengan baik.

Artefak di repositori lokal pada mesin pengembang sampai ke sana dari tujuan "instal" dan tidak menggunakan cap waktu ini ... mereka hanya terus mengganti satu-satunya versi SNAPSHOT kecuali Anda juga menambah nomor revisi (misalnya 1.0.0- SNAPSHOT hingga 1.0.1-SNAPSHOT).


1
Masalahnya adalah, bahwa tujuan "instal" tidak begitu banyak digunakan dalam lingkungan terdistribusi dengan banyak pengembang. Kami juga menggunakan server hudson yang membangun (dan menyebarkan) snapshot baru pada setiap cvs commit, yang terjadi cukup sering setiap hari. Saya tahu tentang mechainsm hapus snapshot nexus, lihat daftar solusi yang mungkin.
mglauche

Setiap mesin pengembangan harus memiliki repositori "lokal" di bawah ~/.m2/repositorydan masing pom.xml- masing harus memiliki definisi repositori yang menunjuk ke satu instance Nexus di LAN Anda. (seperti yang Anda tunjukkan). Kami memiliki pengaturan ini, bersama dengan Hudson yang membangun setiap komitmen Subversion dan bekerja dengan baik. Versi SNAPSHOT "diterapkan" ke Nexus tempat mereka mengumpulkan dan dibersihkan setiap minggu. Mesin pengembang secara otomatis mengunduh SNAPSHOT terbaru dari Nexus ke ~/.m2/repositorydan menggantikan yang diunduh sebelumnya. Pengembang tidak boleh memiliki instance Nexus sendiri.
HDave

2
Saya baru saja membaca pembaruan Anda dan memiliki satu hal lagi untuk ditambahkan: Artefak yang diberi stempel waktu seharusnya tidak pernah terlihat di dalam repositori (~ / .m2 / repositori) lokal Anda. Jika ya, ada sesuatu yang salah. Mereka seharusnya hanya terlihat di dalam Nexus. Di dalam Nexus, ya, mereka mengumpulkan dengan cepat. Ratusan MB sehari berpotensi. Pekerjaan nexus dapat dengan mudah membersihkannya setiap hari untuk menjaga jumlahnya tetap kecil.
HDave

6
Mereka pasti berakhir di repositori lokal (yang ~ / .m2 / repositori satu), mereka berakhir di sana setelah menjalankan target "deploy" dan pada mvn -U menginstal pada proyek yang bergantung (yaitu proyek B). Saya bahkan pernah mengujinya dengan maven 2.2.1 dan maven 3, keduanya memiliki perilaku yang sama.
mglauche

2
Saya rasa saya mengerti sekarang ... mereka TIDAK muncul di sana saat pengembangan melakukan "penerapan", melainkan ketika pengembang membangun proyek yang bergantung. Pada saat itu, SNAPSHOT terbaru proyek hulu diunduh dari Nexus ke ~ / .m2 / repositori dengan stempel waktu yang dibiarkan utuh sebagai bagian dari nama file. Apakah ini benar?
HDave

14

Plugin ini menghapus artefak proyek dari repositori lokal. Berguna untuk menyimpan hanya satu salinan snapshot lokal yang besar.

<plugin>         
    <groupId>org.codehaus.mojo</groupId>         
    <artifactId>build-helper-maven-plugin</artifactId>         
    <version>1.7</version>         
    <executions>           
        <execution>             
            <id>remove-old-artifacts</id>             
            <phase>package</phase>             
            <goals>               
                <goal>remove-project-artifact</goal>             
            </goals>            
            <configuration>  
                <removeAll>true</removeAll><!-- When true, remove all built artifacts including all versions. When false, remove all built artifacts of this project version -->             
            </configuration>          
        </execution>         
    </executions>       
</plugin>

7

Yah, saya tidak suka solusi yang diusulkan. Menghapus cache maven sering kali secara signifikan meningkatkan lalu lintas jaringan dan memperlambat proses build. build-helper-maven-plugin hanya membantu dengan satu artefak, saya menginginkan solusi yang dapat membersihkan semua artefak snapshot cap waktu yang sudah usang dari cache lokal dalam satu perintah sederhana. Setelah beberapa hari mencari, saya menyerah dan memutuskan untuk menulis program kecil. Program terakhir tampaknya berjalan cukup baik di lingkungan kita. Jadi saya memutuskan untuk membagikannya dengan orang lain yang mungkin membutuhkan alat tersebut. Sumber dapat ditarik dari github: https://github.com/nadestin/tools/tree/master/MavenCacheCleanup


@HDave Saya tidak berhasil memformat fragmen pom dengan benar di sini, periksa di https://github.com/nadestin/tools/wiki/m2cachecleanup-maven-plugin . Pada budak Jenkins kami, utilitas ini mengambil kembali ~ 200 MB ruang disk setiap hari.
yurinadestin

2

Sejauh bagian repositori jarak jauh ini, saya pikir jawaban sebelumnya yang membahas pembersihan SNAPSHOT pada interval reguler akan berfungsi. Tetapi tidak ada yang membahas bagian sinkronisasi stasiun kerja pengembang lokal dari pertanyaan Anda.

Kami belum mulai menggunakan Maven3, jadi kami belum melihat SNAPSHOT mulai dibangun di komputer lokal.

Tapi kami punya masalah berbeda dengan m2eclipse. Saat kami mengaktifkan "Resolusi Ruang Kerja" dan proyek ada di dalam ruang kerja kami, pembaruan sumber biasanya membuat kami tetap update. Tapi kami merasa sangat sulit mendapatkan m2eclipse untuk memperbarui dirinya sendiri dengan artefak yang baru-baru ini diterbitkan di Nexus. Kami mengalami masalah serupa dalam tim kami dan ini sangat bermasalah karena kami memiliki grafik proyek yang sangat besar ... ada banyak dependensi yang tidak akan ada di ruang kerja Anda tetapi SNAPSHOT akan sering dipublikasikan.

Saya cukup yakin ini kembali ke masalah di m2eclipse di mana ia tidak menangani SNAPSHOT persis seperti yang seharusnya. Anda dapat melihat di konsol Maven di dalam gerhana di mana m2eclipse memberi tahu Anda bahwa ia melewatkan pembaruan SNAPSHOT yang baru-baru ini diterbitkan karena versi cache-nya. Jika Anda melakukan -U dari konfigurasi proses atau dari baris perintah, Maven akan mengambil perubahan metadata. Tapi pilihan "Perbarui Snapshots ..." seharusnya memberitahu m2eclipse agar Maven mengakhiri cache ini. Tampaknya tidak diteruskan. Tampaknya ada bug di luar sana yang diajukan untuk ini jika Anda tertarik untuk memilihnya: https://issues.sonatype.org/browse/MNGECLIPSE-2608

Anda menyebutkan ini dalam komentar di suatu tempat.

Solusi terbaik untuk masalah ini tampaknya meminta pengembang membersihkan workstation lokal mereka ketika hal-hal mulai rusak dari dalam m2eclipse. Solusi serupa untuk masalah yang berbeda ... Orang lain telah melaporkan masalah dengan Maven 2.2.1 dan 3 m2eclipse dukungan, dan saya telah melihat hal yang sama.

Saya berharap jika Anda menggunakan Maven3, Anda dapat mengkonfigurasinya untuk hanya menarik SNAPSHOT terbaru, dan menyimpannya selama waktu yang dikatakan repositori (atau sampai Anda kedaluwarsa dengan tangan). Mudah-mudahan Anda tidak perlu memiliki banyak SNAPSHOT yang ada di repositori lokal Anda.

Itu kecuali jika Anda berbicara tentang server build yang secara manual melakukan file mvn installpada mereka. Sejauh bagaimana mencegah SNAPSHOT membangun di lingkungan seperti server build, kami telah menghindari peluru itu dengan meminta setiap build menggunakan ruang kerja dan repositori lokalnya sendiri (meskipun, di Maven 2.2.1, hal-hal tertentu seperti POM tampaknya selalu keluar dari ~ / .m2 / repositori) SNAPSHOT ekstra benar-benar hanya bertahan untuk satu build dan kemudian dibuang (dan diunduh lagi dari awal). Jadi kita telah melihat pendekatan ini akhirnya memakan lebih banyak ruang untuk memulai, tetapi cenderung tetap lebih stabil daripada menyelesaikan semuanya dari satu repositori. Opsi ini (di Hudson) disebut "Gunakan repositori Maven pribadi" dan berada di bawah tombol Lanjutan dari bagian Bangun pada konfigurasi proyek ketika Anda memilih untuk membangun dengan Maven. Berikut adalah deskripsi bantuan untuk opsi itu:

Biasanya, Hudson menggunakan repositori Maven lokal seperti yang ditentukan oleh Maven - proses yang tepat tampaknya tidak terdokumentasi, tetapi ~ / .m2 / repositori dan dapat diganti dengan di ~ / .m2 / settings.xml (lihat referensi untuk detail selengkapnya .) Ini biasanya berarti bahwa semua pekerjaan yang dijalankan pada node yang sama berbagi satu repositori Maven. Keuntungannya adalah Anda dapat menghemat ruang disk, tetapi sisi negatifnya adalah terkadang build tersebut dapat saling mengganggu. Misalnya, Anda mungkin akan mendapatkan build yang tidak berhasil dengan benar, hanya karena Anda memiliki semua dependensi di repositori lokal Anda, terlepas dari kenyataan bahwa tidak ada repositori di POM yang mungkin memilikinya.

Ada juga beberapa masalah yang dilaporkan terkait proses Maven bersamaan yang mencoba menggunakan repositori lokal yang sama.

Jika opsi ini dicentang, Hudson akan memberi tahu Maven untuk menggunakan $ WORKSPACE / .repository sebagai repositori Maven lokal. Ini berarti setiap pekerjaan akan mendapatkan repositori Maven yang terisolasi hanya untuk dirinya sendiri. Ini memperbaiki masalah di atas, dengan mengorbankan konsumsi ruang disk tambahan.

Saat menggunakan opsi ini, pertimbangkan untuk menyiapkan pengelola artefak Maven sehingga Anda tidak perlu terlalu sering menggunakan repositori Maven jarak jauh.

Jika Anda lebih suka mengaktifkan mode ini di semua tugas Maven yang dijalankan di Hudson, lihat teknik yang dijelaskan di sini.

Semoga ini bisa membantu - jika tidak mengatasi masalah Anda, beri tahu saya di mana saya ketinggalan.


Bug yang disebutkan di atas telah diperbaiki: bugs.eclipse.org/bugs/show_bug.cgi?id=339527
HDave

1

Secara groovy , menghapus file yang artifact-0.0.1-20101204.150527-6.jardiberi stempel waktu bisa sangat sederhana:

root = 'path to your repository'

new File(root).eachFileRecurse {
  if (it.name.matches(/.*\-\d{8}\.\d{6}\-\d+\.[\w\.]+$/)) {
    println 'Deleting ' + it.name
    it.delete()
  }
}

Instal Groovy , simpan skrip ke dalam file dan jadwalkan eksekusi setiap minggu, mulai, masuk, apa pun yang cocok untuk Anda.

Atau, Anda bahkan dapat mentransfer eksekusi ke maven build, menggunakan gmavenplus-plugin . Perhatikan, bagaimana lokasi repositori diatur oleh maven ke dalam properti settings.localRepositorydan kemudian diikat melalui konfigurasi ke dalam variabel repository:

  <plugin>
    <groupId>org.codehaus.gmavenplus</groupId>
    <artifactId>gmavenplus-plugin</artifactId>
    <version>1.3</version>
    <executions>
      <execution>
        <phase>install</phase>
        <goals>
          <goal>execute</goal>
        </goals>
      </execution>
    </executions>
    <configuration>
      <properties>
        <property>
          <name>repository</name>
          <value>${settings.localRepository}</value>
        </property>
      </properties>
      <scripts>
        <script><![CDATA[
          new File(repository).eachFileRecurse {
            if (it.name.matches(/.*\-\d{8}\.\d{6}\-\d+\.[\w\.]+$/)) {
              println 'Deleting snapshot ' + it.getAbsolutePath()
              it.delete()
            }
          }
        ]]></script>
      </scripts>
    </configuration>
    <dependencies>
      <dependency>
        <groupId>org.codehaus.groovy</groupId>
        <artifactId>groovy-all</artifactId>
        <version>2.3.7</version>
        <scope>runtime</scope>
      </dependency>
    </dependencies>
  </plugin>  

0

Tambahkan parameter berikut ke dalam file POM Anda

POM

<configuration>
<outputAbsoluteArtifactFilename>true</outputAbsoluteArtifactFilename>
</configuration>

https://maven.apache.org/plugins/maven-dependency-plugin/copy-mojo.html

Contoh POM

<plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <version>2.10</version>
        <executions>
          <execution>
            <id>copy</id>
            <phase>package</phase>
            <goals>
              <goal>copy</goal>
            </goals>
            <configuration>
              <artifactItems>
                <artifactItem>
                  <groupId>junit</groupId>
                  <artifactId>junit</artifactId>
                  <version>3.8.1</version>
                  <type>jar</type>
                  <overWrite>false</overWrite>
                  <outputDirectory>${project.build.directory}/alternateLocation</outputDirectory>
                  <destFileName>optional-new-name.jar</destFileName>
                </artifactItem>
              </artifactItems>
              **<outputAbsoluteArtifactFilename>true</outputAbsoluteArtifactFilename>**
              <outputDirectory>${project.build.directory}/wars</outputDirectory>
              <overWriteReleases>false</overWriteReleases>
              <overWriteSnapshots>true</overWriteSnapshots>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

Konfigurasikan di Jenkins:

// copy artifact 
copyMavenArtifact(artifact: "commons-collections:commons-collections:3.2.2:jar", outputAbsoluteArtifactFilename: "${pwd()}/target/my-folder/commons-collections.jar")
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.