Herramientas y Métodos en Ingeniería del Software. Version curso.2022. Joaquín Cañadas <jjcanada@ual.es>

Integración Continua con Jenkins.
Objetivos
  • Construcción automatizada de proyectos Java basados en Maven usando Jenkins como servidor de Integración Continua

  • Diseño de los pasos de construcción con Jenkins Pipelines

  • Configurar Webhooks para la integración de GitHub y Jenkins

  • Generación y visualización de los informes de evolución del proyecto

Realización y entrega

La realización de estas actividades se realizará de forma individual. Serán la base para actividades posteriores que ser harán en equipo. Cada miembro del equipo debe tener sus ejercicios individuales en el Jenkins del equipo. La entrega será mediante el envío de un informe y el acceso al profesor a los servicios configurados, para la revisión y evaluación de los mismos.

1. Introducción a la Integración Continua con Jenkins

Jenkins CI es un sistema de Integración Continua open source, desarrollado por Kohsuke Kawaguchi, desarrollador de la ex Sun Microsystems y posteriormente de Oracle. En 2010 fundó CloudBees, empresa que da soporte empresarial de Jenkins.

Jenkins proporciona integración continua en el desarrollo de software, es decir, permite configurar y agendar la ejecución de las tareas que componen toda y/o cada una de las partes que conforman el ciclo de vida de un proyecto. Para dar una idea de esto, basta pensar en los famosos night-builds, los cuales son compilaciones, validaciones y liberaciones de versiones beta que realizan algunos sistemas durante las noches de forma automática sobre lo que han ido trabajando los desarrolladores durante el día.

Jenkins nace como fork del sistema predecesor Hudson CI, del mismo autor, como alternativa open source desde que Sun fue adquirida por Oracle y cambiada su licencia.

Jenkins posee una interminable lista de plugins, los cuales le permiten definir tareas que pueden integrarse con herramientas de control de versiones (Subversion, Git, …​), ejecutar proyectos basados en Apache Maven, Apache Ant, Microsoft MSBuild, shell y batch scripts, y muchas otras. Además permite ejecutar tareas adicionales previa y posteriormente a la construcción, como por ejemplo preparar el entorno, realizar un despliegue o compactar y subir binarios a un servidor por SSH.

Para cada proyecto, Jenkins guarda un historial de cambios realizados por build o versión, almacena quién lo realizo y cuales archivos fueron manipulados, y sus comentarios al respecto.

Existen otras muchas herramientas de integración continua y despliegue continuo (CI/CD), como Travis CI, Gitlab CI, Circle CI, Semaphore CI, Appveyor, Azure DevOps, y muchas más.

1.1. Principales características

  1. Automatiza la construcción del software, periódicamente o en base a unas condiciones. En proyectos Maven se puede simular una construcción similar a un equipo que sólo tuviese instalado Java y Maven (y el correspondiente sistema operativo); de este modo, se elimina el perverso efecto de la contaminación de los equipos de desarrollo.

  2. Centraliza la información referida a la construcción del software y al estado y salud del proyecto:

    • Estado de la construcción.

    • Informes sobre la construcción.

    • Informes sobre las pruebas.

    • Site del proyecto.

  3. Gestiona la interacción con otras herramientas, como por ejemplo [SonarQube](https://sonarcloud.io/), de mide de calidad del software.

1.2. ¿Por qué usarlo?

  1. Simplifica significativamente (a un par de clicks y dentro de un entorno web lo que lo hace fácilmente accesible desde cualquier parte) los procesos involucrados en el ciclo de vida de un proyecto, ya sean simples o repetitivos, largos y complejos como puede ser de generación de binarios, integrando el trabajo de varios desarrolladores, ejecución de pruebas automatizadas, generación de informes, publicación en pagina web, notificación a clientes de versiones beta, etc.

  2. Da un marco de simplicidad sobre la integración continua gracias a las diferentes posibilidades de notificaciones de éxitos y errores entre procesos, por lo que con la formación adecuada sobre los mismos se puede asegurar una altísima calidad de software desde el primer día, evitando errores, demoras y a un mínimo coste.

  3. Debido a los múltiples sistemas de notificaciones por cual optar (ya sea por mail, chat, slack, twitter, etc), es sencillo estar siempre informado y poder tomar decisiones rápidamente.

Aquí pueden encontrar un resumen de beneficios y preocupaciones de Jenkins.

1.3. CI/CD y DevOps

La integración continua forma parte de un proceso más amplio conocido como entrega continua o despliegue continuo (Continuous Delivery, Continuous Deployment), que además abarca el despliegue automatizado de proyectos en distintos entornos de ejecución. Por ello, frecuentemente en la bibliografía se hace referencia como CI/CD, de sus siglas en inglés: Continuous Integration and Continuous Delivery.

CI/CD es una práctica fundamental dentro de la metodología DevOps en ingeniería del software.

2. Prerrequisitos

Para comenzar a trabajar en esta sesión, será necesario haber realizado las actividades anteriores de JUnit y Maven. Al menos, haberlas empezado, porque si aun no las has terminado, ¡¡¡no te preocupes!!! De hecho, es mejor que hagas esta actividad de Jenkins antes de terminar las anteriores de JUnit y Maven, ya que así verás como Jenkins visualiza los gráficos de evolución (tests, métricas, etc.) cuando vayas completando las actividades anteriores.

Además, se debe disponer de crédito en Azure, y es necesario disponer de una máquina virtual con Jenkins instalado y un usuario con permisos (todo ello realizado en sesiones anteriores). Igualmente, se dispone de usuario en GitHub y los repositorios git en GitHub de los proyectos Java de las sesiones anteriores. También, debes tener una pareja de claves SSH personal en la carpeta HOME del usuario de tu equipo (~).

~/.ssh/
├── id_rsa (1)
└── id_rsa.pub (2)
1 clave privada
2 clave pública

3. Instalación de plugins adicionales

En primer lugar, es recomendable actualizar Jenkins a la última versión, para evitar bugs y vulnerabilidades de seguridad que hayan sido arregladas en la última versión. Para ello, accede a tu máquina Jenkins por ssh y ejecuta la actualización de paquetes:

ssh ubuntu@dns.maquina.jenkins
sudo apt-get update -y
sudo apt-get upgrade -y

A partir de marzo 2023 hay que actualizar las claves de firma de Jenkins

curl -fsSL https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key | sudo tee \
  /usr/share/keyrings/jenkins-keyring.asc > /dev/null

echo deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] \
  https://pkg.jenkins.io/debian-stable binary/ | sudo tee \
  /etc/apt/sources.list.d/jenkins.list > /dev/null

Tras la actualización y reinicio de Jenkins, vamos a instalar varios plugins adicionales en Jenkins, si aun no están instalados: Github integration, Maven Integration, Cobertura, Jacoco (comprobar antes si no están instalados ya), Code Coverage Api, JavaDoc, Warnings Next Generation, Embeddable Build Status Plugin, xUnit, Monitoring, etc.

Haz clic en Manage Jenkins > Manage Plugins. En la pestaña Available busca Github integration, seleccionalo y pulsa en Download now and install after restart.

jenkins plugins github integration
Fig. 1. Instalación del plugin Github integration

Repite los pasos para los plugins Maven Integration, Cobertura, JavaDoc y xUnit.

Necesitaremos visualizar el resultado de la cobertura en Jenkins. Para ello instala el plugin de JaCoCo (Java Code Coverage) y el plugin Code Coverage API.

plugins jacoco install
Fig. 2. Instalación del plugin Jacoco
plugins code coverage api install
Fig. 3. Instalación del plugin Code Coverage API

Para visualizar el resultado del análisis estático de código, necesitaremos el plugin Warnings Next Generation. Procede de la misma forma.

Instala además el Embeddable Build Status Plugin, que nos permitirá visualizar en el archivo README.md del proyecto, o en cualquier otro sitio, un pequeño badge o insignia con el estado de build del proyecto.

badge build status
Fig. 4. Badge con el estado del build

Instala además los plugins: Monitoning, Job Configuration History y Pipeline Configuration History, que nos permitiran, el primero, monitorizar el estado de Jenkins (uso de recursos, etc) para poder decidir si la máquina necesita ser dimensionada a una más grande (con más nucleos, RAM, etc), y los dos siguientes, guardar un historial de los cambios en la configuración de los proyectos y pipelines, por si falla la nueva configuración poder recuperar alguna versión anterior.

Por último, marca Restart Jenkins para completar la instalación. Tras unos segundos, vuelve a iniciar sesión y tendrás los plugins instalados.

jenkins plugins restart
Fig. 5. Reiniciar para completar la instalación

El plugin Embeddable Build Status necesita dar acceso al usuario anónimo en la configuración de seguridad de Jenkins, para que se pueda leer el estado de construcción del proyecto:

build status access
Fig. 6. Acceso al usuario anómimo

Además de los plugins, para que la máquina virtual de Jenkins funcione correctamente al aumentar la carga de trabajo, es necesario añadir memoria Swap (en disco), al menos 2 Gb. Aquí tienes los pasos: How To Add Swap Space on Ubuntu 18.04.

Si tienes crédito de sobra en tu cuenta Azure, puedes incluso cambiar el tamaño de la máquina virtual para que tenga más cores y RAM.

4. Tipos de proyectos en Jenkins

En Jenkins existen varios tipos de proyectos. Al hacer clic en nuevo elemento, aparece la vista de creación de nuevo proyecto, en la que debemos introducir el nombre del proyecto y su tipo. Los 3 principales tipos son:

  • Estilo libre (Freestyle project): es el más flexible en su configuración. Permite construir proyectos en cualquier tecnología, en función de las herramientas (tools) y plugins que tengas instalados. Se utiliza cuando deseemos ejecutar fundamentalmente comandos desde la shell. En la sesión de despliegue automatizado de la web del equipo (sesión 05) usamos proyectos de este tipo.

  • Proyecto Maven: se utiliza para construir proyectos Java basados en Maven. De forma predeterminada incluye un paso en el que añadir los goals de maven que se deseen ejecutar en la construcción del proyecto.

  • Pipeline: un pipeline o tubería identifica los pasos o fases (stages) que se van a ejecutar en el proceso de construcción del proyecto. Cada fase tiene definido cómo se ejecuta, y los resultados que produce. La ejecución de las fases es secuencial, aunque también se pueden configurar fases en paralelo.

001 project types
Fig. 7. Nuevo proyecto. Tipos principales de proyectos

En esta actividad vamos a construir en Jenkins un proyecto estilo libre en Ant, y los proyectos Java mavenizados de las sesiones anteriores de dos formas:

  1. Utilizando la forma clásica, creando un proyecto tipo Maven.

  2. Utilizando la descripción en pases mediante pipeline.

Comencemos por la primera forma.

5. Creación de un Proyecto con Ant

Comenzaremos con un ejemplo sencillo en Java denominado ConnectFour. Este proyecto se construye con Ant, y está disponible aquí: https://github.com/ualhmis/connect-four.git

Este ejercicio ConnectFour debe ser realizado individualmente por cada uno de los miembros del equipo.

Si deseas hacer cambios, por ejemplo para corregir los tests que fallan, primero forkea el repositorio a tu cuenta de GitHub

  1. Creamos una nueva tarea de tipo estilo libre: el nombre debe ser connectFour-nombreMiembro

new connect four
Fig. 8. Nuevo proyecto estilo libre: Connect-four
  1. Jenkins conecta al repositorio donde están los fuentes para descargarlos. Selecciona Git, y añade esta URL: https://github.com/ualhmis/connect-four.git. Al tratarse de un repositorio público no necesita credenciales.

new connect four git url
Fig. 9. Git repositorio URL
  1. Archivo de construcción (build): en la ejecución de la tarea, elegimos Ant

new connect four build ant
Fig. 10. Build. Ant
  1. Seleccionamos la versión de Ant instalada (no dejar “por defecto” porque da error), y en Destinos escribimos all

new connect four build all
Fig. 11. Seleccionar Ant version. Targets all
  1. Acciones a ejecutar después: Publicamos los resultados de los test JUnit y la documentación JavaDoc

new connect four postbuild junit
Fig. 12. Acciones a ejecutar despues: JUnit

Y añadimos la ruta del archivo con los resultados de los test JUnit en xml: target/test-results/*.xml

new connect four postbuild junit xml
Fig. 13. Test report XML
  1. Igualmente, añadimos otra acción a ejecutar después para JavaDoc

new connect four postbuild javadoc
Fig. 14. Javadoc

Y añadimos la ruta donde se han generado los archivos JavaDoc: target/docs

new connect four postbuild javadoc target
Fig. 15. Ruta a Javadoc
  1. Guardamos

  2. Construir ahora. Por consola se visualiza el resultado de la ejecución de las tareas Ant configuradas en el archivo build.xml del proyecto.

El resultado es bola amarilla, porque fallan un par de tests. Para ver una gráfica de resultados de los Test debemos ejecutar al menos 2 construcciones.

new connect four build results
Fig. 16. Connect-four: Resultado de la construcción

6. Creación de un Proyecto Maven

Para ese ejercicio, cada uno debe usar el repositorio de la práctica 7 donde se ha trabajado con Maven.

6.1. Construcción básica

  1. Crea un nuevo proyecto Maven. El nombre debe ser ej07-maven-nombreMiembro.

new maven
Fig. 17. Nuevo proyecto Maven: sesion07
  1. Indica la URL del proyecto en Github. Utiliza aquí la URL de tu proyecto de la práctica 7.

new maven github url
Fig. 18. URL del proyecto en Github
  1. Selecciona Git como control de código fuente. Indica la URL del repositorio.

new maven github repo
Fig. 19. URL del repositorio en Github

En caso de que sea un repositorio privado tendrás que proporcionar unas credenciales. En Jenkins debes crear unas nuevas credenciales. Se recomienda crear en Jenkins unas credenciales de tipo Username and password, donde el password debe ser un token generado en GitHub. El token se genera en GitHub, sobre tu usuario: Settings, Developer Settings, Personal Access tokens, Generate New Token, y marcar las opciones de repo. Otra alternativa es crear en Jenkins unas credenciales tipo pareja de claves SSH, aunque es igual de mala práctica meter tu clave privada personal en Jenkins. Por ello, para esta alternativa, la buena práctica consiste en crear una nueva pareja de claves SSH exclusiva para que Jenkins pueda leer el repositorio privado, añadir la clave pública al repositorio en GitHub (exclusivamente al repositorio concreto, no a nuestro usuario de GitHub), y por último añadir la clave privada como credencial en Jenkins para que pueda leer ese repositorio privado de GitHub.

  1. En la sección de build, añade la ruta correcta al archivo pom.xml y por último añade los goals: clean package

new maven build goals
Fig. 20. Build con Maven
  1. Guarda los cambios

  2. Construir ahora. Por consola se visualiza el resultado de la ejecución de maven.

En los proyectos Maven, no hace falta configurar la publicación de los test de JUnit, se hace de forma predeterminada a partir de la segunda construcción.

new maven build results
Fig. 21. Resultados de la construcción

6.2. Webhook: construcción tras un push en GitHub

Mediante un Webhook se puede configurar que cuando el repositorio en GitHub reciba un push notificará a Jenkins para que lance la construcción automáticamente. Para ello, en la sección de disparadores de la construcción (build trigers) marca la opción de hook con Github:

Webhook: ejecución automática del build en Jenkins tras un push en GitHub

Configura en GitHub un nuevo Webhook para que tras cada cambio de código en el repositorio, Jenkins sea notificado y lance la construcción del pipeline:

  1. En GitHub, seleccionamos el repositorio sobre el que queremos activar la construcción en Jenkins y hacemos clic en: Settings > WebHooks > Add webhook

  2. En Payload URL:

    http://{YOUR_JENKINS_URL}/github-webhook/
jenkins webhook github
Fig. 22. Nuevo Webhook
  1. Finalmente, en la configuración del proyecto en Jenkins, en la sección Build Trigers, marca la opción GitHub hook tirigger from GITScm polling

jenkins webhook build triger
Fig. 23. Activar el Webhook en build trigers

A partir de ahora, cuando el repositorio en GitHub reciba un push notificará a Jenkins para que lance la construcción automáticamente.

6.3. Informe de cobertura

  1. Añade los resultados de la cobertura obtenidos con JaCoCO: entra de nuevo en la configuración del proyecto, en post-build actions añade una acción a ejecutar después y selecciona Record JaCoCo coverage report

maven postbuild jacoco
Fig. 24. Añadir el informe de cobertura con JaCoCO
  1. Configura la ruta correcta a los fuentes: **/src/

maven postbuild jacoco config
Fig. 25. Configuración de JaCoCo
  1. Guarda los cambios y construye el proyecto. Al actualizar el proyecto verás la gráfica de Cobertura. Si ejecutas un par de builds la gráfica muestra la linea de evolución.

maven postbuild jacoco grafica
Fig. 26. Añadir el informe de cobertura con JaCoCo

Y si haces clic en la gráfica, verás el informe detallado.

maven postbuild jacoco details
Fig. 27. Detalle de cobertura con JaCoCo

6.4. Añadiendo Javadoc y Site

  1. Para generar la documentación en Javadoc y publicarla en la página del proyecto, simplemente añade los goals javadoc:javadoc javadoc:aggregate.

  2. Para generar la documentación Site de Maven y publicarla, simplemente añade el goal site.

maven postbuild javadoc site
Fig. 28. Javadoc y Site
  1. Para poder visualizar correctamente el Site, hay que cambiar la configuración de seguridad de Jenkins predeterminada que es muy restrictiva para prevenir de archivos HTML/JS maliciosos. Para modificar la configuración, abre la consola de scritps (Manage Jenkins / Script Console), y ejecuta estas líneas para desestablecer la cabecera:

System.setProperty("hudson.model.DirectoryBrowserSupport.CSP", "")
System.getProperty("hudson.model.DirectoryBrowserSupport.CSP")
maven script console site
Fig. 29. Script Console: permisos para visualizar Site
  1. Tras ello ya podrás visualizar correctamente. Pero ten en cuenta que cada vez que reinicies Jenkins esta configuración se pierde y vuelve a la configuración predeterminada.

7. Creación de un Proyecto Pipeline

Para ese ejercicio, cada estudiante debe usar, de nuevo, el repositorio de la práctica 7 donde se ha trabajado con Maven. Vamos a configurar el proyecto Jenkins que construya el mismo repositorio de la sección anterior, pero esta vez vamos a utilizar pipelines.

7.1. Diseño del pipeline

  1. Crea un nuevo proyecto y dale el nombre y selecciona tipo pipeline. El nombre debe ser ej07-pipeline-nombreMiembro.

  2. Indica la URL del proyecto en Github. Utiliza aquí la URL de tu proyecto de la práctica 7.

  3. En la sección Pipeline, disponemos de un cuadro de texto en el que añadir la descripción de nuestro pipeline utilizando la sintaxis declarativa que Jenkins proporciona. Vamos a ver cómo hacerlo.

pipeline {
  agent any (1)

  tools {
    // Nombre dado a la instalación de Maven en "Global Tool configuration"
    maven "Default Maven" (2)
  }

  stages { (3)
   ...
  }
}
1 agente o nodo de Jenkins en que ejecuta la construcción del proyecto. En el ejemplo, any indica que se ejecutará cualquier nodo, en nuestro caso será en master ya que es el único nodo que hay definido en nuestro Jenkins.
2 como herramienta para la construcción se usará maven. Pon aquí el nombre que diste a tu instalación de Maven configurada previamente en Tools Configuration.
3 Bloque de stages: fases o etapas que conforman el pipeline

A continuación se muestra cómo definir cada fase o stage una a una dentro del bloque stages:

pipeline {
  agent any

  tools {
    // Nombre dado a la instalación de Maven en "Tools configuration"
    maven "Default Maven"
  }

  stages {
    stage('Git fetch') { (1)
      steps {
        // Get some code from a GitHub repository
        git branch: 'main', url: 'https://github.com/ualhmis/MavenEjercicios'
      }
    }
    stage('Compile, Test, Package') { (2)
      steps {
        // When necessary, use '-f path-to/pom.xml' to give the path to pom.xml
        // Run goal 'package'. It includes compile, test and package.
        sh "mvn  -f sesion07Maven/pom.xml clean package" (3)
      }
      post { (4)
        // Record the test results and archive the jar file.
        success {
          junit '**/target/surefire-reports/TEST-*.xml'
          archiveArtifacts '**/target/*.jar'
        }
      }
    }
  }
}
1 El step git clona el repositorio git. En este ejemplo se trata de un repositorio público. También, puedes clonar un repo privado o una rama concreta usando los parámetros adecuados, por ejemplo: git credentialsId: 'my-private-key-credential-id', branch: 'main', url: 'https://github.com/usuario/repoPrivado.git'. Previamente has debido crear una credencial con el ID my-private-key-credential-id. Se recomienda usar credenciales de tipo Username and password, donde el password debe ser un token generado en GitHub. El token se genera en GitHub, sobre tu usuario: Settings, Developer Settings, Personal Access tokens, Generate New Token, y marcar las opciones de repo. Si necesitas hacer alguna otra parametrización, se recomienda usar el Snippet Generator.
2 Fase de build: compilación, test y empaquetado de la aplicación.
3 Se llama a maven con los goals clean package: elimina todo lo generado en la construcción anterior, y a continuación se lanza la construcción con package tal y como está definida en el archivo pom.xml. Cuando sea necesario, indique el path al archivo pom.xml con el parámetro -f path-to/pom.xml
4 Paso posterior al build, que guarda los resultados de los test de JUnit para generar la gráfica de evolución de los test. Además, archiva el empaquetado .jar para que pueda ser descargado posteriormente
new pipeline definition
Fig. 30. Definición del pipeline
  1. Guarda los cambios y construye.

  2. Tras ejecutar el pipeline, con "Build now", el resultado debe ser el siguiente:

new pipeline results
Fig. 31. Resultados del pipeline

7.2. Informe de Cobertura de código

Para visualizar informe de cobertura en el pipeline, añade las dos siguientes linea al bloque post:

  ...
  success {
    junit '**/target/surefire-reports/TEST-*.xml'
    archiveArtifacts '**/target/*.jar'
    jacoco( (1)
      execPattern: '**/target/jacoco.exec',
      classPattern: '**/target/classes',
      sourcePattern: '**/src/',
      exclusionPattern: '**/test/'
    )
    publishCoverage adapters: [jacocoAdapter('**/target/site/jacoco/jacoco.xml')] (2)
  }
  ...
1 Añade el informe Coverage Trend
2 Añade el informe Coverage Report

Tras la construcción de nuevo del proyecto, verás la gráfica de los resultados de los test y debajo la gráfica de evolución de cobertura.

new pipeline coverage results
Fig. 32. Resultados de la cobertura

7.3. Análisis estático de código

Para mantener y aumentar la calidad de nuestro código debemos ayudarnos, entre otras herramientas, de técnicas de análisis estático de código. Básicamente, se encargan de buscar defectos en el código sin necesidad de que este se ejecute. En Java una de las más habituales es Checkstyle, aunque hay otras como FindBugs, PMD, y SonarQube que integra a los anteriores.

Para ejecutar y visualizar el análisis de Checkstyle, añade un nuevo stage al pipeline:

  stage ('Analysis') {
    steps {
	  // Warnings next generation plugin required
	  sh "mvn -f sesion07Maven/pom.xml checkstyle:checkstyle site -DgenerateReports=false"
    }
    post {
      success {
        recordIssues enabledForFailure: true, tool: checkStyle()
      }
    }
  }

Tras la construcción, el pipeline tiene una nueva fase y además en el menú tenemos acceso al informe de CheckStyle.

new pipeline checkstyle report dashboard
Fig. 33. Pipeline con la nueva fase de Análisis
new pipeline checkstyle report details
Fig. 34. Detalles del informe de CheckStyle

Como parte del ejercicio, completa por ti mismo la publicación del resto de informes de análisis estático de código generados en la sesión 7. Se publican a través del plugin Warnings Next Generation.

  • PMD: añade el goal adecuado en la ejecución de maven y añade la publicación del informe:

recordIssues enabledForFailure: true, tool: pmdParser()
  • CPD: añade la publicación del informe:

recordIssues enabledForFailure: true, tool: cpd()
  • FingBugs: repite el proceso.

  • SpotBugs: repite el proceso.

El resultado final debe ser tal que así. Para que se ejecuten todos los análisis simplemente llamamos a site ya que todos los tenemos definidos en el bloque <reporting> del pom.xml.

    stage ('Analysis') {
      steps {
	    // Warnings next generation plugin required
	    sh "mvn -f sesion07Maven/pom.xml site"
      }
      post {
        success {
          recordIssues enabledForFailure: true, tool: checkStyle()
          recordIssues enabledForFailure: true, tool: pmdParser()
          recordIssues enabledForFailure: true, tool: cpd()
          recordIssues enabledForFailure: true, tool: findBugs()
          recordIssues enabledForFailure: true, tool: spotBugs()
        }
      }
    }

Como resultado debes ver las gráficas de cada una de estas 5 herramientas en la página del proyecto. Y haciendo clic en cada gráfica, así como en los enlaces del menú de la izquierda, se accede al detalle de cada informe.

new pipeline analysis links
Fig. 35. Enlaces a los informes de análisis estático de código

7.4. Dependency-check

Dependency Check de OWASP (Open Web Application Security Project) es una herramienta que permite identificar las dependencias de nuestro proyecto y comprobar si hay alguna de ellas que tiene vulnerabilidades conocidas. En la práctica anterior configuramos el plugin dependency-check-maven en el bloque <reporting> del pom.xml, por lo que este plugin se ejecuta cuando llamamos al goal site. Puesto que ya hemos ejecutado site en la fase anterior, no es necesario crear una nueva fase (stage) para generar el informe de Dependency-check, únicamente será necesario publicarlo en el pipeline.

  1. Instala el plugin OWASP Dependency-Check en Jenkins.

plugins owasp dependency check install
Fig. 36. Instalación del plugin Dependency-Check
  1. Modifica el archivo pom.xml en tu proyecto y añade la siguiente línea para que genere el informe también en formato XML, que es el formato que lee el plugin:

      <plugin>
        <groupId>org.owasp</groupId>
        <artifactId>dependency-check-maven</artifactId>
        <version>5.3.2</version>
        <configuration>
          <skipTestScope>false</skipTestScope>
          <formats> (1)
            <format>HTML</format>
            <format>XML</format>
          </formats>
        </configuration>
        ...
      </plugin>
1 Genera el informe en HTML y XML
  1. Añade en el pipeline la siguiente linea para publicar el informe, en el mismo bloque pero antes que checkstyle, pmd, etc.

dependencyCheckPublisher pattern: '**/target/site/dependency-check-report.xml'
  1. Tras volver a construir el proyecto, aparecerá una nueva gráfica de Dependency Check en el proyecto. Si no tienes problemas de seguridad en las dependencias, esta gráfica estará en blanco. El enlace al informe de dependencias no aparece en la página principal del proyecto, en el menú de enlaces como el resto, sino que tienes que hacer clic en el número del último build, y en la nueva página ya aparece el enlace:

new pipeline dependency check link
Fig. 37. Enlace al informe Dependency-Check
Saber más…​ Oligatorio para los equipos de 3 personas

Si estás interesado en profundizar en este tema, en la asignatura Procesos de Ingeniería del Software II, de 4º curso, lo estudiaréis con mas detalle. En cualquier caso, es obligatorio para los equipos de 3 personas integrar SonarQube con Jenkins, ya que SonarQube realiza un análisis mucho más detallado de la calidad y seguridad del código, realizando tanto análisis estático de código (CheckStyle y otros), como de análisis de seguridad (vulnerabilidades), y definiendo lo que denomina Quality Gates que permiten definir condiciones que se deben cumplir basadas en los valores de las métricas del proyecto (por ejemplo, que la cobertura de código sea mayor del 80%).

En la página principal de esta actividad tienes un tutorial sobre Integración de SonarQube y Jenkins. También puedes encontrar mucha documentación online sobre cómo hacerlo:

Además, si tu proyecto está en un repositorio público en GitHub, puedes ahorrarte tener que instalar tu propio SonarQube utilizando SonarCloud, el servicio de SonarQube en la nube (SaaS) gratuito para proyectos públicos, con el que evitas tener que instalar y mantener tu propio SonarQube.

Para lanzar el análisis de Sonar con maven:

  1. Genera el login TOKEN

  2. Ejecuta los goals de maven: clean verify sonar:sonar -Dsonar.login=$SONAR_LOGIN_TOKEN

Incluso puedes configurar SonarCloud y Jenkins para que analizar los pull request de tu repositorio y conocer el resultado del análisis de Sonar antes de hacer el merge del pull request.

7.5. Documentación Javadoc y Site

La siguiente fase recomendada en el pipeline, de las lista de fases genéricas, es la de generar la documentación

Es necesario instalar previamente el plugin HTML Publisher de Jenkins.

Añade esta fase al pipeline:

    stage ('Documentation') {
      steps {
	    sh "mvn -f sesion07Maven/pom.xml javadoc:javadoc javadoc:aggregate" (1)
      }
      post{
        success {
          step $class: 'JavadocArchiver', javadocDir: 'sesion07Maven/target/site/apidocs', keepAll: false (2)
          publishHTML(target: [reportName: 'Maven Site', reportDir: 'sesion07Maven/target/site', reportFiles: 'index.html', keepAll: false]) (3)
        }
      }
    }
1 Llamada a javadoc desde Maven.
2 Publica los archivos html de Javadoc y añade el enlace en el menú.
3 Publica el site y añade el enlace en el menú.
new pipeline docs links
Fig. 38. Enlaces a documentación Javadoc y Site

7.6. Jenkinsfile

La descripción del pipeline puede guardarse en un archivo llamado Jenkinsfile y guardarse en el repositorio como otro archivo de código más. Si haces esto, al configurar el proyecto en Jenkins debes elegir la opción Pipeline script from SCM en la sección de definición del pipeline. A continuación, debes proporcionar la URL del repositorio donde se encuentra el archivo Jenkinsfile.

new pipeline jenkinsfile
Fig. 39. Configuración del pipeline con archivo Jenkinsfile

8. FAQ y resolución de problemas (thoubleshouting)

En esta sección se añadirán soluciones a los problemas más habituales.

  1. La construcción de maven funciona correctamente en Eclipse pero da error en Jenkins:

    1. Revisa la versión de maven instalada en Jenkins, y actualiza a la última versión: En Jenkins / Manage Jenkins / Global Tool Configuration / Maven Installations. Selecciona la última versión disponible, marca install automatically, y dale un nombre por ejemplo Default Maven. IMPORTANTE: si tienes más de una instalación de maven, en los proyectos de tipo maven tendrás que elegir cual deseas usar a partir del nombre que le hayas dado a cada una de ellas, seleccionandola en una lista desplegable en la sección de build.

  2. La fase de documentación del pipeline da error JAVA_HOME:

    1. Si se muestra el error: An error has occurred in Javadoc report generation: Unable to find javadoc command: The environment variable JAVA_HOME is not correctly set. Debes añadir la variable de entorno JAVA_HOME en la configuración de Jenkins: Jenkins > Manage Jenkins > Configure System > Global properties > Add environment variable. Añade la variable JAVA_HOME con el valor de la ruta de instalación de Java, por ejemplo: /usr/lib/jvm/java-11-openjdk-amd64/