Introducción a Jenkins 2 y el poder de las tuberías

1. Información general

En este artículo, mostraremos el uso de canalizaciones a través de un ejemplo de entrega continua con Jenkins.

Vamos a construir una canalización simple, pero bastante útil, para nuestro proyecto de muestra:

  • Compilacion
  • Análisis estático simple (paralelo a la compilación)
  • Pruebas unitarias
  • Pruebas de integración (en paralelo con pruebas unitarias)
  • Despliegue

2. Configurar Jenkins

En primer lugar, necesitamos descargar la última versión estable de Jenkins (2.73.3 en el momento de escribir este artículo).

Naveguemos a la carpeta donde está nuestro archivo y ejecútelo usando el comando java -jar jenkins.war . Tenga en cuenta que no podemos usar Jenkins sin una configuración inicial de usuarios.

Después de desbloquear Jenkins usando la contraseña inicial generada por el administrador, debemos completar la información de perfil del primer usuario administrador y asegurarnos de instalar todos los complementos recomendados.

Ahora tenemos una nueva instalación de Jenkins lista para ser utilizada.

Todas las versiones disponibles de Jenkins se pueden encontrar aquí.

3. Tuberías

Jenkins 2 viene con una gran característica llamada Pipelines , que es muy extensible cuando necesitamos definir un entorno de integración continua para un proyecto.

Una canalización es otra forma de definir algunos pasos de Jenkins mediante código y automatizar el proceso de implementación de software.

Utiliza un lenguaje específico de dominio (DSL) con dos sintaxis diferentes:

  • Canalización declarativa
  • Canalización con guión

En nuestros ejemplos, vamos a usar la Pipeline con secuencias de comandos que está siguiendo un modelo de programación más imperativa construida con Groovy .

Repasemos algunas características del complemento Pipeline :

  • las canalizaciones se escriben en un archivo de texto y se tratan como código; esto significa que pueden agregarse al control de versiones y modificarse más adelante
  • permanecerán después de reiniciar el servidor de Jenkins
  • opcionalmente podemos pausar las canalizaciones
  • soportan requisitos complejos como realizar trabajos en paralelo
  • el complemento Pipeline también se puede ampliar o integrar con otros complementos

En otras palabras, configurar un proyecto Pipeline significa escribir un guión que aplicará secuencialmente algunos pasos del proceso que queremos lograr.

Para empezar a usar pipelines tenemos que instalar el plugin Pipeline que permite componer una automatización simple y compleja.

Opcionalmente, también podemos tener una vista de etapa de canalización para que cuando ejecutemos una compilación, veamos todas las etapas que hemos configurado.

4. Un ejemplo rápido

Para nuestro ejemplo, usaremos una pequeña aplicación Spring Boot. Luego crearemos una canalización que clona el proyecto, lo construye y ejecuta varias pruebas, luego ejecuta la aplicación.

Instalemos los complementos Checkstyle , Static Analysis Collector y JUnit , que son útiles respectivamente para recopilar los resultados de Checkstyle , crear un gráfico de análisis combinado de los informes de prueba e ilustrar las pruebas ejecutadas con éxito y fallidas.

Primero, entendamos la razón de Checkstyle aquí: es una herramienta de desarrollo que ayuda a los programadores a escribir mejor código Java siguiendo estándares aceptados y conocidos.

Static Analysis Collector es un complemento que recopila diferentes resultados de análisis e imprime los resultados en un gráfico de tendencia combinado. Además, el complemento proporciona informes de estado y estabilidad de construcción en función de estos resultados agrupados.

Finalmente, el complemento JUnit proporciona un editor que consume informes de prueba XML generados durante las compilaciones y genera información detallada y significativa relativa a las pruebas de un proyecto.

También configuraremos Checkstyle en el pom.xml de nuestra aplicación :

 org.apache.maven.plugins maven-checkstyle-plugin 2.17 

5. Creación de un script de canalización

Primero, necesitamos crear un nuevo trabajo de Jenkins. Asegurémonos de seleccionar Pipeline como el tipo antes de presionar el botón OK como se describe en esta captura de pantalla:

La siguiente pantalla nos permite completar más detalles de los diferentes pasos de nuestro trabajo de Jenkins, como la descripción , los disparadores , algunas opciones avanzadas del proyecto:

Vamos a sumergirnos en la parte principal y más importante de este tipo de trabajo haciendo clic en la pestaña Pipeline .

Luego, para la definición, seleccione el script Pipeline y marque Usar Groovy Sandbox.

Aquí está el script de trabajo para un entorno Unix:

node { stage 'Clone the project' git '//github.com/eugenp/tutorials.git' dir('spring-jenkins-pipeline') { stage("Compilation and Analysis") { parallel 'Compilation': { sh "./mvnw clean install -DskipTests" }, 'Static Analysis': { stage("Checkstyle") { sh "./mvnw checkstyle:checkstyle" step([$class: 'CheckStylePublisher', canRunOnFailed: true, defaultEncoding: '', healthy: '100', pattern: '**/target/checkstyle-result.xml', unHealthy: '90', useStableBuildAsReference: true ]) } } } stage("Tests and Deployment") { parallel 'Unit tests': { stage("Runing unit tests") { try { sh "./mvnw test -Punit" } catch(err) { step([$class: 'JUnitResultArchiver', testResults: '**/target/surefire-reports/TEST-*UnitTest.xml']) throw err } step([$class: 'JUnitResultArchiver', testResults: '**/target/surefire-reports/TEST-*UnitTest.xml']) } }, 'Integration tests': { stage("Runing integration tests") { try { sh "./mvnw test -Pintegration" } catch(err) { step([$class: 'JUnitResultArchiver', testResults: '**/target/surefire-reports/TEST-' + '*IntegrationTest.xml']) throw err } step([$class: 'JUnitResultArchiver', testResults: '**/target/surefire-reports/TEST-' + '*IntegrationTest.xml']) } } stage("Staging") { sh "pid=\$(lsof -i:8989 -t); kill -TERM \$pid " + "|| kill -KILL \$pid" withEnv(['JENKINS_NODE_COOKIE=dontkill']) { sh 'nohup ./mvnw spring-boot:run -Dserver.port=8989 &' } } } } }

First, we're cloning the repository from GitHub, then changing the directory to our project, which is called spring-jenkins-pipeline.

Next, we compiled the project and apply Checkstyle analysis in a parallel way.

The following step represents a parallel execution of unit tests and integration tests, then deployment of the app.

Parallelism is used to optimize the pipeline, and have the job runs faster. It's a best practice in Jenkins to simultaneously run some independent actions that can take a lot of time.

For example, in a real-world project, we usually have a lot of unit and integration tests that can take longer.

Note that if any test failed the BUILD will be marked as FAILED too and the deployment will not occur.

Also, we're using JENKINS_NODE_COOKIE to prevent immediate shut down of our application when the pipeline reaches the end.

To see a more general script working on other different systems, check out the GitHub repository.

6. Analysis Report

After creating the job, we'll save our script and hit Build Now on the project home of our Jenkins dashboard.

Here's an overview of the builds:

A little further down we'll find the stage view of the pipeline, with the result of each stage:

Each output is accessible when hovering over a stage cell and clicking the Logs button to see the log messages printed in that step.

We can also find more details of the code analysis. Let's click on the desired build from the Build History on the right menu and hit Checkstyle Warnings.

Here we see 60 high priority warnings browsable by clicking:

The Details tab displays pieces of information that highlight warnings and enable the developer to understand the causes behind them.

In the same way, the full test report is accessible by clicking on Test Result link. Let's see the results of the com.baeldung package:

Here we can see each test file with its duration and status.

7. Conclusion

En este artículo, configuramos un entorno de entrega continua simple para ejecutar y mostrar el análisis de código estático y el informe de prueba en Jenkins a través de un trabajo Pipeline .

Como siempre, el código fuente de este artículo se puede encontrar en GitHub.