java - central - ¿Cómo le digo a Maven que use la última versión de una dependencia?
maven versions (12)
¿Es posible que dependa de versiones de desarrollo que obviamente cambian mucho durante el desarrollo?
En lugar de incrementar la versión de las versiones de desarrollo, puede usar una versión de instantánea que sobrescriba cuando sea necesario, lo que significa que no tendría que cambiar la etiqueta de la versión en cada cambio menor. Algo así como 1.0-SNAPSHOT ...
Pero tal vez usted está tratando de lograr otra cosa;)
En Maven, las dependencias se configuran así:
<dependency>
<groupId>wonderful-inc</groupId>
<artifactId>dream-library</artifactId>
<version>1.2.3</version>
</dependency>
Ahora, si está trabajando con bibliotecas que tienen lanzamientos frecuentes, actualizar constantemente la etiqueta <version> puede ser un poco molesto. ¿Hay alguna manera de decirle a Maven que siempre use la última versión disponible (desde el repositorio)?
A diferencia de otros, creo que hay muchas razones por las que siempre querrás la última versión. Particularmente si está haciendo una implementación continua (a veces tenemos como 5 versiones en un día) y no queremos hacer un proyecto de múltiples módulos.
Lo que hago es hacer que Hudson / Jenkins haga lo siguiente para cada compilación:
mvn clean versions:use-latest-versions scm:checkin deploy -Dmessage="update versions" -DperformRelease=true
Es decir, uso el complemento de versiones y el complemento de scm para actualizar las dependencias y luego registrarlas en el control de origen. Sí, dejé que mi CI realice los registros de SCM (lo que debe hacer de todos modos para el complemento de versión de Maven).
Querrá configurar el complemento de versiones para actualizar solo lo que desea:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>versions-maven-plugin</artifactId>
<version>1.2</version>
<configuration>
<includesList>com.snaphop</includesList>
<generateBackupPoms>false</generateBackupPoms>
<allowSnapshots>true</allowSnapshots>
</configuration>
</plugin>
Utilizo el complemento de lanzamiento para hacer el lanzamiento que se encarga de -SNAPSHOT y valida que hay una versión de lanzamiento de -SNAPSHOT (que es importante).
Si hace lo que hago, obtendrá la última versión para todas las compilaciones de instantáneas y la última versión de lanzamiento para las compilaciones de lanzamiento. Tus construcciones también serán reproducibles.
Actualizar
Noté algunos comentarios pidiendo algunos detalles específicos de este flujo de trabajo. Diré que ya no usamos este método y la gran razón por la cual el complemento de las versiones de Maven es defectuoso y en general es inherentemente defectuoso.
Es defectuoso porque al ejecutar el complemento de versiones para ajustar las versiones, todas las versiones existentes deben existir para que el pom se ejecute correctamente. Es decir, el complemento de versiones no puede actualizarse a la última versión de nada si no puede encontrar la versión referenciada en el pom. En realidad, esto es bastante molesto, ya que a menudo limpiamos versiones antiguas por razones de espacio en el disco.
Realmente necesita una herramienta independiente de maven para ajustar las versiones (para que no dependa del archivo pom para que se ejecute correctamente). He escrito una herramienta así en el lenguaje humilde que es Bash. El script actualizará las versiones como el complemento de la versión y verificará el pom nuevamente en el control de fuente. También funciona como 100 veces más rápido que el complemento de las versiones mvn. Desafortunadamente, no está escrito de una manera para uso público, pero si la gente está interesada, podría hacerlo así y ponerlo en una esencia o github.
Volviendo al flujo de trabajo, como algunos comentarios preguntaron acerca de que esto es lo que hacemos:
- Tenemos alrededor de 20 proyectos en sus propios repositorios con sus propios trabajos en jenkins.
- Cuando lanzamos el complemento de liberación maven se utiliza. El flujo de trabajo de eso está cubierto en la documentación del complemento. El plugin de lanzamiento de Maven tipo de chupa (y estoy siendo amable) pero funciona. Un día planeamos reemplazar este método con algo más óptimo.
- Cuando se lance uno de los proyectos, jenkins ejecuta un trabajo especial, llamaremos actualización a todas las versiones (el hecho de que jenkins sepa que es un lanzamiento es una forma complicada en parte porque el complemento de lanzamiento de maven jenkins también es bastante malo).
- El trabajo de actualización de todas las versiones conoce todos los 20 proyectos. En realidad, es un pom agregador para ser específico con todos los proyectos en la sección de módulos en orden de dependencia. Jenkins ejecuta nuestro mágico groovy / bash foo que hará que todos los proyectos actualicen las versiones a la última versión y luego verifiquen a los poms (de nuevo, en orden de dependencia según la sección de módulos).
- Para cada proyecto, si el pom ha cambiado (debido a un cambio de versión en alguna dependencia), se registra e inmediatamente hacemos ping a jenkins para ejecutar el trabajo correspondiente para ese proyecto (esto es para preservar el orden de dependencia de compilación de lo contrario, usted está a merced del programador de encuestas SCM).
En este punto, opino que es bueno tener el lanzamiento y la versión automática de una herramienta separada de su versión general de todos modos.
Ahora puede pensar que Maven es una especie de mierda debido a los problemas enumerados anteriormente, pero esto sería bastante difícil con una herramienta de compilación que no tiene una sintaxis declarable fácil de analizar (también conocida como XML).
De hecho, agregamos atributos XML personalizados a través de espacios de nombres para ayudar a sugerir scripts de bash / groovy (por ejemplo, no actualice esta versión).
A veces no desea utilizar rangos de versión, porque parece que son "lentos" para resolver sus dependencias, especialmente cuando hay una entrega continua en su lugar y hay toneladas de versiones, principalmente durante el desarrollo pesado.
Una solución sería utilizar las maven-versions-plugin . Por ejemplo, puede declarar una propiedad:
<properties>
<myname.version>1.1.1</myname.version>
</properties>
y agrega las versiones-maven-plugin a tu archivo pom:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>versions-maven-plugin</artifactId>
<version>2.3</version>
<configuration>
<properties>
<property>
<name>myname.version</name>
<dependencies>
<dependency>
<groupId>group-id</groupId>
<artifactId>artifact-id</artifactId>
<version>latest</version>
</dependency>
</dependencies>
</property>
</properties>
</configuration>
</plugin>
</plugins>
</build>
Luego, para actualizar la dependencia, tienes que ejecutar los objetivos:
mvn versions:update-properties validate
Si hay una versión más reciente que 1.1.1, le dirá:
[INFO] Updated ${myname.version} from 1.1.1 to 1.3.2
Ahora sé que este tema es antiguo, pero al leer la pregunta y la respuesta proporcionada por el OP, parece que el maven-versions-plugin podría haber sido una mejor respuesta a su pregunta:
En particular los siguientes objetivos podrían ser de utilidad:
- versiones: utilizar las últimas versiones busca el pom para todas las versiones que han sido más nuevas y las reemplaza con la última versión.
- Versiones: use-latest-releases busca en pom todas las versiones que no sean SNAPSHOT que hayan sido más nuevas y las reemplaza con la última versión.
- versiones: las propiedades de actualización actualizan las propiedades definidas en un proyecto para que se correspondan con la última versión disponible de dependencias específicas. Esto puede ser útil si un conjunto de dependencias debe estar bloqueado en una versión.
Los siguientes otros objetivos también se proporcionan:
- Versiones: mostrar actualizaciones de dependencia escanea las dependencias de un proyecto y genera un informe de las dependencias que tienen versiones más nuevas disponibles.
- versiones: mostrar-complemento-actualizaciones escanea los complementos de un proyecto y produce un informe de los complementos que tienen versiones más nuevas disponibles.
- versiones: update-parent actualiza la sección principal de un proyecto para que haga referencia a la versión más reciente disponible. Por ejemplo, si utiliza una POM raíz corporativa, este objetivo puede ser útil si necesita asegurarse de que está utilizando la última versión de la POM raíz corporativa.
- Versiones: update-child-modules actualiza la sección principal de los módulos secundarios de un proyecto para que la versión coincida con la versión del proyecto actual. Por ejemplo, si tiene un pom agregador que también es el principal para los proyectos que agrega y las versiones secundarias y secundarias no están sincronizadas, este mojo puede ayudar a corregir las versiones de los módulos secundarios. (Tenga en cuenta que es posible que deba invocar a Maven con la opción -N para ejecutar este objetivo si su proyecto se rompe tan gravemente que no se puede compilar debido a la falta de coincidencia de la versión).
- versiones: lock-snapshots busca en el pom todas las versiones de -SNAPSHOT y las reemplaza con la versión actual de la marca de tiempo -SNAPSHOT, por ejemplo, -20090327.172306-4
- versiones: unlock-snapshots busca en pom todas las versiones de instantáneas bloqueadas de marca de tiempo y las reemplaza con -SNAPSHOT.
- versiones: resolver-rangos encuentra dependencias usando rangos de versión y resuelve el rango a la versión específica que se está utilizando.
- Versiones: use-releases busca en pom todas las versiones de -SNAPSHOT que se han lanzado y las reemplaza con la versión de lanzamiento correspondiente.
- Versiones: use-next-releases busca en pom todas las versiones que no sean SNAPSHOT que hayan sido más nuevas y las reemplaza con la siguiente versión.
- Versiones: use-next-translations busca en el pom todas las versiones que han sido más nuevas y las reemplaza por la siguiente.
- versiones: commit elimina los archivos pom.xml.versionsBackup. Forma la mitad de la incorporada "SCM del hombre pobre".
- versiones: revert restaura los archivos pom.xml de los archivos pom.xml.versionsBackup. Forma la mitad de la incorporada "SCM del hombre pobre".
Solo pensé que lo incluiría para cualquier referencia futura.
En el momento en que se planteó esta pregunta, había algunos problemas con los rangos de versión en maven, pero estos se han resuelto en versiones más nuevas de maven. Este artículo captura muy bien cómo funcionan los rangos de versión y las mejores prácticas para comprender mejor cómo entiende maven las versiones: https://docs.oracle.com/middleware/1212/core/MAVEN/maven_version.htm#MAVEN8855
La sintaxis de las dependencias se encuentra en la documentación de la Especificación de requisitos de versiones de dependencia . Aquí está es para completar:
El elemento de
version
las dependencias define los requisitos de la versión, que se utiliza para calcular la versión de dependencia efectiva. Los requisitos de versión tienen la siguiente sintaxis:
1.0
: requisito "suave" en 1.0 (solo una recomendación, si coincide con todos los otros rangos para la dependencia)[1.0]
: Requisito "duro" en 1.0(,1.0]
: x <= 1.0[1.2,1.3]
: 1.2 <= x <= 1.3[1.0,2.0)
: 1.0 <= x <2.0[1.5,)
: x> = 1.5(,1.0],[1.2,)
: x <= 1.0 o x> = 1.2; varios conjuntos están separados por comas(,1.1),(1.1,)
: esto excluye 1.1 (por ejemplo, si se sabe que no funciona en combinación con esta biblioteca)
En su caso, podría hacer algo como <version>[1.2.3,)</version>
La verdad es que incluso en 3.x todavía funciona, sorprendentemente los proyectos se construyen y despliegan. Pero la palabra clave LATEST / RELEASE que causa problemas en m2e y eclipse por todos lados, TAMBIÉN los proyectos depende de la dependencia que se implementó a través de LATEST / RELEASE no reconoce la versión.
También causará problemas si intenta definir la versión como propiedad y hacer referencia a ella en otro lugar.
Así que la conclusión es usar las maven-versions-plugin si puedes.
MI solución en Maven 3.5.4, usa nexus, en eclipse:
<dependency>
<groupId>yilin.sheng</groupId>
<artifactId>webspherecore</artifactId>
<version>LATEST</version>
</dependency>
luego en eclipse: atl + F5
, y elija la force update of snapshots/release
esto funciona para mi.
Por favor, eche un vistazo a esta página (sección "Rangos de versiones de dependencia"). Lo que podrías querer hacer es algo como
<version>[1.2.3,)</version>
Estos rangos de versión se implementan en Maven2.
Quien use LATEST, siempre asegúrese de tener -U, de lo contrario, no se obtendrá la última instantánea.
mvn -U dependency:copy -Dartifact=com.foo:my-foo:LATEST
// pull the latest snapshot for my-foo from all repositories
Si desea que Maven use la última versión de una dependencia, entonces puede usar maven-versions-plugin y cómo usar este plugin, Tim ya ha dado una buena respuesta, siga su answer .
Pero como desarrollador, no recomendaré este tipo de prácticas. ¿POR QUÉ?
Respuesta a por qué ya está dada por Pascal Thivent en el comentario de la pregunta.
Realmente no recomiendo esta práctica (ni el uso de rangos de versión) por la reproducibilidad de la compilación. Una construcción que comienza a fallar repentinamente por una razón desconocida es mucho más molesta que actualizar manualmente un número de versión.
Recomendaré este tipo de práctica:
<properties>
<spring.version>3.1.2.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
Es fácil de mantener y fácil de depurar. Puede actualizar su POM en ningún momento.
NOTA:
Esta respuesta se aplica a Maven 2 solamente! Los mencionados LATEST
y RELEASE
metaversiones han sido eliminados en Maven 3 "por el bien de construcciones reproducibles" , hace más de 6 años. Consulte esta solución compatible con Maven 3 .
Si siempre desea utilizar la versión más reciente, Maven tiene dos palabras clave que puede usar como alternativa a los rangos de versión. Debe usar estas opciones con cuidado ya que ya no tiene el control de los complementos / dependencias que está usando.
Cuando dependes de un complemento o una dependencia, puedes usar el valor de una versión de LATEST o RELEASE. ÚLTIMO se refiere a la última versión publicada o instantánea de un artefacto en particular, el artefacto implementado más recientemente en un repositorio en particular. RELEASE se refiere a la última versión que no es de instantánea en el repositorio. En general, no es una mejor práctica diseñar software que dependa de una versión no específica de un artefacto. Si está desarrollando un software, es posible que desee utilizar RELEASE o LATEST como una conveniencia para que no tenga que actualizar los números de versión cuando se publique una nueva versión de una biblioteca de terceros. Cuando libera software, siempre debe asegurarse de que su proyecto dependa de versiones específicas para reducir las posibilidades de que su compilación o su proyecto se vean afectados por una versión de software que no esté bajo su control. Use ÚLTIMO y LIBERAR con precaución, si es que lo hace.
Vea la sección de Sintaxis de POM del libro de Maven para más detalles. O vea este documento en Rangos de versiones de dependencia , donde:
- Un corchete (
[
&]
) significa "cerrado" (incluido). - Un paréntesis (
(
&)
) significa "abierto" (exclusivo).
Aquí hay un ejemplo que ilustra las diversas opciones. En el repositorio de Maven, com.foo:my-foo tiene los siguientes metadatos:
<?xml version="1.0" encoding="UTF-8"?><metadata>
<groupId>com.foo</groupId>
<artifactId>my-foo</artifactId>
<version>2.0.0</version>
<versioning>
<release>1.1.1</release>
<versions>
<version>1.0</version>
<version>1.0.1</version>
<version>1.1</version>
<version>1.1.1</version>
<version>2.0.0</version>
</versions>
<lastUpdated>20090722140000</lastUpdated>
</versioning>
</metadata>
Si se requiere una dependencia de ese artefacto, tiene las siguientes opciones (por supuesto, se pueden especificar otros rangos de versión , simplemente mostrando las relevantes aquí):
Declara una versión exacta (siempre se resolverá a 1.0.1):
<version>[1.0.1]</version>
Declare una versión explícita (siempre se resolverá a 1.0.1 a menos que se produzca una colisión, cuando Maven seleccionará una versión coincidente):
<version>1.0.1</version>
Declare un rango de versiones para todos los 1.x (actualmente se resolverá a 1.1.1):
<version>[1.0.0,2.0.0)</version>
Declare un rango de versión abierta (se resolverá a 2.0.0):
<version>[1.0.0,)</version>
Declare la versión como ÚLTIMA (se resolverá a 2.0.0) (eliminada de Maven 3.x)
<version>LATEST</version>
Declare la versión como LIBERACIÓN (se resolverá en 1.1.1) (eliminada de la versión 3.x):
<version>RELEASE</version>
Tenga en cuenta que, de manera predeterminada, sus propias implementaciones actualizarán la entrada "más reciente" en los metadatos de Maven, pero para actualizar la entrada de "versión", debe activar el "perfil de versión" de la Super POM de Maven . Puede hacer esto con "-Prelease-profile" o "-DperformRelease = true"
Vale la pena enfatizar que cualquier enfoque que le permita a Maven elegir las versiones de dependencia (LATEST, RELEASE y rangos de versión) puede dejarlo abierto para problemas de tiempo de compilación, ya que las versiones posteriores pueden tener un comportamiento diferente (por ejemplo, el complemento de dependencia ha cambiado previamente a predeterminado) valor de verdadero a falso, con resultados confusos).
Por lo tanto, generalmente es una buena idea definir versiones exactas en las versiones. Como señala la respuesta de Tim , el maven-versions-plugin es una herramienta útil para actualizar versiones de dependencia, en particular las versions:use-latest-versions versions:use-latest-releases objetivos de versions:use-latest-releases .