web-dev-qa-db-fra.com

Comment obtenir la version du projet Maven sur la ligne de commande bash

Auparavant, j’ai posé une question sur comment changer la version du projet Maven à partir de la ligne de commande , ce qui m’a amené à un nouveau problème.

Auparavant, je pouvais obtenir le numéro de version car celle-ci était stockée dans une propriété facile à grep et à analyser à partir de la ligne de commande (bash). Maintenant que l’élément pom.xml est utilisé pour cela, il n’est plus unique car toutes les dépendances et peut-être d’autres aussi l’utilisent. Je pense qu’il n’ya aucun moyen d’obtenir le numéro de version actuel avec un script bash sans outils externes pour analyser xml ou une commande sed très sensible au contexte.

La solution la plus propre à mon avis serait que Maven distribue ces informations de version. Je pensais écrire un plugin personnalisé maven pour récupérer différentes propriétés, mais je pensais que je demanderais d'abord ici.

Donc, existe-t-il un moyen simple d’obtenir la valeur de ${project.version} en ligne de commande? Merci d'avance.

Solution

Merci pour l'aide. Je devais cd dans le répertoire manuellement, mais cela peut être fait facilement. Dans mon script bash j'ai

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 } }'`

Ce qui me donne la version actuelle que je peux ensuite avancer. Grepping est peut-être plus simple, mais je pensais que je voudrais être aussi robuste que possible. Je suis donc satisfait de la première ligne qui commence par un numéro et essayez de le gérer comme un numéro de version.

# 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/"
}

Et j'utilise cela en appelant simplement

new_version=$(advance_version $version)

J'espère que ça aide quelqu'un.

145
mkko

Le Maven Help Plugin propose déjà quelque chose pour cela:

  • help:evaluate évalue les expressions Maven données par l'utilisateur en mode interactif.

Voici comment l'invoquer sur la ligne de commande pour obtenir le ${project.version}:

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

La solution de Tom avec le Exec Maven Plugin est bien meilleure, mais toujours plus compliquée qu'elle ne devrait l'être. Pour moi c'est aussi simple que:

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

À mon avis, la réponse la plus imparfaite est que j’ai du mal à utiliser des tas de grep pour pirater la sortie de la console maven. Pourquoi ne pas utiliser le bon outil pour le travail? L'utilisation de la syntaxe xpath est la meilleure approche pour extraire le numéro de version, car il s'agit de la méthode envisagée pour accéder à une structure de données XML. L'expression ci-dessous traverse le pom en utilisant le "nom local" des éléments, c'est-à-dire en ignorant les déclarations d'espace de noms qui peuvent être présentes ou non dans le xml.

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

Cela évitera d'avoir à rechercher des entrées de journal dans la sortie:

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

J'ai fait des recherches et trouvé ce qui suit:

  1. On a reproché à Maven de ne pas être facilement intégrable dans les scripts d’exploitation du système, car il ne suit pas certaines bonnes pratiques concernant les outils de la CLI. (ref: https://youtu.be/1ILEw6Qca3U?t=372 )

  2. Inspiré par l'assertion précédente, j'ai décidé de jeter un coup d'oeil sur le code source de maven ainsi que sur maven-help-plugin. Il semble qu'ils aient un peu corrigé le commutateur -q de maven (j'utilise la version 3.5.3), donc maintenant, si vous le transmettez, vous n'obtiendrez pas tous les trucs de journalisation ennuyants et non-sens qui empêchent d'utiliser maven. dans des scripts automatisés. Vous devriez donc pouvoir utiliser quelque chose comme ceci:

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

    Le problème est que cette commande n'imprime rien car, par défaut, le plug-in d'aide est transmis via le consignateur qui a été désactivé par le commutateur -q. (La dernière version disponible du plugin est la 3.1.0 publiée le 3 juin 2018)

  3. Karl Heinz Marbaise ( https://github.com/khmarbaise ) l'a corrigé en ajoutant un paramètre facultatif lui permettant de l'appeler de la manière suivante:

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

    La description du commit est disponible sur: ( 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)"

Tant que vous avez Python 2.5 ou supérieur, cela devrait fonctionner. Si vous avez une version inférieure, installez python-lxml et modifiez l'importation en lxml.etree. Cette méthode est rapide et ne nécessite pas le téléchargement de plugins supplémentaires. Cela fonctionne également sur les fichiers pom.xml malformés qui ne sont pas validés avec xmllint, comme ceux que je dois analyser. Testé sur Mac et Linux.

11
pdr

Je n'arrêtais pas de me heurter à certaines des autres réponses ici, alors voici une autre alternative.

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

Si cela ne vous dérange pas d'écrire la version dans un fichier temporaire, il existe une autre solution (sans grep/sed) qui fonctionne bien pour moi. (EDIT: voir la réponse de rjrjr pour une solution beaucoup plus simple, sans aucun problème de fichier temporaire)

J'utilise le Exec Maven Plugin avec le binaire echo. Contrairement au plug-in d'aide Maven, le plug-in Exec permet de rediriger la sortie vers un fichier, qui peut être utilisé pour contourner grep/sed, et permet même d'analyser des éléments étranges tels que des chaînes de version multilignes (avec CDATA block dans la version tag) au moins dans une certaine mesure.

#!/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

J'ai remarqué quelques lignes Downloaded: parasites apparaissant dans la sortie qui rompaient mon affectation d'origine. Voici le filtre sur lequel je me suis installé; J'espère que ça aide!

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

MODIFIER

Pas tout à fait sûr de savoir pourquoi, mais lors de l’exécution de celui-ci par le biais d’un script post-génération dans Jenkins, la sortie sortait sous la forme [INFO]version, par exemple. [INFO]0.3.2.

J'ai vidé la sortie dans un fichier et l'ai passé dans mon premier filtre directement à partir de BASH, cela fonctionne très bien .., donc encore une fois, incertain de ce qui se passe dans le pays de Jenkins.

Pour l'obtenir à 100% dans Jenkins, j'ai ajouté un filtre de suivi sed; voici mon dernier

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')

MODIFIER

Une dernière note ici .. J'ai découvert que tr était still, entraînant des choses comme /r/n0.3.2 (à nouveau uniquement lorsque vous exécutez via Jenkins). Passé à awk et le problème est parti! Mon dernier travail résultat

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

Pour rappel, il est possible de configurer la journalisation Simple SLF4J de Maven directement dans la ligne de commande pour ne générer que ce dont nous avons besoin en configurant:

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

documenté à http://www.slf4j.org/api/org/slf4j/impl/SimpleLogger.html

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

En conséquence, on peut exécuter simplement tail -1 et obtenir:

$ 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

Notez que ceci est un one-liner. MAVEN_OPTS sont en cours de réécriture uniquement pour cette exécution mvn particulière.

5
Stepan Vavra

Une simple solution maven

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

Et pour les points bonus analysés partie d'une version

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.

J'ai récemment développé le plug-in Release Candidate Maven qui résout ce problème afin que vous n'ayez pas à recourir à des scripts de hacky Shell ni à l'analyse du résultat du maven-help-plugin.

Par exemple, pour imprimer la version de votre projet Maven sur un terminal, exécutez:

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

ce qui donne une sortie similaire à maven-help-plugin:

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

Toutefois, vous pouvez également spécifier un format de sortie arbitraire (afin que la version puisse être extraite du journal par un serveur de CI, tel que TeamCity ):

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

Ce qui résulte en:

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

Pour enregistrer la sortie dans un fichier (afin qu'un serveur CI tel que Jenkins puisse l'utilise ):

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

Le fichier version.properties résultant ressemblera à ceci:

PROJECT_VERSION=1.0.0-SNAPSHOT

En plus de tout ce qui précède, Release Candidate vous permet également de définir la version de votre projet (ce que vous feriez probablement sur votre serveur CI) en fonction de la version de l'API que vous avez définie. dans votre POM.

Si vous souhaitez voir un exemple d'utilisation de Release Candidate dans le cadre du cycle de vie de Maven, consultez le pom.xml de mon autre projet open source - Build Monitor pour Jenkins .

4
Jan Molak

Solution tout-en-un facile à comprendre qui génère la version du projet maven et supprime les sorties superflues des messages [INFO] et Download:

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

Même chose, mais divisé en deux lignes:

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

Sorties: 4.3-SNAPSHOT

Donc, en utilisant votre project.version dans un script bash simple:

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

Les autres solutions sur cette page ne semblaient pas combiner toutes les astuces.

3
Peter Dietz

J'ai trouvé le juste équilibre pour moi. Après mvn package, le plugin maven-archiver crée target/maven-archiver/pom.properties avec un contenu comme celui-ci.

version=0.0.1-SNAPSHOT
groupId=somegroup
artifactId=someArtifact

et j'utilise bash juste pour l'exécuter

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

puis

echo $version
0.0.1-SNAPSHOT

Bien sûr, l’exécution de ce fichier n’est pas sûre du tout, mais l’exécution peut facilement être convertie en script Perl ou bash pour lire et définir la variable d’environnement à partir de ce fichier.

2
Vladimir I

Devrait être plus facile puisque ce bogue est corrigé dans maven-help-plugin 3.0.0: MPH-99 Evaluate n’a pas de sortie en mode silencieux .

2
mturra

Le plug-in Exec fonctionne sans analyse de la sortie, car celle-ci peut être redirigée dans un fichier et réinjectée dans l'environnement de travail via le plugin EnvInject:

 enter image description here

1
Ondřej Kmoch

Il y a aussi une option sans besoin Maven:

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

C'est la solution la plus propre j'ai trouvé:

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

Cela fonctionne bien sur tous les systèmes d'exploitation. Pas besoin d'outils externes!

Le -q supprime les messages verbeux. maven-help-plugin version 3.2.0 (et supérieur) a l'option forceStdout.

0
Manu M.

Soit vous avez mvn vous donnez la réponse (comme le suggèrent la plupart des réponses), soit vous extrayez la réponse du pom.xml. Le seul inconvénient de la seconde approche est que vous pouvez très facilement extraire la valeur de la balise <version/>, mais elle n’aura de sens que si c’est literal, c’est-à-dire pas une propriété Maven. J'ai choisi cette approche quand même parce que:

  • mvn est une façon de parler et je n'aime simplement pas filtrer sa sortie.
  • Démarrer mvn est très lent comparé à lire le pom.xml.
  • J'utilise toujours des valeurs littérales dans <version/>.

mvn-version est un script shell zsh qui utilise xmlstarlet pour lire le pom.xml et imprimer la version du projet (le cas échéant) ou la version du projet parent (le cas échéant):

$ mvn-version .
1.0.0-SNAPSHOT

L'avantage est que way est plus rapide que d'exécuter 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

La différence sur ma machine est supérieure à deux ordres de grandeur.

0

Cela a fonctionné pour moi, hors ligne et sans dépendre de MVN:

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