Ejecute IntelliJ IDEA Inspecciones en Jenkins

IntelliJ IDEA cuenta hoy con el analizador de código Java estático más avanzado que, en cuanto a sus capacidades, ha dejado muy atrás a "veteranos" como estilo de cuadros и chinches. Sus numerosas "inspecciones" verifican el código en varios aspectos, desde el estilo de codificación hasta los errores característicos.

Sin embargo, mientras los resultados del análisis se muestren solo en el IDE local del desarrollador, son de poca utilidad para el proceso de desarrollo. Análisis estático debe llevarse a cabo como primer paso de la tubería de construcción, sus resultados deben determinar las puertas de calidad, y la construcción debe fallar si fallan las puertas de calidad. Se sabe que TeamCity CI está integrado con IDEA. Pero incluso si no está utilizando TeamCity, aún puede intentar ejecutar las inspecciones de IDEA en cualquier otro servidor de CI. Propongo ver cómo se puede hacer esto usando IDEA Community Edition, Jenkins y el complemento Warnings NG.

Paso 1. Ejecute el análisis en un contenedor y obtenga un informe

Al principio, la idea de ejecutar un IDE (¡aplicación de escritorio!) dentro de un sistema CI que no tiene una interfaz gráfica puede parecer dudosa y muy problemática. Afortunadamente, los desarrolladores de IDEA han proporcionado la capacidad de ejecutar formato de código и inspección desde la línea de comandos. Además, para ejecutar IDEA en este modo, no se requiere un subsistema gráfico y estas tareas se pueden realizar en servidores con un shell de texto.

Las inspecciones se inician mediante un script. bin/inspect.sh desde el directorio de instalación de IDEA. Los parámetros requeridos son:

  • ruta completa al proyecto (los relativos no son compatibles),
  • ruta al archivo .xml con la configuración de inspección (generalmente ubicado dentro del proyecto en .idea/inspectionProfiles/Project_Default.xml),
  • ruta completa a la carpeta donde se almacenarán los archivos .xml con los informes de resultados de análisis.

Además, se espera que

  • la ruta al SDK de Java se configurará en el IDE, de lo contrario, el análisis no funcionará. Estos ajustes están contenidos en el archivo de configuración. jdk.table.xml en la carpeta de configuración global de IDEA. La propia configuración de IDEA global predeterminada está en el directorio de inicio del usuario, pero esta ubicación se puede establecer explícitamente en archivo idea.properties.
  • el proyecto analizado debe ser un proyecto IDEA válido, para lo cual algunos archivos que normalmente se ignoran deberán ser comprometidos con el control de versiones, a saber:
    • .idea/inspectionProfiles/Project_Default.xml — ajustes del analizador, obviamente se utilizarán al iniciar inspecciones en un contenedor,
    • .idea/modules.xml - de lo contrario obtenemos el error 'Este proyecto no contiene módulos',
    • .idea/misc.xml - de lo contrario, obtenemos el error 'El JDK no está configurado correctamente para este proyecto',
    • *.iml-файлы - de lo contrario, obtendremos un error sobre un JDK no configurado en el módulo.

Aunque estos archivos suelen estar incluidos en .gitignore, no contienen ninguna información específica del entorno de un desarrollador en particular, a diferencia, por ejemplo, de un archivo workspace.xml, donde tal información, justamente, está contenida, y por lo tanto no es necesario comprometerla.

Por sí mismo, la salida sugiere empaquetar el JDK junto con IDEA Community Edition en un contenedor en un formulario listo para ser "establecido" en los proyectos analizados. Elijamos un contenedor base adecuado, y aquí está el Dockerfile que obtenemos:

Dockerfile

FROM openkbs/ubuntu-bionic-jdk-mvn-py3

ARG INTELLIJ_VERSION="ideaIC-2019.1.1"

ARG INTELLIJ_IDE_TAR=${INTELLIJ_VERSION}.tar.gz

ENV IDEA_PROJECT_DIR="/var/project"

WORKDIR /opt

COPY jdk.table.xml /etc/idea/config/options/

RUN wget https://download-cf.jetbrains.com/idea/${INTELLIJ_IDE_TAR} && 
    tar xzf ${INTELLIJ_IDE_TAR} && 
    tar tzf ${INTELLIJ_IDE_TAR} | head -1 | sed -e 's//.*//' | xargs -I{} ln -s {} idea && 
    rm ${INTELLIJ_IDE_TAR} && 
    echo idea.config.path=/etc/idea/config >> idea/bin/idea.properties && 
    chmod -R 777 /etc/idea

CMD idea/bin/inspect.sh ${IDEA_PROJECT_DIR} ${IDEA_PROJECT_DIR}/.idea/inspectionProfiles/Project_Default.xml ${IDEA_PROJECT_DIR}/target/idea_inspections -v2

Usando la opción idea.config.path hicimos que IDEA buscara su configuración global en la carpeta /etc/idea, ya que la carpeta de inicio del usuario en las condiciones de trabajo en CI es una cosa indefinida y muchas veces completamente ausente.

Así es como se ve el archivo copiado en el contenedor jdk.table.xml, que contiene las rutas al OpenJDK instalado dentro del contenedor (puede basarse en un archivo similar de su propio directorio de configuración de IDEA):

jdk.tabla.xml

<application>
 <component name="ProjectJdkTable">
   <jdk version="2">
     <name value="1.8" />
     <type value="JavaSDK" />
     <version value="1.8" />
     <homePath value="/usr/java" />
     <roots>
       <annotationsPath>
         <root type="composite">
           <root url="jar://$APPLICATION_HOME_DIR$/lib/jdkAnnotations.jar!/" type="simple" />
         </root>
       </annotationsPath>
       <classPath>
         <root type="composite">
           <root url="jar:///usr/java/jre/lib/charsets.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/deploy.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/ext/access-bridge-64.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/ext/cldrdata.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/ext/dnsns.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/ext/jaccess.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/ext/jfxrt.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/ext/localedata.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/ext/nashorn.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/ext/sunec.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/ext/sunjce_provider.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/ext/sunmscapi.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/ext/sunpkcs11.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/ext/zipfs.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/javaws.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/jce.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/jfr.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/jfxswt.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/jsse.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/management-agent.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/plugin.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/resources.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/rt.jar!/" type="simple" />
         </root>
       </classPath>
     </roots>
     <additional />
   </jdk>
 </component>
</application>

imagen terminada disponible en Docker Hub.

Antes de continuar, probemos la ejecución del analizador IDEA en el contenedor:

docker run --rm -v <путь/к/вашему/проекту>:/var/project inponomarev/intellij-idea-analyzer

El análisis debería funcionar correctamente y deberían aparecer numerosos archivos .xml con informes del analizador en la subcarpeta target/idea_inspections.

Ahora ya no hay duda de que el analizador IDEA se puede ejecutar sin conexión en cualquier entorno de CI, y pasamos al segundo paso.

Paso 2. Mostrar y analizar el informe

Obtener un informe en forma de archivos .xml es la mitad de la batalla, ahora debe ser legible por humanos. Y también sus resultados deben usarse en las puertas de calidad: la lógica para determinar si el cambio aceptado pasa o no pasa de acuerdo con los criterios de calidad.

esto nos ayudara Complemento NG de advertencias de Jenkinsque se lanzó en enero de 2019. Con su introducción, muchos complementos separados para trabajar con resultados de análisis estáticos en Jenkins (CheckStyle, FindBugs, PMD, etc.) ahora están marcados como obsoletos.

El complemento consta de dos partes:

  • numerosos recopiladores de mensajes del analizador (la lista completa incluye todos los analizadores conocidos por la ciencia desde AcuCobol hasta ZPT Lint),
  • un único visor de informes para todos ellos.

La lista de cosas que puede analizar Warnings NG incluye advertencias del compilador de Java y advertencias de los registros de ejecución de Maven: aunque están constantemente a la vista, rara vez se analizan a propósito. Los informes de IntelliJ IDEA también se incluyen en la lista de formatos reconocidos.

Dado que el complemento es nuevo, inicialmente interactúa bien con Jenkins Pipeline. El paso de compilación con su participación se verá así (solo le decimos al complemento qué formato de informe reconocemos y qué archivos deben escanearse):

stage ('Static analysis'){
    sh 'rm -rf target/idea_inspections'
    docker.image('inponomarev/intellij-idea-analyzer').inside {
       sh '/opt/idea/bin/inspect.sh $WORKSPACE $WORKSPACE/.idea/inspectionProfiles/Project_Default.xml $WORKSPACE/target/idea_inspections -v2'
    }
    recordIssues(
       tools: [ideaInspection(pattern: 'target/idea_inspections/*.xml')]
    )
}

La interfaz del informe se ve así:

Ejecute IntelliJ IDEA Inspecciones en Jenkins

Es conveniente que esta interfaz sea universal para todos los analizadores reconocibles. Contiene un gráfico interactivo de la distribución de hallazgos por categoría y un gráfico de la dinámica de cambios en el número de hallazgos. En la cuadrícula en la parte inferior de la página, puede realizar una búsqueda rápida. Lo único que no funcionó correctamente para las inspecciones de IDEA fue la capacidad de explorar el código directamente en Jenkins (aunque para otros informes, como Checkstyle, este complemento puede hacerlo maravillosamente). Parece ser un error en el analizador de informes de IDEA que debe corregirse.

Entre las características de Warnings NG está la capacidad de agregar hallazgos de diferentes fuentes en un informe y programar Quality Gates, incluido un "trinquete" para un conjunto de referencia. Parte de la documentación de programación de Quality Gates está disponible aquí - sin embargo, no está completo, y tienes que mirar la fuente. Por otro lado, para un control completo sobre lo que está sucediendo, el "trinquete" se puede implementar de forma independiente (ver mi antes de la publicación sobre este tema).

Conclusión

Antes de empezar a preparar este material, decidí mirar: ¿alguien ya ha escrito sobre este tema en Habré? solo encontré entrevista 2017 с lanyEn donde dice:

Hasta donde yo sé, no hay integración con Jenkins o un complemento maven [...] En principio, cualquier entusiasta podría hacer amigos de IDEA Community Edition y Jenkins, muchos solo se beneficiarían de esto.

Bueno, después de dos años tenemos el complemento Warnings NG, ¡y finalmente esta amistad se ha hecho realidad!

Fuente: habr.com

Añadir un comentario