Execució d'inspeccions IntelliJ IDEA a Jenkins

IntelliJ IDEA compta avui amb l'analitzador de codi Java estàtic més avançat, que en les seves capacitats deixa molt enrere "veterans" com ara Estil de control и Spotbugs. Les seves nombroses "inspeccions" comproven el codi en diversos aspectes, des de l'estil de codificació fins als errors típics.

Tanmateix, sempre que els resultats de l'anàlisi només es mostrin a la interfície local de l'IDE del desenvolupador, són de poca utilitat per al procés de desenvolupament. Anàlisi estàtica s'ha de complir Com a primer pas del pipeline de construcció, els seus resultats haurien de definir les portes de qualitat, i la construcció hauria de fallar si no es superen les portes de qualitat. Se sap que TeamCity CI està integrat amb IDEA. Però fins i tot si no feu servir TeamCity, podeu provar fàcilment d'executar inspeccions IDEA a qualsevol altre servidor CI. Us suggereixo que vegeu com es pot fer amb IDEA Community Edition, Jenkins i el connector Warnings NG.

Pas 1. Executeu l'anàlisi al contenidor i obteniu un informe

Al principi, la idea d'executar un IDE (aplicació d'escriptori!) dins d'un sistema CI que no té una interfície gràfica pot semblar dubtosa i molt problemàtica. Afortunadament, els desenvolupadors d'IDEA han proporcionat la possibilitat d'executar-se format del codi и inspeccions des de la línia d'ordres. A més, per executar IDEA en aquest mode, no cal un subsistema gràfic i aquestes tasques es poden realitzar en servidors amb un shell de text.

Les inspeccions s'inicien mitjançant un script bin/inspect.sh des del directori d'instal·lació d'IDEA. Els paràmetres necessaris són:

  • camí complet al projecte (no s'admeten els relatius),
  • camí al fitxer .xml amb la configuració d'inspecció (normalment es troba dins del projecte a .idea/inspectionProfiles/Project_Default.xml),
  • camí complet a la carpeta on s'emmagatzemaran els fitxers .xml amb informes sobre els resultats de l'anàlisi.

A més, s'espera que

  • el camí a l'SDK de Java es configurarà a l'IDE, en cas contrari l'anàlisi no funcionarà. Aquests paràmetres es troben al fitxer de configuració jdk.table.xml a la carpeta de configuració global IDEA. La pròpia configuració global d'IDEA es troba al directori inicial de l'usuari per defecte, però aquesta ubicació es pot especificar explícitament a l'arxiu idea.properties.
  • El projecte analitzat ha de ser un projecte IDEA vàlid, per al qual haureu de comprometre alguns fitxers que normalment s'ignoren al control de versions, és a dir:
    • .idea/inspectionProfiles/Project_Default.xml — Configuració de l'analitzador, òbviament s'utilitzaran quan es realitzin inspeccions al contenidor,
    • .idea/modules.xml - en cas contrari, obtindrem l'error "Aquest projecte no conté mòduls",
    • .idea/misc.xml - en cas contrari, obtindrem l'error "El JDK no està configurat correctament per a aquest projecte",
    • *.iml-файлы — en cas contrari, obtindrem un error sobre un JDK no configurat al mòdul.

Tot i que aquests fitxers solen incloure's a .gitignore, no contenen cap informació específica de l'entorn d'un desenvolupador concret, a diferència, per exemple, d'un fitxer workspace.xml, on conté aquesta informació, i per tant no cal comprometre-la.

La solució òbvia és empaquetar el JDK juntament amb l'edició de la comunitat IDEA en un contenidor d'una forma a punt per ser "encaixat" als projectes analitzats. Triem un contenidor base adequat, i això és el que serà el nostre Dockerfile:

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

Utilitzant l'opció idea.config.path vam forçar IDEA a buscar la seva configuració global a la carpeta /etc/idea, perquè la carpeta d'inici de l'usuari quan treballa en CI és una cosa incerta i sovint està completament absent.

Aquest és el que sembla el fitxer copiat al contenidor: jdk.table.xml, que conté els camins a OpenJDK instal·lats dins del contenidor (es pot prendre com a base un fitxer similar del vostre propi directori amb la configuració d'IDEA):

jdk.table.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>

La imatge acabada disponible a Docker Hub.

Abans de continuar, comprovem que l'analitzador IDEA s'està executant al contenidor:

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

L'anàlisi s'hauria d'executar correctament i nombrosos fitxers .xml amb informes de l'analitzador haurien d'aparèixer a la subcarpeta target/idea_inspections.

Ara ja no hi ha cap dubte que l'analitzador IDEA es pot executar autònom en qualsevol entorn CI, i passem al segon pas.

Pas 2. Mostra i analitza l'informe

Obtenir l'informe en forma de fitxers .xml és la meitat de la batalla; ara cal que sigui llegible pels humans. I també els seus resultats s'han d'utilitzar en les portes de qualitat: la lògica per determinar si el canvi acceptat passa o falla segons criteris de qualitat.

Això ens ajudarà Connector NG d'advertències de Jenkins, que es va publicar el gener de 2019. Amb la seva aparició, molts connectors individuals per treballar amb resultats d'anàlisi estàtica a Jenkins (CheckStyle, FindBugs, PMD, etc.) ara es marquen com a obsolets.

El connector consta de dues parts:

  • nombrosos col·leccionistes de missatges de l'analitzador (la llista completa inclou tots els analitzadors coneguts per la ciència des d'AcuCobol fins a ZPT Lint),
  • un únic visualitzador d'informes per a tots ells.

La llista de coses que Warnings NG pot analitzar inclou advertències del compilador Java i advertències dels registres d'execució de Maven: encara que són visibles constantment, poques vegades s'analitzen específicament. Els informes IntelliJ IDEA també s'inclouen a la llista de formats reconeguts.

Com que el connector és nou, inicialment interactua bé amb Jenkins Pipeline. El pas de creació amb la seva participació tindrà aquest aspecte (només li indiquem al connector quin format d'informe reconeixem i quins fitxers s'han d'escanejar):

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 interfície d'informe té aquest aspecte:

Execució d'inspeccions IntelliJ IDEA a Jenkins

Convenientment, aquesta interfície és universal per a tots els analitzadors reconeguts. Conté un diagrama interactiu de distribució de les troballes per categories i un gràfic de la dinàmica dels canvis en el nombre de troballes. Podeu fer una cerca ràpida a la graella de la part inferior de la pàgina. L'únic que no va funcionar correctament per a les inspeccions d'IDEA va ser la possibilitat de navegar pel codi directament a Jenkins (tot i que per a altres informes, per exemple, Checkstyle, aquest connector ho pot fer molt bé). Sembla que es tracta d'un error a l'analitzador d'informes IDEA que s'ha de solucionar.

Entre les característiques de Warnings NG hi ha la capacitat d'agregar troballes de diferents fonts en un informe i programar Quality Gates, inclòs un "trinquet" per al conjunt de referència. Hi ha disponible alguna documentació de programació de Quality Gates aquí - tanmateix, no està complet, i cal mirar el codi font. D'altra banda, per a un control complet sobre el que està passant, el "trinquet" es pot implementar de manera independent (vegeu el meu publicació anterior sobre aquest tema).

Conclusió

Abans de començar a preparar aquest material, vaig decidir buscar: algú ja ha escrit sobre aquest tema a Habré? Només vaig trobar entrevista 2017 с llanyon diu:

Pel que jo sé, no hi ha integració amb Jenkins o un complement expert […] En principi, qualsevol entusiasta podria fer amistat amb IDEA Community Edition i Jenkins, molts només es beneficiaran d'això.

Bé, dos anys després tenim el connector Warnings NG, i finalment aquesta amistat s'ha fet realitat!

Font: www.habr.com

Afegeix comentari