webentwicklung-frage-antwort-db.com.de

Wie aktualisiere ich die Version der Kindermodule in Maven?

Wie aktualisiere ich die Version der untergeordneten Module? Es gibt eine Menge solcher Stackoverflow-Fragen, aber ich konnte keine finden, die genau zu diesem Szenario passt ... würde mich freuen, wenn dies ein Duplikat ist.

Betrachten Sie das folgende Projekt.

parent
  --mod1
  --mod2

Zu Beginn eines Entwicklungszyklus muss das übergeordnete Element und die Module auf dieselbe Version aktualisiert werden. Wenn die Version des übergeordneten Elements und der Module während des gesamten Release gleich bleiben würde, würde ich einfach das Tag <version> aus den Modulen weglassen und versions:set -DnewVersion=1.1.1 ausführen, um den Entwicklungszyklus zu starten. Es stellt sich jedoch heraus, dass nicht alle Module den Zyklus mit derselben Version beenden. Wenn Bugs und Fixes auftreten, werden nur die Module mit den Bugs aktualisiert. Das übergeordnete Element und mod2 befinden sich möglicherweise in Version 1.1.1-RC1, mod1 jedoch möglicherweise in Version 1.1.1-RC2.

Als solches muss ich:
1) Fügen Sie ein <version>-Tag in die Module ein, um jede Modulversion unabhängig zu verfolgen.

2) Wenn mod2 mod1 als abhängigkeit benötigt, muss ich sicherstellen, dass mod2 auf die neueste version von mod1 verweist.

Dies führt zu den folgenden zwei Fragen.

1) Wie kann ich zu Beginn des Zyklus das übergeordnete Element und die Module in einem einzigen Maven-Befehl auf dieselbe Version einstellen? Ich habe version:set -DnewVersion=1.1.1 ausprobiert, aber dies aktualisiert nur die Version der Eltern über alle POMs hinweg, jedoch nicht die Version des Moduls. Ich habe auch -N versions:update-child-modules ausprobiert, aber ich glaube, ich verwende es falsch, weil es nichts bewirkt. Es wird nur für alle Module übersprungen.

2) Dies ist etwas schwieriger und entspricht dem obigen Punkt 2. Wie aktualisiere ich in einem Schritt sowohl die Version von mod1 als auch die Referenz von mod2 auf die Version von mod1? Ich weiß, wie es in zwei Schritten geht:

eltern-Pom:

<properties>
    <!-- update this manually if mod1's version no longer matches parent -->
    <mod1.version>${project.version}</mod1.version>
</properties>

mod2 pom:

    <dependency>
        <groupId>com.xxx</groupId>
        <artifactId>mod1</artifactId>
        <version>${mod1.version}</version>
    </dependency>

Wenn mod1 auf 1.1.1-RC2 hochfährt, aktualisiere ich das übergeordnete POM und das mod1 POM, um dies widerzuspiegeln. Das sind zwei Schritte. Wie auch immer, um es in einen Schritt zu verwandeln?

Mein Beispiel war klein, aber im wirklichen Leben gibt es viele Module, die diese wichtige Zeitersparnis ermöglichen, und ich bin neugierig.

17
Jose Martinez

Frage 1)

Der beste Weg zur Verwaltung des Anwendungslebenszyklus und der Releases ist die Verwendung des Release-Plugins.

Wie Sie vielleicht wissen, ist Maven Philosophie Konvention über Konfiguration. Maven-Konvention ist, Snapshot-Versionen (die mit -SNAPSHOT enden) während der Entwicklung zu verwenden und eine Nicht-Snapshot-Version nur für Releases zuzuweisen.

Angenommen, Sie entwickeln Version 1.1.1. Während der Entwicklung verwenden Sie nur 1.1.1-SNAPSHOT. Maven kümmert sich um die Aktualisierung des Schnappschusses. Wenn Sie ein Artefakt-Repository verwenden, können Sie -U verwenden, um sicherzustellen, dass Sie immer über die letzte Version der Momentaufnahmen verfügen.

Wenn das Release fertig ist, generiert und implementiert das Plug-In-Release Version 1.1.1 und aktualisiert POMs mit der neuen Entwicklungsversion, z. B. 1.1.2-SNAPSHOT.

Bei Multimodulprojekten gibt es zwei Szenarien: Module sind verwandt, aber unabhängig voneinander (z. B. mehrere Webanwendungen), oder sie sind Module einer einzelnen großen Anwendung oder Bibliothek, und sie verwenden Versionen. Sie scheinen sich für Letzteres zu interessieren.

In diesem Fall ist es am einfachsten, dasselbe übergeordnete (möglicherweise auch root-) Modul einschließlich seiner Version zu erben. Sie referenzieren die übergeordnete Gruppe: Artifact: Version und geben keine Version für die untergeordneten Elemente an. Im Allgemeinen erben Sie auch eine Gruppe, sodass Ihr Pom so aussehen kann:

<parent>
   <groupId>com.mycompany.myproject</groupId>
   <artifactId>myproject-parent</artifactId>
   <version>1.1.1-SNAPSHOT</version>
   <relativePath>../myproject-parent</relativePath>
</parent>
<artifactId>myproject-module1</artifactId>

Jetzt müssen Sie nur noch auf Kinder achten, die mit Hilfe des Release-Plugins auf die richtige Version des Elternteils zeigen.

Damit Sie mehr über Kinder erfahren können, sollten Sie Ihren Eltern-Pom auch zu einem Root-Pom machen, indem Sie den Modulabschnitt einschließen, wie später gezeigt.

Frage 2) Normalerweise erkläre ich Eigenschaften mit allen Versionen aller Artefakte, auf die verwiesen werden kann. Wenn mehrere Module die Version gemeinsam nutzen, benötigen Sie nur eine Eigenschaft. Das Elternteil kann so aussehen:

<groupId>com.mycompany.myproject</groupId>
<artifactId>myproject-parent</artifactId>
<version>1.1.1-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
   <myproject.version>1.1.1-SNAPSHOT</myproject.version>
</properties>

.......

<modules>
   <module>../myproject-module1</module>
   ...
</modules>

Kinder können über andere Module referenzieren

<version>${myproject.version}</version>

Es ist eine sehr schlechte Praxis, Abhängigkeiten mit LATEST zu deklarieren. Angenommen, Sie tun dies für Version 1.1.1. Jetzt arbeiten Sie mit Version 1.1.2-SNAPSHOT und haben wahrscheinlich Artefakte, wenn diese Version in Ihrem lokalen Repo installiert ist.

Nun sagen Sie aus irgendeinem Grund, dass Sie Version 1.1.1 neu erstellen müssen, beispielsweise aufgrund eines Fehlers in der Produktion. Ihr Build wird die neue Version verwenden. Wenn Sie Glück haben, wird dies den Build zerstören. Wenn Sie Pech haben, kann die Produktion sogar unbemerkt bleiben.

Zu guter Letzt verwenden manche Leute gerne Eigenschaftswerte, um untergeordnete Versionen zu deklarieren. Dies wird dringend empfohlen und wird von maven als Warnung angezeigt. Ich persönlich mache das nie. Die Gründe hängen auch mit der Reproduzierbarkeit von Builds und der Tatsache zusammen, dass Maven davon ausgeht, dass sich ein Release-Build niemals ändern wird. Dass eine Modulversion extern anpassbar ist, ist nicht wirklich eine gute Idee.

BEARBEITEN:

Fall, wenn die Modulversionen nicht ausgerichtet sind.

Tatsächlich können beide Szenarien gemischt werden. Sie können beispielsweise Folgendes haben:

Elternteil

--- Komponente1

--- Komponente2

--- Komponente3

------ Comp3Module1

------ Como3Module2

------ Comp3Module3

Die übergeordneten und die drei Komponentenversionen unterscheiden sich, und die drei Module von Komponente3 haben dieselbe Version wie zuvor erläutert.

Frage 1) In diesem Fall wird die Version jedes Moduls uneingeschränkt angegeben. Wie bereits erwähnt, ist es eine schlechte Idee, eine Eigenschaft zur Angabe der Modulversion zu verwenden, weshalb ich nur empfehlen kann, sie wörtlich anzugeben versions. Wie bereits erwähnt, ist die Verwaltung von Versionsverwaltung am besten, das Release-Plugin zu verwenden und es in das Versionskontrollsystem zu integrieren, z. B. SVN. Weitere Antworten enthalten Einzelheiten zur Verwendung Ich werde es also nicht weiter ausführen, es sei denn, ich werde darum gebeten.

Frage 2) Der empfohlene Ansatz ist der gleiche, wenn Sie dieselbe Version verwenden, nur dass Sie mehrere Eigenschaften benötigen. Das übergeordnete Element kann folgendermaßen aussehen:

<properties>
   <myproject.group>com.mycompany.myproject</myproject.group>
   <component1.version>1.1.1-RC1</component1.version>
   <component2.version>1.1.1-RC2</component2.version>
   <component3.version>2.0.0</component3.version>
<properties>

Anschließend können Sie die Abhängigkeitsverwaltung verwenden, um die Versionsverwaltung im übergeordneten Element zu zentralisieren.

Zum Beispiel in übergeordneten Pom,

<dependencyManagement>
   <dependencies>
      <dependency>
         <groupId>${myproject.group}</groupId>
         <artifactId>component1</artifactId>
         <version>${component1.version}</version>
      </dependency>
      <dependency>
        <groupId>${myproject.group}</groupId>
         <artifactId>component2</artifactId>
         <version>${component2.version}</version>
         <type>war</type>
      </dependency>
      <dependency>
         <groupId>${myproject.group}</groupId>
         <artifactId>comp3module1</artifactId>
         <version>${component3.version}</version>
        <type>ejb</type>
      </dependency>
      <dependency>
         <groupId>${myproject.group}</groupId>
         <artifactId>comp3module1</artifactId>
         <version>${component3.version}</version>
        <type>ejb-client</type>
      </dependency>
      <dependency>
         <groupId>${myproject.group}</groupId>
         <artifactId>comp3module2</artifactId>
         <version>${component3.version}</version>
        <type>war</version>
      </dependency>
   </dependencies>
</dependencyManagement>

Um nun von einem anderen Modul auf ein beliebiges Modul zu verweisen, ist es so einfach wie folgt:

<dependency>
   <groupId>${myproject.group}</groupId>
   <artifactId>component1</artifactId>
</dependency>
<dependency>
   <groupId>${myproject.group}</groupId>
   <artifactId>comp3module1</artifactId>
   <type>ejb-client</type>
</dependency>

Versionen werden automatisch vom übergeordneten Element aus verwaltet. Sie müssen sie nicht in Abhängigkeiten von Kindern pflegen, die auch weniger ausführlich werden.

5
Juan

Ok, das ist was ich mir ausgedacht habe. Dies basiert auf diesem kontinuierlich-freisetzenden von Maven-Artefakten Artikel.

Eltern-POM:

<properties>
    <!-- versions of modules -->
    <main.version>1.0</main.version>
    <revision>SNAPSHOT</revision> <!-- default revision -->
    <Module1.revision>${revision}</Module1.revision>
    <Module2.revision>${revision}</Module2.revision>
    <Module3.revision>${revision}</Module3.revision>
    <Module4.revision>${revision}</Module4.revision>
    <Module5.revision>${revision}</Module5.revision>
    <Module1.version>${main.version}-${Module1.revision}</Module1.version>
    <Module2.version>${main.version}-${Module2.revision}</Module2.version>
    <Module3.version>${main.version}-${Module3.revision}</Module3.version>
    <Module4.version>${main.version}-${Module4.revision}</Module4.version>
    <Module5.version>${main.version}-${Module5.revision}</Module5.version>
</properties>

Beispiel für ein untergeordnetes POM mit Interprojektabhängigkeit:

    <groupId>com.xyz</groupId>
    <artifactId>Module4</artifactId>
    <packaging>jar</packaging>
    <version>${Module4.version}</version>

    <parent>
        <groupId>com.xyz</groupId>
        <artifactId>ParentProject</artifactId>
        <version>1.0</version>
    </parent>   

    <dependencies>
        <dependency>
            <groupId>com.xyz</groupId>
            <artifactId>Module1</artifactId>
            <version>${Module1.version}</version>
        </dependency>
        <dependency>
            <groupId>com.xyz</groupId>
            <artifactId>Module2</artifactId>
            <version>${Module2.version}</version>
        </dependency>
        <dependency>
            <groupId>com.xyz</groupId>
            <artifactId>Module3</artifactId>
            <version>${Module3.version}</version>
            <type>jar</type>
        </dependency>
    <dependencies>

1) Wie kann ich zu Beginn des Zyklus in einem Maven-Befehl Eltern und Module auf dieselbe Version einstellen?

Sie brauchen nicht mehr. Das übergeordnete POM kann auf derselben Version verbleiben und sich nur ändern, wenn sich das übergeordnete POM ändert. In diesem Fall können Sie mvn version:set -DnewVersion=1.1.1 verwenden. Für diesen Ansatz brauchen Sie jedoch nicht.

Stattdessen können Sie die Version mithilfe der Eigenschaft main.version dynamisch festlegen. Z.B. mvn clean deploy -Dmain.version=1.1.1 Um eine dynamische Übergabe der Versionsnummer zu erzwingen, können Sie die Standardeigenschaft main.version weglassen, die ich oben in mein übergeordnetes POM aufgenommen habe.

2) Wie aktualisiere ich sowohl die Version von mod1 als auch den Verweis von mod2 auf die Version von mod1 in einem Schritt?

Im Grunde geht es darum, wie man mit Revisionen umgeht. Wenn ich die revision-Eigenschaft im mvn-Befehl nicht setze, verwenden alle Module SNAPSHOT als Revision. Wenn ich die revision-Eigenschaft auf RC1 setze, erhalten alle Module diese Revision. Wenn ich außerdem revision auf RC1, aber Module4.revision auf RC2 setze, erhält Module4 RC2 und alle anderen Module erhalten RC1. Dies erfüllt die Kundenanforderung nach dynamischen Modifikationen pro Modul.

Hier sind einige Beispiele: 

  • mvn clean deploy -Dmain.version=1.1.1 Setzt alle Module auf Version 1.1.1-SNAPSHOT
  • mvn clean deploy -Dmain.version=1.1.1 -Drevision=RC1 Setzt alle Module auf Version 1.1.1-RC1.
  • mvn clean deploy -Dmain.version=1.1.1 -Drevision=RC1 -DModule4.revision=RC2 Setzt alle Module auf Version 1.1.1-RC1, mit Ausnahme von Module4, das auf Version 1.1.1-RC2 eingestellt ist.

Es gibt eine Einschränkung, die erwähnt werden muss. Wenn Sie die Version eines abhängigen Moduls, z. B. Module1, auf RC2 erhöhen, müssen Sie auch die Version aller Module, die dieses Modul verwenden, erhöhen. Beispielsweise muss Modul4 nicht auf RC2 (oder die nächste Version) erhöht werden. Dies ist etwas, auf das der Client aufmerksam gemacht wurde, und deshalb würde ich es vorziehen, wenn alle Module die gleiche Version hätten. Aber ich mag die Dynamik, die dabei herauskam. Im Wesentlichen wird die Version jetzt über die Befehlszeile festgelegt, sodass keine Aktualisierungen der POM-Dateien erforderlich sind.

1
Jose Martinez

1) Ich habe auch die Version ausprobiert: In der Vergangenheit eingestellt, aber nie richtig funktioniert. Es soll den gleichen Prozess wie Release machen: Vorbereiten, aber eigentlich nicht. Was Sie also ausprobieren können, ist mvn release:prepare -DautoVersionSubmodules -DdryRun. Das soll alle Updates durchführen, ohne etwas in das Repo einzuchecken und keine Tags zu machen.

2) Ich glaube, das ClearTK-Projekt verfolgte einst eine ähnliche Strategie wie Sie: Es wurde ein Projekt mit mehreren Modulen unterhalten, wobei jedes Modul seinen eigenen Veröffentlichungszyklus hatte. Um den Überblick zu behalten, implementierten sie ein benutzerdefiniertes Maven-Plugin, um sie vor Inkonsistenzen der Abhängigkeitsversion zu warnen. 

https://github.com/ClearTK/cleartk/tree/master/consistent-versions-plugin

Obwohl ein solches Plugin die von Ihnen angeforderten Aktualisierungen nicht durchführen würde, sollte es Sie zumindest benachrichtigen, wenn Aktualisierungen erforderlich sind. Um das Problem wirklich zu beheben, sollten Sie die gleiche Route wie ClearTK befolgen und Ihr eigenes Maven-Plugin implementieren (oder Sie tun, was ClearTK schließlich getan hat: Umschalten auf einen synchronisierten Veröffentlichungszyklus;))

1
rec

1) Wie @rec sagte, würde das Plug-In für das Release von Maven den Trick tun

$ mvn release:prepare -DautoVersionSubmodules=true
$ mvn release:perform

2) Sie können die Abhängigkeit von mod2 zu mod1 wie folgt definieren:

<dependency>
    <groupId>com.xxx</groupId>
    <artifactId>mod1</artifactId>
    <version>LATEST</version>
</dependency>

Weitere Informationen: Wie kann ich Maven sagen, dass er die neueste Version einer Abhängigkeit verwenden soll?

Ich habe beide Lösungen getestet und es funktioniert! Hoffe es hilft dir :)

0
Andrés