maven-2 - introduccion - limpiar proyecto maven
Cómo obtener la versión del proyecto Maven a la línea de comando bash (20)
Debería ser más fácil ya que este error se corrigió en maven-help-plugin 3.0.0: MPH-99 Evaluate no tiene salida en modo silencioso .
Anterior Publiqué una pregunta sobre cómo cambiar la vección del proyecto de Maven desde la línea de comandos, lo que me llevó a un nuevo problema.
Anteriormente pude obtener el número de versión desde que la versión se almacenó como una propiedad fácil de analizar y analizar desde la línea de comandos (bash). Ahora que el elemento pom.xml se utiliza para esto, ya no es único, ya que todas las dependencias y quizás otras también lo usan. Creo que no hay forma de obtener el número de versión actual con un script bash sin herramientas externas para analizar xml o algún comando sed muy sensible al contexto.
La solución más limpia en mi opinión sería que Maven distribuya esta información de versión. Estaba pensando en escribir un plugin maven personalizado para recuperar diferentes propiedades, pero pensé en preguntar aquí primero.
Entonces, ¿hay alguna manera fácil de obtener el valor de ${project.version}
en la línea de comando? Gracias por adelantado.
Solución
Gracias por la ayuda. Tuve que hacer un cd
al directorio manualmente, pero eso se puede hacer fácilmente. En mi script bash tengo
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 } }''`
Lo que me da la versión actual que puedo avanzar. La expansión podría ser más simple, pero pensé que me gustaría lo más sólida posible, por lo que estoy satisfecho con la primera línea que comienza con un número y trato de manejarlo como un número de versión.
# 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/"
}
Y uso esto simplemente llamando
new_version=$(advance_version $version)
Espero que esto ayude a alguien.
El plugin de ayuda de Maven ya está proponiendo algo para esto:
help:evaluate
evalúa expresiones Maven dadas por el usuario en un modo interactivo.
Aquí es cómo lo invocaría en la línea de comando para obtener el ${project.version}
:
mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate /
-Dexpression=project.version
El pie de página de Maven es bastante estándar:
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.609s
[INFO] Finished at: Wed May 21 18:02:38 MSK 2014
[INFO] Final Memory: 17M/736M
[INFO] ------------------------------------------------------------------------
Entonces puedes usar el siguiente código:
> version=$(mvn help:evaluate -Dexpression=project.version | tail -8 | head -1)
> echo $version
Esto evitará la necesidad de agrupar las entradas de registro del resultado:
mvn -Dexec.executable=''echo'' -Dexec.args=''${project.version}'' --non-recursive exec:exec -q
Esto funcionó para mí, fuera de línea y sin depender de mvn:
VERSION=$(grep --max-count=1 ''<version>'' <your_path>/pom.xml | awk -F ''>'' ''{ print $2 }'' | awk -F ''<'' ''{ print $1 }'')
echo $VERSION
La respuesta principal es bastante basura, en mi opinión, tienes que usar un montón de grep para hackear la salida de la consola Maven. ¿Por qué no usar la herramienta adecuada para el trabajo? El uso de la sintaxis xpath es el mejor enfoque para recuperar el número de versión, ya que es el método previsto para acceder a una estructura de datos XML. La expresión siguiente está atravesando el pom usando el "nombre local" de los elementos, en otras palabras, ignorando las declaraciones del espacio de nombres que pueden estar o no presentes en el xml.
xmllint --xpath "//*[local-name()=''project'']/*[local-name()=''version'']/text()" pom.xml
La solución de Tom con el complemento Exec Maven es mucho mejor, pero aún más complicada de lo que debe ser. Para mí es tan simple como:
set -o errexit
MVN_VERSION=$(mvn -q /
-Dexec.executable="echo" /
-Dexec.args=''${project.version}'' /
--non-recursive /
org.codehaus.mojo:exec-maven-plugin:1.3.1:exec)
La solución todo en uno fácil de entender que genera la versión del proyecto maven y suprime los resultados externos de [INFO]
y los mensajes de Download
:
mvn -o org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | grep -v ''/[''
Lo mismo, pero dividido en dos líneas:
mvn -o org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate /
-Dexpression=project.version | grep -v ''/[''
Salidas: 4.3-SNAPSHOT
Entonces, usando su project.version
en un simple script bash:
projectVersion=`mvn -o org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | grep -v ''/[''`
cd "target/"$projectVersion"-build"
Otras soluciones en esta página no parecían combinar todos los trucos en uno.
Me encontré con casos secundarios cuando uso algunas de las otras respuestas aquí, así que aquí hay otra alternativa.
version=$(printf ''VER/t${project.version}'' | mvn help:evaluate | grep ''^VER'' | cut -f2)
O bien, puede que mvn
dé la respuesta (como sugieren la mayoría de las respuestas) o extrae la respuesta del pom.xml
. El único inconveniente del segundo enfoque es que puede extraer fácilmente el valor de la etiqueta <version/>
, pero solo tendrá sentido si es literal , es decir, no una propiedad de Maven. Elegí este enfoque de todos modos porque:
-
mvn
es muy verboso y simplemente no me gusta filtrar su salida. - Iniciar
mvn
es muy lento en comparación con la lectura depom.xml
. - Siempre uso valores literales en
<version/>
.
mvn-version
es un script de shell zsh
que usa xmlstarlet
para leer el pom.xml
e imprimir la versión del proyecto (si existe) o la versión del proyecto principal (si existe):
$ mvn-version .
1.0.0-SNAPSHOT
La ventaja es que es mucho más rápido que ejecutar 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 diferencia en mi máquina es mayor que dos órdenes de magnitud.
Observé algunas líneas Downloaded:
espurias en la salida que estaban rompiendo mi asignación original. Aquí está el filtro en el que me he adaptado; ¡Espero eso ayude!
version=$(mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | egrep -v ''^/[|Downloading:'' | tr -d '' /n'')
EDITAR
No está 100% seguro de por qué, pero al ejecutar esto a través de un script posterior a la construcción en Jenkins, el resultado salió como la [INFO]version
, por ejemplo, [INFO]0.3.2
.
Dejé la salida en un archivo y lo pasé por mi primer filtro directamente desde BASH, funciona bien ..., así que de nuevo, no estoy seguro de lo que está pasando en Jenkins.
Para obtenerlo al 100% en Jenkins, he agregado un filtro sed
seguimiento; aquí está mi último
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'')
EDITAR
Una última nota aquí ... descubrí que tr
todavía estaba dando como resultado /r/n0.3.2
(otra vez solo cuando se ejecuta a través de Jenkins). Cambió a awk
y el problema se ha ido! Mi resultado final de trabajo
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=''''
Recientemente desarrollé el complemento Release Candidate Maven que resuelve este problema exacto para que no tenga que recurrir a ningún script de shell hacky y analizar el resultado del maven-help-plugin
.
Por ejemplo, para imprimir la versión de su proyecto Maven en una terminal, ejecute:
mvn com.smartcodeltd:release-candidate-maven-plugin:LATEST:version
que da salida similar a maven-help-plugin
:
[INFO] Detected version: ''1.0.0-SNAPSHOT''
1.0.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
Sin embargo, también puede especificar un formato de salida arbitrario (para que la versión pueda ser recogida del registro por un servidor de CI como TeamCity ):
mvn com.smartcodeltd:release-candidate-maven-plugin:LATEST:version /
-DoutputTemplate="##teamcity[setParameter name=''env.PROJECT_VERSION'' value=''{{ version }}'']"
Lo que resulta en:
[INFO] Detected version: ''1.0.0-SNAPSHOT''
##teamcity[setParameter name=''env.PROJECT_VERSION'' value=''1.0.0-SNAPSHOT'']
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
Para guardar la salida en un archivo (para que un servidor de CI como Jenkins pueda usarlo ):
mvn com.smartcodeltd:release-candidate-maven-plugin:LATEST:version /
-DoutputTemplate="PROJECT_VERSION={{ version }}" /
-DoutputUri="file:///${project.basedir}/version.properties"
El archivo resultante de version.properties
se verá de la siguiente manera:
PROJECT_VERSION=1.0.0-SNAPSHOT
Además de todo lo anterior, Release Candidate también te permite configurar la versión de tu proyecto (que es algo que probablemente harías en tu servidor de CI) en función de la versión de API que hayas definido en tu POM.
Si desea ver un ejemplo de Release Candidate que se utiliza como parte del ciclo de vida de Maven, eche un vistazo al pom.xml
de mi otro proyecto de código abierto: Build Monitor for Jenkins .
Si no te importa escribir la versión en un archivo temporal, hay otra solución (sin grep / sed) que funciona bien para mí. ( EDITAR : vea la respuesta de rjrjr para una solución mucho más simple sin ningún problema temporal con el archivo)
Uso el complemento Exec Maven junto con el binario de echo
. A diferencia del Plugin de ayuda de Maven, el plugin Exec permite la redirección de salida a un archivo, que puede usarse para eludir grep / sed, e incluso permite analizar cosas extrañas como cadenas de versión de línea múltiple (con bloque CDATA en la etiqueta de versión). al menos hasta cierto punto.
#!/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"
Solo para el registro, es posible configurar el registro Simple SLF4J de Maven directamente en la línea de comando para generar solo lo que necesitamos configurando:
-
org.slf4j.simpleLogger.defaultLogLevel=WARN
y -
org.slf4j.simpleLogger.log.org.apache.maven.plugins.help=INFO
como se documenta en 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
Como resultado, uno puede ejecutar simplemente tail -1
y obtener:
$ 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
Tenga en cuenta que esto es de una sola línea. MAVEN_OPTS
se reescriben solo para esta ejecución particular de mvn
.
Una solución simple solo maven
mvn -q -N org.codehaus.mojo:exec-maven-plugin:1.3.1:exec /
-Dexec.executable=''echo'' /
-Dexec.args=''${project.version}''
Y para los puntos de bonificación analizados parte de una versión
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}''
VERSION=$(head -50 pom.xml | awk -F''>'' ''/SNAPSHOT/ {print $2}'' | awk -F''<'' ''{print $1}'')
Esto es lo que solía obtener el número de versión, pensé que habría habido una mejor manera de hacerlo.
mvn help:evaluate -Dexpression=project.version | sed -e 1h -e ''2,3{H;g}'' -e ''//[INFO/] BUILD SUCCESS/ q'' -e ''1,2d'' -e ''{N;D}'' | sed -e ''1q''
Solo estoy agregando una pequeña mejora en el filtro de sed
que he implementado recientemente para extraer project.version
de la salida de maven.
mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | grep -v ''/[''
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)"
Mientras tengas python 2.5 o superior, esto debería funcionar. Si tiene una versión más baja que esa, instale python-lxml
y cambie la importación a lxml.etree. Este método es rápido y no requiere descargar complementos adicionales. También funciona en archivos pom.xml malformados que no se validan con xmllint, como los que necesito analizar. Probado en Mac y Linux.