Blog

Kontinuierliche Freigabe von Maven-Artefakten

Marcus Martina

Aktualisiert Oktober 22, 2025
5 Minuten

Konzeptionell unterscheidet Maven zwischen Snapshot-Versionen und Release-Versionen. Für Maven-Projekte auf höchster Ebene, die kontinuierlich integriert werden, ist es unnatürlich, diese Unterscheidung zu treffen. Insbesondere wenn eine Art von kontinuierlichem Deployment implementiert ist, macht es nicht viel Sinn, Artefakte mit einer Snapshot-Version zu erstellen und zu verteilen. Snapshot-Versionen können nicht mit einer eindeutigen Revision in einem Versionskontrollsystem verknüpft werden und können mehrdeutige Snapshot-Abhängigkeiten aufweisen. Deshalb sollten solche Artefakte nicht in einer Live-Umgebung bereitgestellt werden. Obwohl es möglich ist, Versionskontrollinformationen als Metadaten in Artefakte einzubetten, z.B. über die Manifest-Datei, wird empfohlen, Snapshot-Versionen ganz zu vermeiden. Stattdessen sollten nur eindeutige Release-Versionen kontinuierlich erstellt und bereitgestellt werden. Tatsächlich kann jede einzelne Revision als Release betrachtet werden, wie weiter unten gezeigt wird.Um dieses Konzept der kontinuierlichen Freigabe muss die Revisionsnummer Teil der Artefaktversion sein. Die Revisionsnummer sollte jedoch nicht zu einem statischen, fest kodierten Teil der Maven-Projektversion gemacht werden. Selbst wenn eine solche Aufnahme automatisiert werden könnte, zum Beispiel durch die Anwendung einer Schlüsselworterweiterung, wäre es unpraktisch, eine POM-Datei bei jedem einzelnen Commit zu ändern.Eine geeignetere Strategie ist es, die Revisionsnummer zu einem dynamischen Teil der Maven-Projektversion zu machen, indem ein Ausdruck verwendet wird, der zur Build-Zeit ersetzt wird. Dieser Ansatz steht jedoch im Widerspruch zur Philosophie von Maven in Bezug auf Projektversionen, da Maven von der Verwendung von nicht fixierten Projektversionen abrät. Darüber hinaus werden nicht-fixierte übergeordnete Versionen nicht einmal unterstützt, was es unmöglich macht, die Snapshot-Version im Falle eines Multi-Modul-Maven-Projekts vollständig loszuwerden. Nehmen wir dennoch an, dass wir einen kontinuierlichen Build eines Multi-Modul-Maven-Projekts auf oberster Ebene haben und die Revisionsnummer dynamisch in die Projektversion aufnehmen möchten. Wir werden einen Ausdruck für diese Einbindung verwenden, obwohl diese Funktion von zukünftigen Maven-Versionen möglicherweise nicht mehr unterstützt wird. Außerdem können wir die Projektversion in einen funktionalen und einen technischen Teil aufteilen. Der funktionale Teil ist eine statische Hauptversionsnummer, die manuell gepflegt werden muss. Der technische Teil ist die dynamische Revisionsnummer, die dem Build-Prozess zur Verfügung gestellt werden muss. In der Child-POM werden die Projektversion und die Parent-Version wie folgt definiert

<Version>${release}-${revision}</version> <Elternteil><version>1.0-SNAPSHOT</version></parent>

Das übergeordnete POM ist ein geeigneter Ort, um geeignete Standardwerte für die Eigenschaften Release und Revision festzulegen:

<version>1.0-SNAPSHOT</version> <Eigenschaften><release>1.0</release><Revision>SNAPSHOT</revision></properties>

Damit die tatsächliche Revisionsnummer korrekt in die Projektversion jedes Moduls aufgenommen werden kann, muss sie als Systemeigenschaft -Drevision=$N an den Maven Build-Prozess übergeben werden. Beachten Sie, dass das Build Number Maven Plugin dafür nicht verwendet werden kann, da es die Revisionsnummer erst setzen kann, nachdem die Projektversionen bereits von Maven aufgelöst wurden. Angenommen, Jenkins wird als Build-Server und Subversion als Versionskontrollsystem verwendet, kann N einfach durch die in Jenkins eingebaute Variable SVN_REVISION ersetzt werden. Im Falle von nachgelagerten Builds innerhalb einer echten Pipeline muss N durch die spezielle Pipeline-Variable PL_SVN_REVISION ersetzt werden.Das Projekt kann auch ohne Übergabe einer Revisionsnummer als Systemeigenschaft gebaut werden. In diesem Fall haben die Module einfach dieselbe Snapshot-Version wie das übergeordnete Projekt. Dies ist für lokale Entwickler-Builds ausreichend.Wenn das Maven-Projekt der obersten Ebene mit dynamischen Projektversionen konfiguriert ist, ist es nicht mehr möglich, das Maven Release Plugin zu verwenden, da dieses Plugin einfach alle Ausdrücke durch statische Versionen ersetzen würde. Dasselbe gilt natürlich auch für das Jenkins M2Release Plugin. Aber es besteht ohnehin keine Notwendigkeit mehr, eine Maven-Freigabe durchzuführen, da wir das Konzept der kontinuierlichen Freigabe umsetzen. Dies bedeutet insbesondere, dass es keine Revisionen mehr gibt, die automatisch im Versionskontrollsystem markiert werden. Dies ist sinnvoll, da jede Revision bereits eine eindeutige Version identifiziert und ein Kandidat für die Bereitstellung in einer Produktionsumgebung ist. Außerdem werden keine Artefaktversionen mehr an einen Maven-Repository-Manager wie Nexus bereitgestellt. Jenkins selbst kann jedoch als Maven Repository Server verwendet werden. Die Jenkins Maven Repository Server Plugin stellt alle archivierten Artefakte in einem einzigen Repository zur Verfügung, sofern sie für unterschiedliche Revisionsnummern erstellt wurden:

${JENKINS_URL}plugin/repository/everything/

Ein weiterer wichtiger Vorteil der ausschließlichen Erstellung von Release-Versionen besteht darin, dass kontinuierliche Integration und kontinuierliche Bereitstellung jetzt noch besser zusammenpassen. Mit dem Deployit-Plugin ist es sehr einfach, Deployment-Pakete zu erstellen, zu importieren und bereitzustellen. Solche Deployment-Pakete haben die gleiche eindeutige Anwendungsversion wie die generierten Deployables, die in diesen Paketen enthalten sind. Abgesehen von der übergeordneten POM-Version gibt es keine Snapshot-Versionen, so dass keine anderen Identifikatoren wie Zeitstempel verwendet werden müssen, um die bereitgestellten Anwendungen zu identifizieren. Obwohl kein Maven-Release mehr durchgeführt wird, muss die statische Hauptversionsnummer von Zeit zu Zeit aktualisiert werden, um bestimmte Anwendungsänderungen zu berücksichtigen. Dies kann einfach durch einen einzigen manuellen Commit erfolgen. Das übergeordnete POM und die untergeordneten POMs können ganz einfach mit dem Versions Maven Plugin:

mvn versions:set -DgenerateBackupPoms=false

Die Release-Eigenschaft im übergeordneten POM muss ebenfalls entsprechend aktualisiert werden. Bei der Vorbereitung eines Maven-Release wird automatisch überprüft, dass die freizugebende Revision keine Snapshot-Abhängigkeiten hat. Da nun jede Revision als Release betrachtet wird, gilt diese Regel eigentlich für jede Revision. Um dies automatisch überprüfen zu lassen, wird das Maven Enforcer Plugin verwendet werden, um die entsprechende Regel Require Release Dependencies durchzusetzen. Da das übergeordnete POM immer eine Snapshot-Version hat, muss die Eigenschaft failWhenParentIsSnapshot allerdings auf false gesetzt werden. Diese Prüfung wird normalerweise nur auf dem Build-Server durchgeführt, natürlich durch die Aktivierung des Maven-Profils.

Verfasst von

Marcus Martina

Contact

Let’s discuss how we can support your journey.