75 Stimmen

Ableitung der Maven-Artefaktversion aus dem Git-Zweig

Wir haben eine Workflow-Anforderung, die im Wesentlichen bedeutet, dass wir die Artefaktversion eines Moduls extern von dem aktuellen Branch in git definieren müssen.

D.h. wenn wir uns auf dem Master-Branch in git befinden, benötige ich master-... und wenn wir auf dem bugfixX-Branch sind, benötige ich bugfixX-.... für das generierte Artefakt für diese pom.xml.

Ich habe bereits festgestellt, dass https://github.com/koraktor/mavanagaiata den SHA-1-Hash als Eigenschaft liefern kann und es scheint aus der Dokumentation hervorzugehen, dass es auch den Branch liefern kann. Vielleicht könnten wir, wenn es früh genug im Prozess ausgeführt wird, die Eigenschaft setzen und einfach ${our.version} in der pom platzieren. Wenn dies möglich ist, würde ich gerne eine funktionierende pom.xml sehen (und auch eine Belohnung von 500 Punkten dafür ausloben).

Wenn nicht, denke ich, dass wir entweder in die Vorverarbeitung oder "git checkout" gehen müssen, um zusätzliche Magie mit einigen der Hooks zu bewirken (was ich noch nicht ausprobiert habe, ein funktionierender Code wäre auch großartig).

Wir haben ein Top-Level-Pom, das ausgeführt werden kann, um eine Eigenschaftendatei in ".." zu generieren, bevor die Module erstellt werden, in denen diese Funktionalität, über die ich spreche, eingesetzt werden muss.

Irgendwelche Vorschläge, wie man das lösen kann?

59voto

Timur Punkte 11272

Aktualisierung 2022: Seit der Abfassung dieser Antwort im Jahr 2012 wurden alternative Lösungen geschaffen. Während die hier vorgestellte Git-Hook-Lösung noch gültig ist (mit ihren Vor- und Nachteilen), werden hier gute Antworten vorgestellt, die pluginbasierte oder sogar reine Maven-Lösungen präsentieren, die ich empfehlen würde zu berücksichtigen.


Tatsächlich kann Maven [Hinweis 2022: es sei denn, es werden dem Projekt einige Plugins hinzugefügt] die Version seines eigenen Projekts nicht in einem Durchlauf mit anderen Zielen ändern. Zusätzlich unterstützt reines Maven keine beliebigen Eigenschaften im -Tag. Daher ist eine separate Ausführung erforderlich, um ein Ziel auszuführen, das die Version des POMs ändert. Es gibt verschiedene Plugins, die dies tun können. Zum Beispiel: das Ziel versions:set vom Plugin versions - http://mojo.codehaus.org/versions-maven-plugin/set-mojo.html

Also könnten Sie es folgendermaßen ausführen:

mvn versions:set -DgenerateBackupPoms=false -DnewVersion=$branch-SNAPSHOT

wobei die Variable $branch den Namen des aktuellen Git-Branches enthalten muss; er kann mit git rev-parse extrahiert werden, wie folgt:

branch=$(git rev-parse --abbrev-ref HEAD)

Dennoch muss es irgendwie ausgeführt werden. Sie können es manuell tun, aber das ist umständlich. Daher ist meine Vermutung, dass die robusteste Lösung tatsächlich sein würde, dies von der Git-Seite aus anzugehen. Das heißt - ein Git-Hook. Hier ist der vollständige Git-post-checkout-Hook, der die Arbeit erledigen wird (der gleiche Code wie oben mit einigen Filtern, um den Hook nur auszuführen, wenn der Branch ausgecheckt wird, nicht nur die einzelnen Dateien):

#!/bin/bash

echo 'Ändere die Version in pom.xml-Dateien...'

# Überprüfen, ob der Checkout zum Auschecken eines Branchs war
if [ $3 != '1' ]
    then echo 'git checkout hat keinen Branch ausgecheckt - beende';exit
fi

# aktuellen Branchnamen abrufen
branch=$(git rev-parse --abbrev-ref HEAD)
version=$branch-SNAPSHOT

# führe das Maven-Versionen-Plugin aus, um die neue Version zu setzen
mvn versions:set -DgenerateBackupPoms=false -DnewVersion=$version

echo 'Version in pom.xml-Dateien zu $version geändert'

Fügen Sie diesen Inhalt in die Datei PROJECTDIR\.git\hooks\post-checkout ein. Beachten Sie, dass die Hook-Datei ausführbar sein sollte, um sie auszuführen (chmod +x post-checkout).

Ein paar Anmerkungen zum versions-Plugin - es ist ziemlich flexibel und unterstützt viele Optionen und hat einige andere Ziele, die je nach Projektstruktur hilfreich sein könnten (verwenden Sie Eltern-POMs oder nicht, haben Kinder ihre eigenen Versionen oder leiten sie von Eltern ab, usw.). Daher könnte der obige Hook leicht modifiziert werden, um Ihren spezifischen Fall zu unterstützen, indem andere Ziele des versions-Plugins verwendet oder zusätzliche Parameter angegeben werden.

Vorteile:

  • Robust
  • Es ist nicht erforderlich, etwas in den pom.xml-Dateien selbst zu ändern, damit dies funktioniert
  • Diese "Funktionalität" kann einfach durch Deaktivierung des Hooks deaktiviert werden (entfernen oder nicht ausführbar machen) - auch hier sind keine Änderungen in der pom.xml erforderlich

Nachteile:

  • Man kann andere nicht dazu zwingen, einen Hook zu verwenden - er sollte manuell installiert werden, nachdem das Repo geklont wurde (oder Sie können ein Skript bereitstellen, um den Hook zu installieren, wenn angenommene Git-Benutzer Angst haben, Dinge im .git-Verzeichnis zu berühren).

Eine ausführlichere Version des Bash-Skripts für den Git-Hook:

Hier ist die kompliziertere Version des Hooks, die nicht nur die Version auf den Branch-Namen setzt, sondern auch das Suffix der alten Version beibehält. Beispielsweise wird bei einer bereitgestellten alten Version master-1.0-SNAPSHOT das Wechseln zum Branch feature1 die Version des Projekts auf feature1-1.0-SNAPSHOT ändern. Dieses Bash-Skript leidet unter einigen Problemen (erfordert Branch-Namen ohne Bindestrichsymbol (-) im Namen und nimmt nur die Version des Wurzelpoms), kann jedoch eine Vorstellung davon vermitteln, wie der Hook erweitert werden kann: Mit einer Mischung aus mvn- und Bash-Befehlen können Sie viele Informationen im POM extrahieren und aktualisieren.

#!/bin/bash

echo 'Ändere die Version in pom.xml-Dateien...'

# Überprüfen, ob der Checkout zum Auschecken eines Branchs war
if [ $3 != '1' ]
    then echo 'git checkout hat keinen Branch ausgecheckt - beende';exit
fi

# aktuellen Branchnamen abrufen
branch=$(git rev-parse --abbrev-ref HEAD)

# aktuelle Version des obersten POM abrufen
current_version=$(mvn help:evaluate -Dexpression=project.version | grep -v '\[.*')

# Suffix der Version extrahieren
suffix=$(echo $current_version | cut -d \- -f 2)

# neue Version erstellen
version=$branch-$suffix

# führe das Maven-Versionen-Plugin aus, um die neue Version zu setzen
mvn versions:set -DgenerateBackupPoms=false -DnewVersion=$version

echo 'Version in pom.xml-Dateien zu $version geändert'

22voto

Es tut uns leid, diese Frage wiederzubeleben und sehr spät eine weitere Lösung zu posten, aber es ist tatsächlich möglich, die Maven-Version dynamisch zu ändern und einige Git-Funktionen zu nutzen, ähnlich wie es git describe tun würde.

Das Projekt, das dies ermöglicht, ist jgitver-maven-plugin (Haftungsausschluss; ich bin der Autor). Es verwendet jgitver, eine auf jgit basierende Bibliothek, um die Maven-Projektversion aus Git-Informationen abzuleiten.

Bildbeschreibung hier eingeben

Es ist sehr einfach als Maven-Erweiterung zu verwenden

...

              fr.brouillard.oss
              jgitver-maven-plugin
              0.1.0

     ...

...

Die Erweiterung kann auch als Plugin-Erweiterung verwendet werden und ermöglicht dann mehr Konfiguration, zum Beispiel, wenn Sie keine SNAPSHOTS verwenden möchten. Besuchen Sie die Projekt-Seite für eine Beschreibung der vollständigen Anwendungsszenarien.

Es gibt auch ein Gradle-Plugin, das mehr oder weniger dasselbe tut.


[Bearbeiten 1]: Antwort auf den Kommentar von Thorbjørn Ravn Andersen

Das Plugin ändert nicht die Original-Pom-Dateien oder die build.gradle-Dateien.
Für das Maven-Plugin werden Änderungen sowohl im Arbeitsspeicher im Maven-Objektmodell vorgenommen als auch in eine temporäre Datei im temporären Verzeichnis geschrieben. Die Berechnung basiert nur auf den Git-Metadaten (Tags, Commits, ...).
Diese Nichtänderung ermöglicht es, die Git-History nicht zu verschmutzen. Wenn Sie mit einem Git-Commit zufrieden sind, taggen Sie ihn mit git tag -a x.y.z und mvn deploy: das war's.
Die Version in Ihren Projektdateien ist jetzt nutzlos und kann beispielsweise auf 0 gesetzt werden.

Bis heute funktionieren aufgrund von IDEA-155733 nur die neuesten EAP-Versionen von IntelliJ mit dem Maven-Plugin.
Eclipse & Netbeans haben keine Probleme.


19voto

qoomon Punkte 3470

Haftungsausschluss: Ich bin der Autor

Meine maven-Kernerweiterung wird die Version virtuell basierend auf dem aktuellen Branch oder Tag festlegen. Sie können benutzerdefinierte Versionsschema-Muster konfigurieren, wie Sie möchten.

https://github.com/qoomon/maven-git-versioning-extension

Beispiel für das Versionsformat Bildbeschreibung hier eingeben

9voto

Ed Randall Punkte 6005

Von maven-3.5.0 an gibt es Unterstützung für die ${revision}, ${sha1} und ${changelist} Variablen innerhalb des version Tags. Diese Funktion kann ausreichend sein für Ihren Zweck, wenn Sie zum Beispiel den Git-Zweignamen in die Version für einen CI-Build-Job integrieren möchten. Siehe Maven CI Friendly Versions

Im Grunde genommen ersetzen Sie in Ihrer pom.xml die festgelegte Version durch:

${revision}${changelist}

Legen Sie Standardwerte für revision und changelist im Projektstammverzeichnis fest, indem Sie eine Datei .mvn/maven.config erstellen, die folgendes enthält:

-Drevision=1.2.3
-Dchangelist=-SNAPSHOT

Checken Sie diese Datei in die Versionskontrolle ein und aktualisieren Sie sie, wenn Sie die Projektrevision erhöhen.

In Ihrem CI-System können Sie dann die changelist Variable mit einer bereinigten Darstellung des Git-Zweignamens überschreiben, z.B.

# sed Regex ersetzt nicht-(alphanumerische, Punkt oder Strich) Zeichenfolgen durch einen Strich
BRANCHNAME=$(git rev-parse --abbrev-ref HEAD | sed -E -e 's@[^0-9A-Za-z.-]+@-@g')
mvn clean install -Dchangelist="-${BRANCHNAME}"

(Sie bevorzugen möglicherweise git symbolic-ref --short HEAD zum Abrufen des Zweignamens, YMMV)

Ihr von CI-System für den Zweig feature/branchname erstelltes Artefakt wird dann einen versionierten Branch-Suffix haben, wie z.B.:

yourproject-1.2.3-feature-branchname.jar

während Entwickler, die keine Überschreibungen verwenden, es immer noch als bauen werden:

yourproject-1.2.3-SNAPSHOT.jar

4voto

Wenn es ausreicht, den git-Tag und die Versionsinformation im Dateinamen des Artefakts festzulegen, können Sie den maven-jgit-buildnumber-plugin verwenden:

  ${artifactId}-${git.buildnumber}

      ru.concerteza.buildnumber
      maven-jgit-buildnumber-plugin
      1.2.7

          git-buildnumber

            extract-buildnumber

          prepare-package

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