- PVSM.RU - https://www.pvsm.ru -
IntelliJ IDEA на сегодня обладает наиболее продвинутым статическим анализатором кода Java, по своим возможностям оставившим далеко позади таких «ветеранов», как Checkstyle [1] и Spotbugs [2]. Её многочисленные «инспекции» проверяют код в различных аспектах, от стиля кодирования до характерных багов.
Однако пока результаты анализа отображаются лишь в локальном интерфейсе IDE разработчика, от них мало пользы для процесса разработки. Статический анализ необходимо выполнять [3] в качестве первого шага конвейера сборки, его результаты должны определять quality gates, а сборка должна фейлиться, если quality gates не пройдены. Известно, что TeamCity CI интегрирован с IDEA. Но даже если вы не используете TeamCity, вы вполне можете попробовать запускать инспекции IDEA в любом другом CI-сервере. Предлагаю посмотреть, как это можно сделать, используя IDEA Community Edition, Jenkins и Warnings NG plugin.
Поначалу затея запускать IDE (десктопное приложение!) внутри CI-системы, не имеющей графического интерфейса, может показаться сомнительной и очень хлопотной. К счастью, разработчики IDEA предоставили возможность запускать форматирование кода [4] и инспекции [5] из командной строки. Причём для запуска IDEA в таком режиме не требуется графическая подсистема и эти задачи можно выполнять на серверах с текстовой оболочкой.
Запуск инспекций осуществляется при помощи скрипта bin/inspect.sh из установочной директории IDEA. В качестве параметров требуются:
Кроме того, ожидается, что
jdk.table.xml в папке глобальной конфигурации IDEA. Сама глобальная конфигурация IDEA по умолчанию лежит в домашней директории пользователя, но это местоположение может быть явно задано [6] в файле idea.properties..idea/inspectionProfiles/Project_Default.xml — настройки анализатора, они явно будут использованы при запуске инспекций в контейнере,.idea/modules.xml — иначе получим ошибку 'This project contains no modules',.idea/misc.xml — иначе получим ошибку 'The JDK is not configured properly for this project',*.iml-файлы — иначе получим ошибку про не настроенный JDK в модуле.Хотя обычно эти файлы включают в .gitignore, они не содержат никакой специфичной для окружения конкретного разработчика информации — в отличие от, например, файла workspace.xml, где такая информация, как раз, содержится, и потому коммитить его не надо.
Сам собою напрашивается выход запаковать JDK вместе с IDEA Community Edition в контейнер в виде, готовом к «натравливанию» на анализируемые проекты. Выберем подходящий базовый контейнер, и вот какой у нас получится 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
При помощи опции idea.config.path мы заставили IDEA искать свою глобальную конфигурацию в папке /etc/idea, т. к. домашняя папка пользователя в условиях работы в CI — вещь неопределённая и зачастую вовсе отсутствующая.
Так выглядит копируемый в контейнер файл jdk.table.xml, в котором прописаны пути к OpenJDK, установленной внутри контейнера (за основу может быть взят аналогичный файл из вашей собственной директории с настройками IDEA):
<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>
Образ в готовом виде доступен на Docker Hub [7].
Перед тем, как двинуться дальше, проверим запуск анализатора IDEA в контейнере:
docker run --rm -v <путь/к/вашему/проекту>:/var/project inponomarev/intellij-idea-analyzer
Анализ должен успешно отработать, а в подпапке target/idea_inspections должны появиться многочисленные .xml-файлы с отчётами анализатора.
Теперь больше нет никаких сомнений в том, что анализатор IDEA может быть запущен в автономном режиме в любом CI-окружении, и мы переходим ко второму шагу.
Получить отчёт в виде .xml-файлов — полдела, теперь его нужно сделать человекочитаемым. А также его результаты должны быть использованы в quality gates — логике определения того, проходит или не проходит принимаемое изменение по критериям качества.
В этом нам поможет Jenkins Warnings NG Plugin [8], релиз которого был сделан в январе 2019 года. С его появлением многие отдельные плагины для работы с результатами статического анализа в Jenkins (CheckStyle, FindBugs, PMD и т. п.) теперь помечены как устаревшие (obsolete).
Плагин состоит из двух частей:
В перечне того, что умеет анализировать Warnings NG, находятся в том числе предупреждения компилятора Java и предупреждения из логов выполнения Maven: хотя они постоянно на виду, их редко когда целенаправленно анализируют. Отчёты IntelliJ IDEA также входят в перечень распознаваемых форматов.
Т. к. плагин новый, он изначально хорошо взаимодействует Jenkins Pipeline. Шаг сборки с его участием будет выглядеть следующим образом (мы просто говорим плагину, какой формат отчёта распознаём и какие файлы следует просканировать):
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')]
)
}
Интерфейс отчёта выглядит так:

Удобно, что этот интерфейс является универсальным для всех распознаваемых анализаторов. Он содержит интерактивную диаграмму распределения находок по категориям и график динамики изменения количества находок. В гриде внизу страницы можно выполнять быстрый поиск. Единственное, что для испекций IDEA не заработало корректно — возможность браузить код непосредственно в Jenkins (хотя для других отчётов, например Checkstyle, этот плагин умеет это делать красиво). Похоже, это баг парсера отчётов IDEA, который предстоит починить.
Среди возможностей Warnings NG — возможность агрегировать в одном отчёте находки из разных источников и программировать Quality Gates, в том числе — «храповик» по референтной сборке. Некоторая документация по программированию Quality Gates доступна здесь [10] — впрочем, она не полная, и приходится смотреть в исходники. С другой стороны, для полного контроля над происходящим «храповик» можно реализовать и самостоятельно (см. мой предыдущий пост [3] на эту тему).
Перед тем, как начать готовить данный материал, я решил поискать: а не писал ли уже кто-нибудь на эту тему на Хабре? Я нашёл лишь интервью 2017 года [11] с lany [12], где он говорит:
Насколько мне известно, интеграции с Jenkins или maven-плагина нету [...] В принципе, любой энтузиаст мог бы подружить IDEA Community Edition и Jenkins, многие бы от этого только выиграли.
Что же: спустя два года у нас есть Warnings NG Plugin, и наконец-то эта дружба осуществилась!
Автор: Иван Пономарев
Источник [13]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/java/316366
Ссылки в тексте:
[1] Checkstyle: http://checkstyle.sourceforge.net/
[2] Spotbugs: https://spotbugs.github.io/
[3] необходимо выполнять: https://habr.com/ru/post/436868/
[4] форматирование кода: https://www.jetbrains.com/help/idea/command-line-formatter.html
[5] инспекции: https://www.jetbrains.com/help/idea/command-line-code-inspector.html
[6] может быть явно задано: https://intellij-support.jetbrains.com/hc/en-us/articles/207240985
[7] доступен на Docker Hub: https://hub.docker.com/r/inponomarev/intellij-idea-analyzer
[8] Jenkins Warnings NG Plugin: https://github.com/jenkinsci/warnings-ng-plugin
[9] полный список: https://github.com/jenkinsci/warnings-ng-plugin/blob/master/SUPPORTED-FORMATS.md
[10] здесь: https://github.com/jenkinsci/warnings-ng-plugin/blob/master/doc/Documentation.md#quality-gate-configuration
[11] интервью 2017 года: https://habr.com/ru/company/jugru/blog/320494
[12] lany: https://habr.com/ru/users/lany/
[13] Источник: https://habr.com/ru/post/450214/?utm_source=habrahabr&utm_medium=rss&utm_campaign=450214
Нажмите здесь для печати.