example - maven deploy jenkins pipeline
¿Jenkins construyendo un producto que consiste en muchos proyectos de Maven?(¿Con el plugin Jenkins Pipeline?) (1)
Para cumplir con sus requisitos, puede confiar en muchas de las características predeterminadas de una compilación de varios módulos de Maven y en una configuración adicional que se explica a continuación.
De tu pregunta:
No es necesario copiar todas las dependencias entre proyectos a la configuración de Jenkins: estas deben estar en un solo lugar, idealmente los archivos
pom.xml
.
Usando un pom agregador / multi-módulo puede tener un solo punto de entrada (un archivo pom.xml) para una compilación maven que luego construiría todos los módulos definidos:
Un proyecto con módulos se conoce como un multimódulo o proyecto agregador. Los módulos son proyectos que este POM enumera y se ejecutan como un grupo. Un proyecto pom empaquetado puede agregar la construcción de un conjunto de proyectos enumerándolos como módulos, que son directorios relativos a esos proyectos.
Es decir, un archivo pom.xml
como el siguiente:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.sample</groupId>
<artifactId>project</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>module-1</module>
<module>module-2</module>
<module>module-n</module>
</modules>
</project>
Es un ejemplo mínimo: defina una lista de módulos (otros proyectos de maven) que se construirán a partir de este proyecto de maven (un proyecto vacío cuyo único propósito es construir otros proyectos de maven). Tenga en cuenta el paquete pom
requerido para tener módulos, le está diciendo a Maven que este proyecto solo proporciona un pom (no más artefactos).
Por lo tanto, podría tener un proyecto de agregador de Maven raíz que definiría los otros proyectos de Maven como sus módulos y tendría un solo trabajo de Jenkins construyendo este punto de entrada.
Además, a partir de su pregunta:
Evite construcciones innecesarias: en un cambio de SCM, solo compile los proyectos que puedan verse afectados.
Para cumplir con este requisito, puede utilizar el incremental-build-plugin
:
Debido a que busca modificaciones en los módulos de un proyecto único, el complemento incremental de Maven lo toma en cuenta solo en proyectos de múltiples módulos. Si se detecta una modificación en un módulo, el directorio de salida se elimina.
Este complemento verificará si alguno de los archivos pom, recursos, fuentes, fuentes de prueba, recursos de prueba cambiaría en un módulo y si el caso elimina su directorio de salida. Como tal, ahorrando tiempo de compilación para un módulo en cuestión y en cadena para todo el proyecto de múltiples módulos (nuestra propia compilación, en este caso).
Para habilitar este mecanismo, puede configurar en el agregador anterior, lo siguiente:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.sample</groupId>
<artifactId>project</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>module-1</module>
<module>module-2</module>
<module>module-n</module>
</modules>
<properties>
<skip.incremental>true</skip.incremental>
</properties>
<build>
<plugins>
<plugin>
<groupId>net.java.maven-incremental-build</groupId>
<artifactId>incremental-build-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<goals>
<goal>incremental-build</goal>
</goals>
<configuration>
<noIncrementalBuild>${skip.incremental}</noIncrementalBuild>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Anteriormente, simplemente hemos agregado el incremental-build-plugin
del agregador y una propiedad, skip.incremental
, que omitirá la ejecución del complemento para la primera compilación, el agregador vacío, al mismo tiempo que lo habilitamos en los módulos de la siguiente manera:
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.sample</groupId>
<artifactId>project</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>simple-module</artifactId>
<properties>
<skip.incremental>false</skip.incremental>
</properties>
</project>
Nota: en el pom anterior de un módulo de muestra, estamos apuntando al archivo pom agregador como padre, por lo tanto, utilizamos la herencia de Maven en combinación con la agregación (un uso clásico) y, como tal, tenemos una compilación de múltiples módulos más un gobierno de compilación común proporcionado por el padre común para todos los módulos declarados (en este caso, el gobierno de compilación común proporciona la configuración adicional incremental-build-plugin
). Además, cada módulo reconfigura la propiedad skip.incremental
para no omitir el complemento mencionado anteriormente. Eso es un truco: ahora el complemento solo se ejecutará en módulos, no en su raíz (lo que no tendría sentido y, en este caso, en realidad arrojaría un error).
Obviamente, en el trabajo de Jenkins relacionado, en su sección Administración del código fuente , no tenemos que configurar un nuevo registro de salida como parte de cada compilación, de lo contrario no se podrían detectar cambios (y cada vez que comenzaría desde cero, que es una buena práctica para las versiones de lanzamiento en realidad).
Además, su comando maven no debería invocar el ciclo de vida clean
, lo que también eliminaría el target
en cada compilación y, como tal, tampoco haría que ningún cambio sea detectable.
Además, a partir de su pregunta:
En el caso de ''dependencias de diamante'' (C depende de B1 y B2, que dependen de A), si se cambia la más baja (A), el producto final (C) siempre debe usar la versión de A que también se usó para construir / probar B1 y B2.
Maven se hará cargo de este requisito como parte de una construcción de múltiples módulos y su mecanismo de reactor :
El mecanismo en Maven que maneja proyectos de múltiples módulos se conoce como el reactor. Esta parte del núcleo de Maven hace lo siguiente:
- Recoge todos los módulos disponibles para construir.
- Ordena los proyectos en el orden de construcción correcto
- Construye los proyectos seleccionados en orden.
Por defecto, el reactor también creará una orden de construcción y siempre construirá un módulo antes de su módulo dependiente / consumidor. Eso también significa que el último módulo construido será realmente el módulo responsable de construir el artefacto final, el producto entregable dependiendo de parte o de todos los demás módulos (por ejemplo, un módulo responsable de entregar un archivo de war
probablemente será el último) para construir en un proyecto de aplicación web de múltiples módulos).
Lecturas adicionales relacionadas con Maven y omitir acciones cuando algo no cambia:
- El
maven-jar-plugin
proporciona laforceCreation
que, de forma predeterminada, ya está habilitadaRequiera que el plugin jar cree un nuevo JAR incluso si parece que ninguno de los contenidos ha cambiado. De forma predeterminada, este complemento ve si el contenedor de salida existe y las entradas no han cambiado. Si estas condiciones son ciertas, el complemento omite la creación del archivo jar.
- El
maven-compiler-plugin
proporciona lauseIncrementalCompilation
, aunque no funciona correctamente en este momento. - El
maven-war-plugin
proporciona la opciónrecompressZippedFiles
que también podría usarse para acelerar las compilaciones y evitar volver a hacer algo (para cambiar afalse
en este caso):Indica si los archivos zip (jar, zip, etc.) que se agregan a la guerra deben comprimirse nuevamente. La compresión de nuevo puede resultar en un tamaño de archivo más pequeño, pero ofrece un tiempo de ejecución notablemente más largo.
Predeterminado :true
Actualizar
Los proyectos de Maven comparten el mismo ciclo de vida.
Este requisito también impondría el uso de un agregador / proyecto de múltiples módulos, sin embargo, también puede aplicarse a diferentes proyectos vinculados a través de dependencias de hecho.
no son administrados por equipos separados de personas con cambios explícitos para recoger versiones más recientes de otros proyectos.
Este punto también impone el uso de un proyecto de múltiples módulos. En un proyecto de múltiples módulos, puede tener diferentes versiones entre los módulos, sin embargo, la práctica y la guía comunes es compartir la misma versión, definida por el proyecto principal (el agregador) y en cascada a través de sus módulos. Como tal, su centralización y gobierno evitarán desalineaciones y errores.
cuando alguien cambia algo en uno de los proyectos, el resultado debe ir directamente al producto final sin cambios adicionales.
Nuevamente, esto sería manejado automáticamente por un proyecto de múltiples módulos. Lo mismo sucedería con diferentes proyectos, cada uno de los cuales usaría versiones SNAPSHOT , y luego no habría necesidad de cambiar la versión de dependencia en su proyecto del consumidor (el responsable de construir el producto final). Sin embargo, aunque las versiones de SNAPSHOT son realmente útiles (y recomendadas) durante el desarrollo, definitivamente no deben usarse al entregar el producto final, ya que la reproducibilidad de la compilación estaría en peligro (es decir, es posible que no pueda volver a compilar la misma versión más adelante). ya que se basaba en las versiones SNAPSHOT, por lo tanto, no en versiones congeladas). Por lo tanto, SNAPSHOT no es una solución de bala de plata y debe usarse solo durante ciertas fases del SDLC del producto, no como una solución finalizada y congelada.
Actualización 2
También vale la pena ver el nuevo Maven Incremental Module Builder para Maven 3.3.1+ y Java 7 .
Más detalles sobre:
Tenemos un producto que consta de muchos proyectos de Maven que dependen unos de otros. Todos estos proyectos de Maven se unen en un solo proyecto que entrega el producto final.
Los proyectos de Maven comparten el mismo ciclo de vida. En otras palabras, no son administrados por equipos separados de personas con cambios <dependency>
explícitos para recoger versiones más recientes de otros proyectos. Más bien, cuando alguien cambia algo en uno de los proyectos, el resultado debe ir directamente al producto final sin cambios adicionales.
Usamos Jenkins como nuestra herramienta de integración continua.
Los principales deseos que tenemos son los siguientes:
- No es necesario copiar todas las dependencias entre proyectos a la configuración de Jenkins: estas deben estar en un solo lugar, idealmente los archivos
pom.xml
. - Evite construcciones innecesarias: en un cambio de SCM, solo compile los proyectos que puedan verse afectados.
- En el caso de las dependencias de diamante (C depende de B1 y B2, que dependen de A), si se cambia la más baja (A), el producto final (C) siempre debe usar la versión de A que también se usó para construir / prueba B1 y B2.
Pregunta : ¿Cuál es el mejor enfoque para hacer esto con Jenkins?
Actualmente estamos pensando en utilizar un solo trabajo con el plugin Jenkins Pipeline, que analiza las dependencias de Maven y los cambios de SCM, decide qué debe construirse y en qué orden, y luego construir los proyectos.