IntelliJ IDEA dispose aujourd'hui de l'analyseur de code Java statique le plus avancé, qui dans ses capacités a laissé loin derrière des "vétérans" comme Checkstyle et Spotbugs . Ses nombreuses «inspections» vérifient le code sous divers aspects, du style de codage aux bogues caractéristiques.
Cependant, bien que les résultats d'analyse ne soient affichés que dans l'interface locale de l'IDE du développeur, ils sont peu utiles pour le processus de développement. L'analyse statique doit être effectuée comme première étape du pipeline d'assemblage, ses résultats doivent déterminer les portes de qualité et l'assemblage doit échouer si les portes de qualité ne sont pas réussies. TeamCity CI est connu pour être intégré à IDEA. Mais même si vous n'utilisez pas TeamCity, vous pouvez très bien essayer d'exécuter des inspections IDEA sur n'importe quel autre serveur CI. Je propose de voir comment cela peut être fait en utilisant le plugin IDEA Community Edition, Jenkins et Warnings NG.
Étape 1. Exécutez l'analyse dans le conteneur et obtenez un rapport
Au départ, l'idée de démarrer un IDE (application de bureau!) À l'intérieur d'un système CI qui n'a pas d'interface graphique peut sembler douteuse et très gênante. Heureusement, les développeurs d'IDEA ont fourni la possibilité d'exécuter le formatage du code et des inspections à partir de la ligne de commande. De plus, pour exécuter IDEA dans ce mode, aucun sous-système graphique n'est requis et ces tâches peuvent être effectuées sur des serveurs avec un shell de texte.
Les inspections sont lancées à l'aide du bin/inspect.sh
du répertoire d'installation IDEA. Comme les paramètres sont requis:
- chemin complet vers le projet (parent non pris en charge)
- chemin d'accès au fichier .xml avec les paramètres d'inspection (généralement situé à l'intérieur du projet dans .idea / inspectionProfiles / Project_Default.xml),
- chemin d'accès complet au dossier dans lequel les fichiers .xml contenant des rapports sur les résultats de l'analyse seront ajoutés.
En outre, il est prévu que
- l'IDE configurera le chemin vers le SDK Java, sinon l'analyse ne fonctionnera pas. Ces paramètres sont contenus dans le fichier de configuration
jdk.table.xml
dans le dossier de configuration globale IDEA. La configuration globale d'IDEA elle-même se trouve par défaut dans le répertoire personnel de l'utilisateur, mais cet emplacement peut être explicitement spécifié dans le fichier idea.properties
. - le projet analysé doit être un projet IDEA valide, pour lequel le contrôle de version devra valider certains fichiers qui sont généralement ignorés, à savoir:
.idea/inspectionProfiles/Project_Default.xml
- paramètres de l'analyseur, ils seront évidemment utilisés lors du démarrage des inspections dans le conteneur,.idea/modules.xml
- sinon nous obtenons l'erreur 'Ce projet ne contient aucun module',.idea/misc.xml
- sinon nous obtenons l'erreur 'Le JDK n'est pas configuré correctement pour ce projet',*.iml-
- sinon nous obtenons une erreur sur un JDK non configuré dans le module.
Bien que ces fichiers soient généralement inclus dans .gitignore
, ils ne contiennent aucune information spécifique à l'environnement d'un développeur particulier - contrairement, par exemple, au fichier workspace.xml
, où ces informations sont contenues, et il n'est donc pas nécessaire de les valider.
Lui-même demande un moyen d'emballer le JDK avec IDEA Community Edition dans un conteneur sous une forme prête à "définir" les projets analysés. Nous allons sélectionner le conteneur de base approprié, et voici le Dockerfile que nous obtenons:
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
En utilisant l'option idea.config.path
nous avons forcé IDEA à rechercher sa configuration globale dans le dossier /etc/idea
, car le dossier de départ de l'utilisateur dans les conditions CI est une chose indéfinie et souvent complètement absente.
Voici à quoi jdk.table.xml
fichier jdk.table.xml
copié dans le conteneur, dans lequel les chemins vers OpenJDK installés à l'intérieur du conteneur sont écrits (un fichier similaire de votre propre répertoire avec les paramètres IDEA peut être pris):
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>
L'image finie est disponible sur le Docker Hub .
Avant de continuer, vérifiez le démarrage de l'analyseur IDEA dans le conteneur:
docker run --rm -v <///>:/var/project inponomarev/intellij-idea-analyzer
L'analyse doit fonctionner correctement et de nombreux fichiers .xml contenant des rapports d'analyseur doivent apparaître dans le sous-dossier target / idea_inspections.
Maintenant, il ne fait plus aucun doute que IDEA peut être exécuté hors ligne dans n'importe quel environnement CI, et nous passons à la deuxième étape.
Étape 2. Affichez et analysez le rapport
Obtenir un rapport sous forme de fichiers .xml est la moitié de la bataille, vous devez maintenant le rendre lisible par l'homme. Et ses résultats devraient également être utilisés dans les portes de qualité - la logique de déterminer si un changement accepté passe ou non selon les critères de qualité.
Cela nous aidera à utiliser le plugin Jenkins Warnings NG , qui a été publié en janvier 2019. Avec son apparence, de nombreux plugins individuels pour travailler avec les résultats de l'analyse statique dans Jenkins (CheckStyle, FindBugs, PMD, etc.) sont désormais marqués comme obsolètes.
Le plugin se compose de deux parties:
- de nombreux collecteurs de messages d'analyseurs (la liste complète comprend tous les analyseurs connus d'AcuCobol à ZPT Lint),
- un seul spectateur pour chacun d'eux.
La liste de ce que Warnings NG peut analyser comprend des avertissements du compilateur Java et des avertissements des journaux d'exécution de Maven: bien qu'ils soient constamment en vue, ils sont rarement analysés de manière ciblée. Les rapports IntelliJ IDEA sont également inclus dans la liste des formats reconnus.
Étant donné que le plugin est nouveau, il interagit initialement bien avec Jenkins Pipeline. L'étape d'assemblage avec sa participation ressemblera à ceci (nous indiquons simplement au plug-in quel format de rapport nous reconnaissons et quels fichiers doivent être analysés):
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')] ) }
L'interface de rapport ressemble à ceci:

Idéalement, cette interface est universelle pour tous les analyseurs reconnus. Il contient un diagramme interactif de la répartition des trouvailles par catégorie et un graphique de la dynamique des changements dans le nombre de trouvailles. Dans la grille en bas de la page, vous pouvez effectuer une recherche rapide. La seule chose que IDEA n'a pas fonctionné pour l'inspection était la possibilité de parcourir le code directement dans Jenkins (bien que pour d'autres rapports, par exemple Checkstyle, ce plugin puisse le faire magnifiquement). Cela semble être un bug de l'analyseur de rapports IDEA à corriger.
Parmi les capacités de Warnings NG, il y a la possibilité d'agréger les découvertes provenant de différentes sources dans un seul rapport et de programmer des portes de qualité, y compris un cliquet pour l'assemblage de référence. Une documentation de programmation Quality Gates est disponible ici - cependant, elle n'est pas complète, et vous devez regarder la source. D'un autre côté, pour un contrôle total sur ce qui se passe, le «cliquet» peut être implémenté indépendamment (voir mon post précédent sur ce sujet).
Conclusion
Avant de commencer à préparer ce matériel, j'ai décidé de chercher: quelqu'un a-t-il déjà écrit sur ce sujet à Habré? Je n'ai trouvé qu'une interview de 2017 avec Lany où il dit:
Pour autant que je sache, il n'y a pas d'intégration avec Jenkins ou le plugin maven [...] En principe, tout passionné pourrait se faire des amis IDEA Community Edition et Jenkins, beaucoup en bénéficieraient.
Eh bien: deux ans plus tard, nous avons le plugin Warnings NG, et enfin cette amitié est devenue réalité!