java - tutorial - maven version




Wie sage ich Maven, die neueste Version einer Abhängigkeit zu verwenden? (8)

Bitte werfen Sie einen Blick auf diese Seite (Abschnitt "Dependency Version Ranges"). Was Sie vielleicht tun möchten, ist etwas wie

<version>[1.2.3,)</version>

Diese Versionsbereiche sind in Maven2 implementiert.

In Maven sind Abhängigkeiten normalerweise wie folgt aufgebaut:

<dependency>
  <groupId>wonderful-inc</groupId>
  <artifactId>dream-library</artifactId>
  <version>1.2.3</version>
</dependency>

Wenn Sie nun mit Bibliotheken arbeiten, die häufig veröffentlicht werden, kann das ständige Aktualisieren des Tags <version> etwas ärgerlich sein. Gibt es eine Möglichkeit, Maven mitzuteilen, immer die neueste verfügbare Version (aus dem Repository) zu verwenden?


Die Abhängigkeiten-Syntax befindet sich in der Dokumentation zur Spezifikation der Abhängigkeits-Version . Hier ist es der Vollständigkeit halber:

Das version Abhängigkeiten definiert die Versionsanforderungen, die zur Berechnung der effektiven Abhängigkeitsversion verwendet werden. Version Anforderungen haben die folgende Syntax:

  • 1.0 : "Soft" Anforderung auf 1.0 (nur eine Empfehlung, wenn sie alle anderen Bereiche für die Abhängigkeit erfüllt)
  • [1.0] : "Hard" Anforderung an 1.0
  • (,1.0] : x <= 1.0
  • [1.2,1.3] : 1.2 <= x <= 1.3
  • [1.0,2.0) : 1.0 <= x <2.0
  • [1.5,) : x> = 1.5
  • (,1.0],[1.2,) : x <= 1.0 oder x> = 1.2; Mehrere Sets sind durch Kommas getrennt
  • (,1.1),(1.1,) : Dies schließt 1.1 aus (zum Beispiel, wenn bekannt ist, dass es nicht in Kombination mit dieser Bibliothek arbeitet)

In Ihrem Fall könnten Sie etwas wie <version>[1.2.3,)</version> tun


Im Gegensatz zu anderen denke ich, es gibt viele Gründe, warum Sie immer die neueste Version möchten . Vor allem, wenn Sie eine kontinuierliche Bereitstellung durchführen (wir haben manchmal 5 Releases an einem Tag) und möchten kein Multi-Modul-Projekt erstellen.

Was ich mache ist, dass Hudson / Jenkins folgendes für jeden Build macht:

mvn clean versions:use-latest-versions scm:checkin deploy -Dmessage="update versions" -DperformRelease=true

Das heißt, ich benutze das Versions-Plugin und das scm-Plugin, um die Abhängigkeiten zu aktualisieren und checke es dann in die Quellcodeverwaltung ein. Ja, ich lasse meine CI SCM-Checkins (was Sie sowieso für das Maven-Release-Plugin tun müssen).

Sie sollten das Versions-Plugin so einrichten, dass es nur das aktualisiert, was Sie wollen:

        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>versions-maven-plugin</artifactId>
            <version>1.2</version>
            <configuration>
                <includesList>com.snaphop</includesList>
                <generateBackupPoms>false</generateBackupPoms>
                <allowSnapshots>true</allowSnapshots>
            </configuration>
        </plugin>

Ich benutze das Release-Plugin, um das Release zu erledigen, das sich um -SNAPSHOT kümmert und bestätigt, dass es eine Release-Version von -SNAPSHOT gibt (was wichtig ist).

Wenn Sie das tun, was ich tue, erhalten Sie die neueste Version für alle Snapshot-Builds und die neueste Release-Version für Release-Builds. Ihre Builds werden auch reproduzierbar sein.

Aktualisieren

Ich habe einige Kommentare gelesen, in denen einige Besonderheiten dieses Arbeitsablaufs gefragt wurden. Ich werde sagen, dass wir diese Methode nicht mehr verwenden und der Hauptgrund, warum das Maven Versionen Plugin fehlerhaft ist und im Allgemeinen fehlerhaft ist.

Es ist fehlerhaft, da das Versions-Plug-in ausgeführt werden muss, um Versionen anzupassen, die alle vorhandenen Versionen vorhanden sein müssen, damit das Pom ordnungsgemäß ausgeführt wird. Das heißt, das Versions-Plugin kann nicht auf die neueste Version von irgendetwas aktualisieren, wenn es die Version nicht finden kann, auf die im Pom verwiesen wird. Das ist eigentlich ziemlich ärgerlich, da wir alte Versionen oft aus Platzgründen aufräumen.

Wirklich brauchen Sie ein separates Werkzeug von Maven, um die Versionen anzupassen (damit Sie nicht auf die Pom-Datei angewiesen sind, um korrekt zu laufen). Ich habe ein solches Werkzeug in der einfachen Sprache geschrieben, die Bash ist. Das Skript wird die Versionen wie das Versions-Plugin aktualisieren und die Pom zurück in die Quellcodeverwaltung überprüfen. Es läuft auch 100x schneller als das mvn Versionen Plugin. Leider ist es nicht für den öffentlichen Gebrauch geschrieben, aber wenn die Leute interessiert sind, könnte ich es so machen und es in einen Sinn oder Github setzen.

Zurück zum Workflow, da einige Kommentare danach gefragt haben:

  1. Wir haben etwa 20 Projekte in ihren eigenen Repositories mit eigenen jenkins-Jobs
  2. Bei Veröffentlichung wird das maven release plugin verwendet. Der Workflow dafür ist in der Dokumentation des Plugins beschrieben. Das Maven-Release-Plugin stinkt irgendwie (und ich bin nett), aber es funktioniert. Eines Tages planen wir, diese Methode durch etwas Optimales zu ersetzen.
  3. Wenn eines der Projekte veröffentlicht wird, führt jenkins dann einen speziellen Job aus, den wir als Update aller Versionen bezeichnen werden (wie Jenkins weiß, dass eine Veröffentlichung eine komplizierte Art ist, weil das maven jenkins release plugin auch ziemlich beschissen ist).
  4. Der Update aller Versionen kennt alle 20 Projekte. Es ist eigentlich ein Aggregator Pom, um mit allen Projekten in der Modul-Sektion in Abhängigkeitsreihenfolge zu sein. Jenkins läuft unser magischer Groovy / Bash Foo, der alle Projekte auf den neusten Stand bringt und dann die Poms eincheckt (wiederum in Abhängigkeitsreihenfolge basierend auf dem Modul-Abschnitt).
  5. Für jedes Projekt, wenn sich der Pom geändert hat (wegen einer Versionsänderung in einer Abhängigkeit), wird er eingecheckt, und dann pingen wir Jenkins sofort an, um den entsprechenden Job für dieses Projekt auszuführen (um die Abhängigkeitsreihenfolge zu erhalten, sonst sind Sie der Gnade ausgeliefert) des SCM-Poll-Schedulers).

An dieser Stelle bin ich der Meinung, dass es eine gute Sache ist, die Release- und Auto-Version ein separates Tool von Ihrem allgemeinen Build zu haben.

Jetzt mag man denken, dass Maven irgendwie wegen der oben aufgelisteten Probleme saugt, aber das wäre mit einem Build-Tool, das keine deklarative, einfach zu analysierende Syntax (auch bekannt als XML) hat, ziemlich schwierig.

Tatsächlich fügen wir benutzerdefinierte XML-Attribute über Namespaces hinzu, um Bash / Groovy-Skripten anzudeuten (zB diese Version nicht zu aktualisieren).


Jetzt weiß ich, dass dieses Thema alt ist, aber beim Lesen der Frage und der gelieferten Antwort scheint das maven-versions-plugin tatsächlich eine bessere Antwort auf seine Frage gewesen zu sein:

Insbesondere könnten folgende Ziele sinnvoll sein:

  • Versionen: use-latest-versions sucht den Pom nach allen neueren Versionen und ersetzt sie durch die neueste Version.
  • Versionen: Use-Latest-Releases durchsucht den Pom nach allen nicht-SNAPSHOT-Versionen, die eine neuere Version waren, und ersetzt sie durch die neueste Release-Version.
  • Versionen: update-properties aktualisiert in einem Projekt definierte Eigenschaften so, dass sie der neuesten verfügbaren Version bestimmter Abhängigkeiten entsprechen. Dies kann nützlich sein, wenn eine Reihe von Abhängigkeiten alle für eine Version gesperrt sein müssen.

Die folgenden anderen Ziele werden ebenfalls bereitgestellt:

  • Versionen: display-dependency-updates überprüft die Abhängigkeiten eines Projekts und erstellt einen Bericht über die Abhängigkeiten, für die neuere Versionen verfügbar sind.
  • Versionen: display-plugin-updates scannt die Plugins eines Projekts und erstellt einen Bericht über diese Plugins, für die neuere Versionen verfügbar sind.
  • Versionen: update-parent aktualisiert den übergeordneten Abschnitt eines Projekts so, dass es auf die neueste verfügbare Version verweist. Wenn Sie beispielsweise ein Unternehmens-Root-POM verwenden, kann dieses Ziel hilfreich sein, wenn Sie sicherstellen müssen, dass Sie die neueste Version des Unternehmens-Root-POM verwenden.
  • Versionen: update-child-modules aktualisiert den übergeordneten Abschnitt der untergeordneten Module eines Projekts, sodass die Version der Version des aktuellen Projekts entspricht. Wenn Sie beispielsweise ein Aggregator-Pom haben, das auch das übergeordnete Element für die zusammengeführten Projekte ist und die untergeordneten und übergeordneten Versionen nicht mehr synchron sind, kann dieses Mojo helfen, die Versionen der untergeordneten Module zu reparieren. (Beachten Sie, dass Sie möglicherweise Maven mit der Option -N aufrufen müssen, um dieses Ziel zu erreichen, wenn Ihr Projekt so fehlerhaft ist, dass es aufgrund der falschen Übereinstimmung der Version nicht erstellt werden kann).
  • Versionen: lock-snapshots durchsucht den Pom nach allen -SNAPSHOT-Versionen und ersetzt sie durch die aktuelle Zeitstempelversion des -SNAPSHOT, zB -20090327.172306-4
  • Versionen: Unlock-Snapshots durchsucht den Pom nach allen Timestamp-gesperrten Snapshot-Versionen und ersetzt sie durch -SNAPSHOT.
  • Versionen: resolve-ranges findet Abhängigkeiten mithilfe von Versionsbereichen und löst den Bereich für die jeweils verwendete Version auf.
  • Versionen: Use-Releases durchsucht den POM nach allen freigegebenen -SNAPSHOT-Versionen und ersetzt sie durch die entsprechende Release-Version.
  • Versionen: use-next-releases durchsucht das POM nach allen nicht-SNAPSHOT-Versionen, die eine neuere Version waren und ersetzt sie durch die nächste Release-Version.
  • Versionen: use-next-versions sucht den Pom nach allen neueren Versionen und ersetzt sie durch die nächste Version.
  • versions: commit entfernt die pom.xml.versionsBackup-Dateien. Bildet eine Hälfte des eingebauten "SCM" des armen Mannes.
  • versions: revert stellt die pom.xml-Dateien aus den pom.xml.versionsBackup-Dateien wieder her. Bildet eine Hälfte des eingebauten "SCM" des armen Mannes.

Ich dachte nur, ich würde es für eine zukünftige Referenz hinzufügen.


Sind Sie möglicherweise auf Entwicklungsversionen angewiesen, die sich während der Entwicklung deutlich ändern?

Anstatt die Version von Entwicklungsversionen zu erhöhen, können Sie einfach eine Snapshot-Version verwenden, die Sie bei Bedarf überschreiben. Dies bedeutet, dass Sie das Versionstag nicht bei jeder geringfügigen Änderung ändern müssen. Etwas wie 1.0-SNAPSHOT ...

Aber vielleicht versuchst du etwas anderes zu erreichen;)


Wenn Sie möchten, dass Maven die neueste Version einer Abhängigkeit verwendet, dann können Sie maven-versions-plugin und wie man dieses Plugin verwendet, Tim hat bereits eine gute Antwort gegeben, folgen Sie seiner answer .

Aber als Entwickler werde ich diese Art von Praktiken nicht empfehlen. WARUM?

Antwort auf warum ist bereits von Pascal Thivent in der Kommentar der Frage gegeben

Ich empfehle diese Praxis (noch Verwendung von Versionsbereichen) aus Gründen der Build-Reproduzierbarkeit wirklich nicht. Ein Build, der plötzlich aus einem unbekannten Grund fehlschlägt, ist viel ärgerlicher als das manuelle Aktualisieren einer Versionsnummer.

Ich werde diese Art von Übung empfehlen:

<properties>
    <spring.version>3.1.2.RELEASE</spring.version>
</properties>

<dependencies>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>

</dependencies>

Es ist einfach zu warten und leicht zu debuggen. Sie können Ihr POM in kürzester Zeit aktualisieren.



HINWEIS:

Diese Antwort gilt nur für Maven 2! Die erwähnten LATEST und RELEASE Metaversionen wurden vor mehr als 6 Jahren in Maven 3 "wegen reproduzierbarer Builds" fallen gelassen . Bitte beachten Sie diese Maven 3-konforme Lösung .

Wenn Sie immer die neueste Version verwenden möchten, verfügt Maven über zwei Schlüsselwörter, die Sie als Alternative zu Versionsbereichen verwenden können. Sie sollten diese Optionen mit Vorsicht verwenden, da Sie die Plugins / Abhängigkeiten, die Sie verwenden, nicht mehr kontrollieren können.

Wenn Sie von einem Plug-in oder einer Abhängigkeit abhängig sind, können Sie den Versionswert LATEST oder RELEASE verwenden. LATEST bezieht sich auf die neueste Version oder Snapshot-Version eines bestimmten Artefakts, des zuletzt implementierten Artefakts in einem bestimmten Repository. RELEASE bezieht sich auf die letzte Nicht-Snapshot-Version im Repository. Im Allgemeinen ist es keine bewährte Vorgehensweise, Software zu entwickeln, die von einer unspezifischen Version eines Artefakts abhängt. Wenn Sie Software entwickeln, empfiehlt es sich, RELEASE oder LATEST zu verwenden, damit Sie die Versionsnummern nicht aktualisieren müssen, wenn eine neue Version einer Drittanbieterbibliothek veröffentlicht wird. Wenn Sie Software veröffentlichen, sollten Sie immer sicherstellen, dass Ihr Projekt von bestimmten Versionen abhängt, um die Wahrscheinlichkeit zu verringern, dass Ihr Build oder Ihr Projekt von einer Softwareversion beeinflusst wird, die nicht unter Ihrer Kontrolle steht. Verwenden Sie LATEST und RELEASE mit Vorsicht, wenn überhaupt.

Weitere Informationen finden Sie im Abschnitt "POM-Syntax" im Maven-Buch . Oder sehen Sie sich dieses Dokument zu den Dependency-Versionsbereichen an:

  • Eine eckige Klammer ( [ & ] ) bedeutet "geschlossen" (inklusive).
  • Eine Klammer ( ( & ) ) bedeutet "offen" (exklusiv).

Hier ein Beispiel, das die verschiedenen Optionen veranschaulicht. Im Maven-Repository hat com.foo:my-foo die folgenden Metadaten:

<?xml version="1.0" encoding="UTF-8"?><metadata>
  <groupId>com.foo</groupId>
  <artifactId>my-foo</artifactId>
  <version>2.0.0</version>
  <versioning>
    <release>1.1.1</release>
    <versions>
      <version>1.0</version>
      <version>1.0.1</version>
      <version>1.1</version>
      <version>1.1.1</version>
      <version>2.0.0</version>
    </versions>
    <lastUpdated>20090722140000</lastUpdated>
  </versioning>
</metadata>

Wenn eine Abhängigkeit von diesem Artefakt erforderlich ist, haben Sie die folgenden Optionen (andere Versionsbereiche können natürlich angegeben werden, indem Sie nur die relevanten hier anzeigen):

Deklariere eine exakte Version (wird immer auf 1.0.1 aufgelöst):

<version>[1.0.1]</version>

Deklariere eine explizite Version (wird immer zu 1.0.1 aufgelöst, es sei denn, es kommt zu einer Kollision, wenn Maven eine passende Version auswählt):

<version>1.0.1</version>

Deklariere einen Versionsbereich für alle 1.x (wird derzeit zu 1.1.1 aufgelöst):

<version>[1.0.0,2.0.0)</version>

Deklarieren Sie einen offenen Versionsbereich (wird auf 2.0.0 aufgelöst):

<version>[1.0.0,)</version>

Deklariere die Version als LATEST (wird auf 2.0.0 aufgelöst) (entfernt von maven 3.x)

<version>LATEST</version>

Deklariere die Version als RELEASE (wird zu 1.1.1 aufgelöst) (entfernt von maven 3.x):

<version>RELEASE</version>

Beachten Sie, dass Ihre eigenen Bereitstellungen standardmäßig den "neuesten" Eintrag in den Maven-Metadaten aktualisieren. Um den Eintrag "release" zu aktualisieren, müssen Sie jedoch das "release-profile" aus dem Maven Super POM aktivieren. Sie können dies entweder mit "-Prelease-Profil" oder "-DeperformRelease = true" tun.

Es sollte betont werden, dass jeder Ansatz, der Maven erlaubt, die Abhängigkeitsversionen (LATEST-, RELEASE- und Versionsbereiche) auszuwählen, Zeitprobleme aufwerfen kann, da spätere Versionen ein anderes Verhalten haben können (zum Beispiel hat das Abhängigkeits-Plugin zuvor einen Standardwechsel vorgenommen) Wert von wahr zu falsch, mit verwirrenden Ergebnissen).

Es ist daher generell eine gute Idee, genaue Versionen in Releases zu definieren. Wie Tims Antwort darauf hinweist, ist das maven-versions-plugin ein praktisches Werkzeug zum Aktualisieren von Abhängigkeitsversionen, insbesondere der versions:use-latest-versions und versions:use-latest-releases Ziele.





maven-metadata