89 Stimmen

Wie kann man mit Maven-3 zeitgestempelten Snapshots effizient umgehen?

Nun, da maven-3 die Tropfenabstützung für die <uniqueVersion>false</uniqueVersion> für Snapshot Artefakte scheint es, dass Sie wirklich zeitgestempelte SNAPSHOTS verwenden müssen. Speziell m2eclipse, welches maven 3 intern verwendet, scheint davon betroffen zu sein, update-snapshots funktioniert nicht, wenn die SNAPSHOTS nicht eindeutig sind.

Es schien das Beste zu sein vorher üben um alle Schnappschüsse auf uniqueVersion=false zu setzen

Nun scheint es kein großes Problem zu sein, auf die zeitgestempelte Version umzusteigen, schließlich werden sie von einem zentralen Nexus-Repository verwaltet, das in der Lage ist, alte Snapshots in regelmäßigen Abständen zu löschen.

Das Problem sind die lokalen Entwickler-Workstations. Ihr lokales Repository wächst schnell sehr groß mit einzigartigen Schnappschüssen.

Wie kann man mit diesem Problem umgehen?

Im Moment sehe ich die folgenden möglichen Lösungen:

  • Bitten Sie die Entwickler, das Repository in regelmäßigen Abständen zu bereinigen (was zu viel Frustration führt, da es lange dauert, alles zu löschen und noch länger, alles herunterzuladen, was benötigt wird)
  • Ein Skript einrichten, das alle SNAPSHOT Verzeichnisse aus dem lokalen Repository und bitten Sie die Entwickler, dieses Skript von Zeit zu Zeit auszuführen (besser als das erste, aber es dauert immer noch ziemlich lange, bis es ausgeführt und aktuelle Snapshots heruntergeladen sind)
  • Verwenden Sie das Plugin dependency:purge-local-repository (hat Probleme, wenn es von Eclipse aus ausgeführt wird, wegen offener Dateien, muss von jedem Projekt aus ausgeführt werden)
  • nexus auf jeder Workstation einrichten und einen Job zum Bereinigen alter Snapshots einrichten (bestes Ergebnis, aber ich möchte nicht 50+ nexus-Server verwalten, außerdem ist der Speicher auf den Entwickler-Workstations immer knapp)
  • SNAPSHOTS überhaupt nicht mehr verwenden

Wie lässt sich am besten verhindern, dass Ihr lokales Repository den Festplattenspeicher füllt?

Aktualisierung:

Um das Verhalten zu überprüfen und mehr Informationen zu erhalten, habe ich einen kleinen Nexus-Server eingerichtet, zwei Projekte (a und b) erstellt und ausprobiert:

a:

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

Wenn ich nun Maven verwende und "deploy" auf "a" ausführe, habe ich

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

im lokalen Repository. Jedes Mal, wenn ich das Bereitstellungsziel ausführe, wird eine neue Version mit Zeitstempel erstellt. Dasselbe passiert, wenn ich versuche, Snapshots vom Nexus-Server zu aktualisieren (Projekt "a" schließen, aus dem lokalen Repository löschen, "b" erstellen).

In einer Umgebung, in der viele Snapshots erstellt werden (z.B. Hudson Server ...), füllt sich das lokale Reposioty mit alten Versionen schnell

Update 2:

Um herauszufinden, wie und warum dies scheitert, habe ich einige weitere Tests durchgeführt. Jeder Test ist gegen saubere alles laufen (de/glauche wird von beiden Maschinen und Nexus löschen)

  • mvn deploy mit maven 2.2.1 :

Das lokale Repository auf Rechner A enthält snapshot.jar + snapshot-timestamp.jar

ABER: nur ein mit einem Zeitstempel versehenes Gefäß in Nexus, Metadaten lesen:

<?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>
  • Update-Abhängigkeiten (auf Rechner B) in m2eclipse ausführen (eingebettetes m3 final) -> lokales Repository hat snapshot.jar + snapshot-timestamp.jar :(
  • Paketziel mit externem Maven 2.2.1 ausführen -> lokales Repository hat snapshot.jar + snapshot-timestamp.jar :(

Ok, nächster Versuch mit Maven 3.0.1 (nachdem alle Spuren von Projekt a entfernt wurden)

  • lokales Repository auf Rechner A sieht besser aus, nur ein einziges nicht zeitgestempeltes jar

  • nur ein zeitgestempeltes Glas in Nexus, Metadaten werden gelesen:

    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>
  • Update-Abhängigkeiten (auf Rechner B) in m2eclipse ausführen (eingebettetes m3 final) -> lokales Repository hat snapshot.jar + snapshot-timestamp.jar :(

  • Paketziel mit externem Maven 2.2.1 ausführen -> lokales Repository hat snapshot.jar + snapshot-timestamp.jar :(

Also, um es noch einmal zusammenzufassen: Das "deploy"-Ziel in maven3 funktioniert besser als in 2.2.1, das lokale Repository auf dem erstellenden Rechner sieht gut aus. Aber der Empfänger hat am Ende immer viele Versionen mit Zeitstempel ...

Was mache ich falsch?

Aktualisierung 3

Ich habe auch verschiedene andere Konfigurationen getestet, zuerst nexus durch artifactory ersetzen -> gleiches Verhalten. Dann verwende ich Linux Maven 3 Clients, um die Snapshots vom Repository Manager herunterzuladen -> das lokale Repository hat immer noch zeitgestempelte Snapshots :(

0 Stimmen

Ähnliche Frage, nur zu den lokalen .m2 \repository Teil, der sich auf das lokale Repository auf einem (Jenkins-)Build-Server konzentriert: stackoverflow.com/q/9729076/223837 .

0 Stimmen

Hier ist ein funktionierender Link zu den Apcahe Maven Comptability Notes - cwiki.apache.org/confluence/display/MAVEN/

37voto

HDave Punkte 20835

Le site <uniqueVersion> Konfiguration, die auf Artefakte angewandt wird, die (über mvn deploy) in ein Maven-Repository wie Nexus deployt wurden.

Um diese aus Nexus zu entfernen, können Sie ganz einfach einen automatisierten Job erstellen, der das SNAPSHOT-Repository jeden Tag bereinigt. Er kann so konfiguriert werden, dass er eine bestimmte Anzahl von Shapshots aufbewahrt oder sie für eine bestimmte Zeit aufbewahrt. Das ist super einfach und funktioniert hervorragend.

Artefakte im lokalen Repository auf einem Entwickler-Rechner gelangen über das "install"-Ziel dorthin und verwenden diese Zeitstempel nicht... sie ersetzen einfach die einzige SNAPSHOT-Version, es sei denn, Sie erhöhen auch die Revisionsnummer (z.B. 1.0.0-SNAPSHOT zu 1.0.1-SNAPSHOT).

1 Stimmen

Das Problem ist, dass das "install"-Ziel in einer verteilten Umgebung mit vielen Entwicklern nicht so sehr von Nutzen ist. Wir verwenden auch einen Hudson-Server, der bei jedem cvs-Commit neue Snapshots erstellt (und bereitstellt), was jeden Tag ziemlich oft passiert. Ich wusste über die Nexus Snapshot löschen mechainsm, siehe die Liste der möglichen Workarounds.

0 Stimmen

Jeder Entwicklungsrechner sollte ein "lokales" Repository unter ~/.m2/repository und jede pom.xml sollte eine Repository-Definition haben, die auf eine einzelne Instanz von Nexus in Ihrem LAN verweist. (genau wie Sie zeigen). Wir haben das so eingerichtet, zusammen mit Hudson, das auf jeden Subversion-Commit baut, und es funktioniert hervorragend. SNAPSHOT-Builds werden an Nexus "verteilt", wo sie gesammelt und wöchentlich gelöscht werden. Die Maschinen der Entwickler laden automatisch die neuesten SNAPSHOTs von Nexus auf ~/.m2/repository und ersetzt die zuvor heruntergeladene Datei. Entwickler sollten niemals ihre eigene Nexus-Instanz haben.

2 Stimmen

Ich habe gerade Ihr Update gelesen und möchte noch eine Sache hinzufügen: Die mit einem Zeitstempel versehenen Artefakte sollten niemals in Ihrem lokalen (~/.m2/repository) Repository zu sehen sein. Falls doch, stimmt etwas nicht. Sie sollten nur innerhalb von Nexus zu sehen sein. Innerhalb von Nexus, ja, sie sammeln sich schnell an. Möglicherweise Hunderte von MBs pro Tag. Ein Nexus-Job kann diese täglich bereinigen, um die Menge klein zu halten.

15voto

Cathy Punkte 169

Dieses Plugin entfernt die Artefakte des Projekts aus dem lokalen Repository. Nützlich, um nur eine Kopie eines großen lokalen Snapshots zu behalten.

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

9voto

yurinadestin Punkte 111

Nun, mir gefiel keine der vorgeschlagenen Lösungen. Das Löschen des Maven-Caches erhöht den Netzwerkverkehr oft erheblich und verlangsamt den Build-Prozess. Das build-helper-maven-plugin hilft nur bei einem Artefakt, ich wollte eine Lösung, die alle veralteten Snapshot-Artefakte mit Zeitstempel mit einem einfachen Befehl aus dem lokalen Cache löschen kann. Nach einigen Tagen der Suche habe ich aufgegeben und beschlossen, ein kleines Programm zu schreiben. Das fertige Programm scheint in unserer Umgebung recht gut zu funktionieren. Daher habe ich beschlossen, es mit anderen zu teilen, die ein solches Werkzeug benötigen. Die Quellen können von github gezogen werden: https://github.com/nadestin/tools/tree/master/MavenCacheCleanup

0 Stimmen

@HDave Ich habe es nicht geschafft, das pom-Fragment hier richtig zu formatieren, schau mal unter https://github.com/nadestin/tools/wiki/m2cachecleanup-maven-plugin . Auf unseren Jenkins-Slaves beansprucht dieses Dienstprogramm täglich ~200 MB Festplattenplatz.

2voto

cwash Punkte 4055

Was den Teil mit dem entfernten Repository angeht, denke ich, dass die vorherigen Antworten, die eine regelmäßige Bereinigung von SNAPSHOTs diskutieren, funktionieren werden. Aber niemand hat sich mit dem Teil Ihrer Frage befasst, der sich auf die Synchronisierung der Arbeitsstation des lokalen Entwicklers bezieht.

Wir haben noch nicht mit der Verwendung von Maven3 begonnen, daher müssen wir noch sehen, wie sich SNAPSHOTs auf den lokalen Rechnern aufbauen.

Aber wir hatten andere Probleme mit m2eclipse. Wenn wir "Workspace Resolution" aktiviert haben und das Projekt in unserem Workspace existiert, sind wir mit den Source-Updates in der Regel auf der Höhe der Zeit. Aber wir haben festgestellt, dass es sehr schwierig ist, m2eclipse dazu zu bringen, sich mit kürzlich veröffentlichten Artefakten in Nexus zu aktualisieren. Wir haben ähnliche Probleme in unserem Team und es ist besonders problematisch, weil wir einen sehr großen Projektgraphen haben... es gibt viele Abhängigkeiten, die sich nicht in Ihrem Workspace befinden, aber häufig SNAPSHOTs veröffentlicht bekommen.

Ich bin mir ziemlich sicher, dass dies auf ein Problem in m2eclipse zurückzuführen ist, bei dem SNAPSHOTs nicht genau so gehandhabt werden, wie es sein sollte. Sie können in der Maven-Konsole in eclipse sehen, dass m2eclipse das Update eines kürzlich veröffentlichten SNAPSHOTs überspringt, weil es eine gecachte Version hat. Wenn Sie ein -U aus einer Run-Konfiguration oder von der Kommandozeile aus ausführen, Maven wird die Änderung der Metadaten aufgreifen. Eine "Update Snapshots..."-Auswahl sollte m2eclipse jedoch dazu veranlassen, diesen Cache ablaufen zu lassen. Es scheint aber nicht weitergegeben zu werden. Es scheint einen Bug für dieses Problem zu geben, wenn Sie daran interessiert sind, dafür zu stimmen: https://issues.sonatype.org/browse/MNGECLIPSE-2608

Sie haben dies irgendwo in einem Kommentar erwähnt.

Die beste Lösung für dieses Problem scheint darin zu bestehen, dass die Entwickler ihre lokalen Workstations löschen, wenn es in m2eclipse zu Problemen kommt. Ähnliche Lösung für ein anderes Problem... Andere haben von Problemen mit Maven 2.2.1 und 3 in Verbindung mit m2eclipse berichtet, und auch ich habe das gleiche Problem beobachtet.

Ich hoffe, wenn Sie Maven3 verwenden, können Sie es so konfigurieren, dass es nur den neuesten SNAPSHOT zieht und diesen für die im Repository angegebene Zeitspanne zwischenspeichert (oder bis Sie ihn von Hand ablaufen lassen). Hoffentlich werden Sie dann nicht brauchen, um eine Reihe von SNAPSHOTs sitzen in Ihrem lokalen Repository haben.

Es sei denn, Sie sprechen von einem Build-Server, der manuell eine mvn install über sie. Um zu verhindern, dass sich SNAPSHOTs in einer Umgebung wie einem Build-Server ansammeln, sind wir diesem Problem ausgewichen, indem jeder Build seinen eigenen Arbeitsbereich und sein eigenes lokales Repository verwendet (obwohl in Maven 2.2.1 bestimmte Dinge wie POMs immer aus dem ~/.m2/Repository zu kommen scheinen). Die zusätzlichen SNAPSHOTs bleiben wirklich nur für einen einzigen Build bestehen und werden dann fallen gelassen (und wieder von Grund auf heruntergeladen). Wir haben also gesehen, dass dieser Ansatz am Ende mehr Speicherplatz verbraucht, aber er bleibt tendenziell stabiler, als wenn alles aus einem einzigen Repository aufgelöst wird. Diese Option (auf Hudson) heißt "Use private Maven repository" und befindet sich unter der Schaltfläche Advanced im Build-Abschnitt der Projektkonfigurationen, wenn Sie sich für den Build mit Maven entschieden haben. Hier ist die Hilfebeschreibung für diese Option:

Normalerweise verwendet Hudson die lokale Maven Repository, wie von Maven festgelegt - der genaue Prozess scheint zu sein undokumentiert zu sein, aber es ist ~/.m2/repository und kann überschrieben werden durch in ~/.m2/settings.xml überschrieben werden (siehe die Referenz für weitere Details). Dies bedeutet normalerweise dass alle Jobs, die auf demselben Knoten ausgeführt werden demselben Knoten ausgeführt werden, ein einziges Maven Repository teilen. Der Vorteil hiervon ist, dass Sie den Plattenplatz sparen können, aber die Nachteil ist, dass manchmal diese Builds sich gegenseitig stören können gegenseitig stören. Zum Beispiel könnte es passieren, dass dass Builds fälschlicherweise erfolgreich sind, nur weil Sie alle Abhängigkeiten in Ihrem lokalen Repository haben, trotz der Tatsache, dass keines der Repositories in POM sie haben könnte.

Es gibt auch einige gemeldete Probleme mit konkurrierenden Maven Prozessen, die versuchen, das gleiche lokale Repository zu verwenden.

Wenn diese Option aktiviert ist, wird Hudson Maven anweisen, die Datei $WORKSPACE/.repository als das lokale Maven-Repository zu verwenden. Dies bedeutet, dass jeder Job erhält sein eigenes isoliertes Maven Repository nur für sich selbst. Es behebt die oben genannten Probleme, allerdings auf Kosten von zusätzlichen Speicherplatzverbrauchs.

Wenn Sie diese Option verwenden, sollten Sie Folgendes beachten einen Maven Artefaktmanager einzurichten, damit damit Sie nicht zu oft auf entfernte Maven-Repositories zu oft aufrufen müssen.

Wenn Sie diesen Modus lieber aktivieren möchten in allen Maven-Jobs, die auf Hudson ausgeführt werden, verwenden Sie die Technik die hier beschrieben ist.

Ich hoffe, das hilft Ihnen - wenn Ihr Problem damit nicht gelöst ist, lassen Sie mich bitte wissen, was ich übersehen habe.

0 Stimmen

Der oben erwähnte Fehler wurde behoben: bugs.eclipse.org/bugs/show_bug.cgi?id=339527

1voto

vnov Punkte 335

In groovy das Löschen von Dateien mit Zeitstempel wie artifact-0.0.1-20101204.150527-6.jar kann sehr einfach sein:

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()
  }
}

Installieren Sie Groovy Speichern Sie das Skript in einer Datei und planen Sie die Ausführung für jede Woche, den Start, die Anmeldung oder was immer Sie wollen.

Oder Sie können die Ausführung sogar in Maven Build einbinden, indem Sie gmavenplus-Plugin . Beachten Sie, wie der Speicherort des Repositorys von Maven in der Eigenschaft settings.localRepository und dann über die Konfiguration in die Variable 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>

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X