it-swarm.com.de

So erhalten Sie die Maven-Projektversion in der Bash-Befehlszeile

Vorher habe ich eine Frage zu wie kann ich die Maven-Projektversion von der Kommandozeile aus ändern die mich zu einem neuen Problem führen lassen.

Zuvor konnte ich die Versionsnummer abrufen, da die Version als Eigenschaft gespeichert wurde, die leicht von der Befehlszeile (Bash) aus grep und analysiert werden konnte. Nun, da das pom.xml-Element dafür verwendet wird, ist es nicht mehr eindeutig, da alle Abhängigkeiten und möglicherweise auch einige andere dies verwenden. Ich denke, es gibt keine Möglichkeit, die aktuelle Versionsnummer mit einem Bash-Skript without externen Tools für das Parsen von XML oder einen sehr kontextabhängigen sed-Befehl zu erhalten.

Die sauberste Lösung in meiner Meinung wäre, dass Maven diese Versionsinformationen austeilt. Ich dachte daran, ein benutzerdefiniertes Maven-Plugin zum Abrufen verschiedener Eigenschaften zu schreiben, aber ich dachte, ich würde zuerst hier nachfragen.

Gibt es eine einfache Möglichkeit, den Wert von ${project.version} in die Befehlszeile zu bekommen? Danke im Voraus.

Lösung

Danke für die Hilfe. Ich musste cd manuell in das Verzeichnis eintragen, aber das geht problemlos. In meinem Bash-Skript habe ich

version=`cd $project_loc && mvn org.Apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | sed -n -e '/^\[.*\]/ !{ /^[0-9]/ { p; q } }'`

Was mir die aktuelle Version gibt, kann ich dann weiterbringen. Grepping ist vielleicht einfacher, aber ich dachte, ich möchte so robust wie möglich sein. Daher bin ich mit der ersten Zeile, die mit einer Nummer beginnt, zufrieden und versuche, dies als Versionsnummer zu behandeln.

# Advances the last number of the given version string by one.
function advance_version () {
    local v=$1
    # Get the last number. First remove any suffixes (such as '-SNAPSHOT').
    local cleaned=`echo $v | sed -e 's/[^0-9][^0-9]*$//'`
    local last_num=`echo $cleaned | sed -e 's/[0-9]*\.//g'`
    local next_num=$(($last_num+1))
    # Finally replace the last number in version string with the new one.
    echo $v | sed -e "s/[0-9][0-9]*\([^0-9]*\)$/$next_num/"
}

Und ich benutze das, indem ich einfach anrufe

new_version=$(advance_version $version)

Hoffe das hilft jemandem.

145
mkko

Das Maven Help Plugin schlägt irgendwie schon etwas dafür vor:

  • help:evaluate wertet die vom Benutzer angegebenen Maven-Ausdrücke in einem interaktiven Modus aus.

So würden Sie es in der Befehlszeile aufrufen, um den ${project.version} zu erhalten:

mvn org.Apache.maven.plugins:maven-help-plugin:2.1.1:evaluate \
    -Dexpression=project.version
177
Pascal Thivent

Toms Lösung mit dem Exec Maven Plugin ist viel besser, aber immer noch komplizierter als es sein muss. Für mich ist es so einfach wie:

MVN_VERSION=$(mvn -q \
    -Dexec.executable=echo \
    -Dexec.args='${project.version}' \
    --non-recursive \
    exec:exec)
151
rjrjr
mvn org.Apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | grep -v '\['
45
user1712021

Die beste Antwort ist meiner Meinung nach ziemlich müllig, man muss ein paar Bündel grep verwenden, um die Ausgabe der Maven-Konsole herauszuhacken. Warum nicht das richtige Werkzeug für den Job verwenden? Die Verwendung der xpath-Syntax ist der beste Weg, um die Versionsnummer abzurufen, da dies die beabsichtigte Methode für den Zugriff auf eine XML-Datenstruktur ist. Der folgende Ausdruck durchläuft den Pom unter Verwendung des "lokalen Namens" der Elemente, dh die Namespace-Deklarationen werden ignoriert, die in der XML-Datei enthalten sein können oder nicht.

xmllint --xpath "//*[local-name()='project']/*[local-name()='version']/text()" pom.xml
30
lukeforehand

Auf diese Weise wird vermieden, dass Protokolleinträge aus der Ausgabe entfernt werden müssen:

mvn -Dexec.executable='echo' -Dexec.args='${project.version}' --non-recursive exec:exec -q
23
Jose Alban

Ich habe etwas recherchiert und folgendes gefunden:

  1. Maven wurde vorgeworfen, es sei nicht einfach, in Systemoperationsskripts integriert zu werden, da es einigen guten Praktiken in Bezug auf CLI-Tools nicht folgt. (ref: https://youtu.be/1ILEw6Qca3U?t=372 )

  2. Inspiriert von der vorherigen Behauptung beschloss ich, einen Blick auf den Quellcode von maven sowie auf das maven-help-plugin zu werfen. Es scheint, dass sie den -q-Schalter des maven ein wenig korrigiert haben (ich verwende Version 3.5.3). Wenn Sie ihn also übergeben, werden Sie nicht all die lästigen, unsinnigen Protokollierungssachen erhalten, die die Verwendung von maven verhindern in automatisierten Skripten. Du solltest also so etwas verwenden können:

    mvn help:evaluate -Dexpression=project.version -q
    

    Das Problem ist, dass dieser Befehl nichts ausgibt, da das Hilfe-Plugin standardmäßig über den Logger ausgibt, der durch den Schalter -q stummgeschaltet wurde. (Die neueste verfügbare Version des Plugins ist 3.1.0 und wurde am 3. Juni 2018 veröffentlicht.)

  3. Karl Heinz Marbaise ( https://github.com/khmarbaise ) korrigierte dies durch Hinzufügen eines optionalen Parameters, mit dem Sie ihn folgendermaßen aufrufen können:

    mvn help:evaluate -Dexpression=project.version -q -DforceStdout
    

    Die Commit-Beschreibung ist verfügbar unter: ( https://github.com/Apache/maven-help-plugin/commit/316656983d780c04031bbadd97d4ab245c84d014 )

18
montoyaedu
python -c "import xml.etree.ElementTree as ET; \
  print(ET.parse(open('pom.xml')).getroot().find( \
  '{http://maven.Apache.org/POM/4.0.0}version').text)"

Solange Sie Python 2.5 oder höher haben, sollte dies funktionieren. Wenn Sie eine niedrigere Version als diese haben, installieren Sie python-lxml und ändern Sie den Import in lxml.etree. Diese Methode ist schnell und erfordert keine zusätzlichen Plugins. Es funktioniert auch mit fehlerhaften pom.xml-Dateien, die nicht mit xmllint validiert werden, wie die, die ich analysieren muss. Getestet auf Mac und Linux.

11
pdr

Ich habe immer wieder auf Nebenfälle gestoßen, als ich einige der anderen Antworten hier verwendet habe, also hier noch eine Alternative.

version=$(printf 'VER\t${project.version}' | mvn help:evaluate | grep '^VER' | cut -f2)
8
slow

Wenn Sie die Version nicht in eine temporäre Datei schreiben möchten, gibt es eine andere Lösung (ohne grep/sed), die für mich gut funktioniert. (EDIT: siehe Antwort von rjrjr für eine viel einfachere Lösung ohne zeitweilige Dateiprobleme)

Ich benutze das Exec Maven Plugin zusammen mit der echo-Binärdatei. Im Gegensatz zum Maven-Hilfe-Plugin ermöglicht das Exec-Plugin die Ausgabeumleitung in eine Datei, mit der grep/sed umgangen werden kann, und es ist sogar möglich, seltsame Dinge wie mehrzeilige Versionszeichenfolgen (mit CDATA-Block im Versions-Tag) zu analysieren. zumindest bis zu einem gewissen Grad.

#!/usr/bin/env sh

MVN_VERSION=""
VERSION_FILE=$( mktemp mvn_project_version_XXXXX )
trap "rm -f -- \"$VERSION_FILE\"" INT EXIT

mvn -Dexec.executable="echo" \
    -Dexec.args='${project.version}' \
    -Dexec.outputFile="$VERSION_FILE" \
    --non-recursive \
    --batch-mode \
    org.codehaus.mojo:exec-maven-plugin:1.3.1:exec > /dev/null 2>&1 ||
    { echo "Maven invocation failed!" 1>&2; exit 1; }

# if you just care about the first line of the version, which will be
# sufficent for pretty much every use case I can imagine, you can use
# the read builtin
[ -s "$VERSION_FILE" ] && read -r MVN_VERSION < "$VERSION_FILE"

# Otherwise, you could use cat.
# Note that this still has issues when there are leading whitespaces
# in the multiline version string
#MVN_VERSION=$( cat "$VERSION_FILE" )

printf "Maven project version: %s\n" "$MVN_VERSION"
7
Tom

Ich habe einige falsche Downloaded:-Zeilen in der Ausgabe festgestellt, die meine ursprüngliche Zuweisung brachen. Hier ist der Filter, für den ich mich entschieden habe; ich hoffe es hilft!

version=$(mvn org.Apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | egrep -v '^\[|Downloading:' | tr -d ' \n')

EDIT

Nicht ganz sicher, warum, aber wenn dies durch ein Post-Build-Skript in Jenkins ausgeführt wurde, wurde die Ausgabe als [INFO]version ausgegeben, z. [INFO]0.3.2.

Ich legte die Ausgabe in eine Datei ab und ließ sie durch meinen ersten Filter direkt von BASH laufen, es funktioniert gut .., also nochmal unsicher, was in Jenkins Land los ist.

Um es zu 100% in Jenkins zu bekommen, habe ich einen Folgefilter sed hinzugefügt; hier ist meine neueste

version=$(mvn org.Apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | egrep -v '^\[|Downloading:' | tr -d ' \n' | sed -E 's/\[.*\]//g')

EDIT

Ein letzter Hinweis hier .. Ich fand heraus, dass trnoch war, was zu /r/n0.3.2 führte (wieder nur bei Jenkins). Umstellung auf awk und das Problem ist weg! Mein letztes Arbeit Ergebnis

mvn org.Apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version \
| egrep -v '^\[|Downloading:' | sed 's/[^0-9\.]//g' | awk 1 ORS=''
5
quickshiftin

Nur für die Aufzeichnung ist es möglich, die Simple SLF4J-Protokollierung von Maven direkt in der Befehlszeile so zu konfigurieren, dass nur das ausgegeben wird, was wir benötigen:

  • org.slf4j.simpleLogger.defaultLogLevel=WARN und
  • org.slf4j.simpleLogger.log.org.Apache.maven.plugins.help=INFO

wie unter http://www.slf4j.org/api/org/slf4j/impl/SimpleLogger.html dokumentiert

MAVEN_OPTS="\
-Dorg.slf4j.simpleLogger.defaultLogLevel=WARN \
-Dorg.slf4j.simpleLogger.log.org.Apache.maven.plugins.help=INFO" \
mvn help:evaluate -o -Dexpression=project.version

Als Ergebnis kann man einfach tail -1 ausführen und erhalten:

$ MAVEN_OPTS="\
-Dorg.slf4j.simpleLogger.defaultLogLevel=WARN \
-Dorg.slf4j.simpleLogger.log.org.Apache.maven.plugins.help=INFO" \
mvn help:evaluate -o -Dexpression=project.version | tail -1

1.0.0-SNAPSHOT

Beachten Sie, dass dies ein Einzeiler ist. MAVEN_OPTS wird nur für diese bestimmte mvn-Ausführung umgeschrieben.

5
Stepan Vavra

Eine einfache Lösung, die nur für Maven geeignet ist

mvn -q -N org.codehaus.mojo:exec-maven-plugin:1.3.1:exec \
    -Dexec.executable='echo' \
    -Dexec.args='${project.version}'

Und für Bonuspunkte wird ein Teil einer Version analysiert

mvn -q -N org.codehaus.mojo:build-helper-maven-plugin:3.0.0:parse-version \
    org.codehaus.mojo:exec-maven-plugin:1.3.1:exec \
    -Dexec.executable='echo' \
    -Dexec.args='${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}'
4
Jakob O.

Ich habe kürzlich das Release Candidate Maven-Plugin entwickelt, das genau dieses Problem löst, sodass Sie nicht auf hackige Shell-Skripte zurückgreifen und die Ausgabe des maven-help-plugin.

Um beispielsweise die Version Ihres Maven-Projekts auf einem Terminal auszudrucken, führen Sie Folgendes aus:

mvn com.smartcodeltd:release-candidate-maven-plugin:LATEST:version

was eine Ausgabe ähnlich der von maven-help-plugin ergibt:

[INFO] Detected version: '1.0.0-SNAPSHOT'
1.0.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

Sie können jedoch auch ein beliebiges Ausgabeformat ​​angeben (damit die Version von einem CI-Server wie TeamCity aus dem Protokoll abgerufen werden kann):

mvn com.smartcodeltd:release-candidate-maven-plugin:LATEST:version \
   -DoutputTemplate="##teamcity[setParameter name='env.PROJECT_VERSION' value='{{ version }}']"

Was in ... endet:

[INFO] Detected version: '1.0.0-SNAPSHOT'
##teamcity[setParameter name='env.PROJECT_VERSION' value='1.0.0-SNAPSHOT']
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

So speichern Sie die Ausgabe in einer Datei (damit ein CI-Server wie Jenkinsverwenden ):

mvn com.smartcodeltd:release-candidate-maven-plugin:LATEST:version \
   -DoutputTemplate="PROJECT_VERSION={{ version }}" \
   -DoutputUri="file://\${project.basedir}/version.properties"

Die resultierende Datei version.properties Sieht folgendermaßen aus:

PROJECT_VERSION=1.0.0-SNAPSHOT

Darüber hinaus können Sie mit Release Candidate auch die Version festlegen Ihres Projekts (was Sie wahrscheinlich auf Ihrem CI-Server tun würden) basierend auf dem API-Version, die Sie in Ihrem POM definiert haben.

Wenn Sie ein Beispiel für die Verwendung von Release Candidate als Teil des Maven-Lebenszyklus sehen möchten, sehen Sie sich pom.xml In meinem anderen Open-Source-Projekt an - Build Monitor for Jenkins =.

4
Jan Molak

Die leicht verständliche All-in-One-Lösung, die die Maven-Projektversion ausgibt und überflüssige Ausgaben von [INFO]- und Download-Meldungen unterdrückt:

mvn -o org.Apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | grep -v '\['

Gleiche Sache, aber auf zwei Zeilen aufgeteilt:

mvn -o org.Apache.maven.plugins:maven-help-plugin:2.1.1:evaluate \
      -Dexpression=project.version | grep -v '\['

Ausgaben: 4.3-SNAPSHOT

Verwenden Sie also Ihren project.version in einem einfachen Bash-Skript:

projectVersion=`mvn -o org.Apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | grep -v '\['`
cd "target/"$projectVersion"-build"

Andere Lösungen auf dieser Seite schienen nicht alle Tricks zu kombinieren.

3
Peter Dietz

Ich habe das richtige Gleichgewicht für mich gefunden. Nach mvn package erstellt das maven-archiver-Plugin target/maven-archiver/pom.properties mit einem solchen Inhalt

version=0.0.1-SNAPSHOT
groupId=somegroup
artifactId=someArtifact

und ich benutze bash, nur um es auszuführen

. ./target/maven-archiver/pom.properties

dann

echo $version
0.0.1-SNAPSHOT

Natürlich ist dies nicht sicher, um diese Datei auszuführen, aber die Ausführung kann leicht in Perl- oder Bash-Skript konvertiert werden, um Umgebungsvariable aus dieser Datei zu lesen und festzulegen.

2
Vladimir I

Sollte einfacher sein, da dieser Fehler in maven-help-plugin 3.0.0 behoben wurde: MPH-99 Evaluate hat keine Ausgabe im stillen Modus .

2
mturra

Exec-Plugin funktioniert ohne Analyse von Ausgaben, da die Ausgabe in eine Datei umgeleitet und über das EnvInject-Plugin wieder in die Jobumgebung eingefügt werden kann:

 enter image description here

1
Ondřej Kmoch

Es gibt auch eine Option ohne Maven:

grep -oPm1 "(?<=<version>)[^<]+" "pom.xml"
0
Michal Šípek

Dies ist die sauberste Lösung ich fand:

mvn org.Apache.maven.plugins:maven-help-plugin:3.2.0:evaluate -Dexpression=project.version -q -DforceStdout

Es funktioniert gut auf allen Betriebssystemen. Kein externes Werkzeug erforderlich!

Der -q unterdrückt ausführliche Nachrichten. maven-help-plugin version 3.2.0 (und höher) hat die Option forceStdout.

0
Manu M.

Entweder haben Sie mvn die Antwort (wie die meisten Antworten vermuten lassen), oder Sie extrahieren die Antwort aus dem pom.xml. Der einzige Nachteil des zweiten Ansatzes besteht darin, dass Sie den Wert des <version/>-Tags sehr leicht extrahieren können. Er ist jedoch nur dann sinnvoll, wenn er literal ist, also keine Maven-Eigenschaft. Ich habe diesen Ansatz trotzdem gewählt, weil:

  • mvn ist viel zu viel und ich mag es einfach nicht, die Ausgabe zu filtern.
  • Das Starten von mvn ist im Vergleich zum Lesen von pom.xml sehr langsam.
  • In <version/> verwende ich immer wörtliche Werte.

mvn-version ist ein zsh Shell-Skript, das xmlstarlet verwendet, um den pom.xml zu lesen und die Version des Projekts (falls vorhanden) oder die Version des übergeordneten Projekts (falls vorhanden) zu drucken:

$ mvn-version .
1.0.0-SNAPSHOT

Der Vorteil ist, dass way schneller ist als mvn:

$ time mvn-version .
1.1.0-SNAPSHOT
mvn-version .  0.01s user 0.01s system 75% cpu 0.019 total

$ time mvn org.Apache.maven.plugins:maven-help-plugin:2.1.1:evaluate \
> -Dexpression=project.version
mvn org.Apache.maven.plugins:maven-help-plugin:2.1.1:evaluate   4.17s user 0.21s system 240% cpu 1.823 total

Der Unterschied meiner Maschine ist größer als zwei Größenordnungen.

Das funktionierte für mich offline und ohne Abhängigkeit von mvn:

VERSION=$(grep --max-count=1 '<version>' <your_path>/pom.xml | awk -F '>' '{ print $2 }' | awk -F '<' '{ print $1 }')
echo $VERSION
0
George