SonarQube — отличный инструмент для внедрения статического анализа кода в процесс разработки ПО. Он поддерживает как используемую у нас в компании Java, так и большое количество других языков программирования.
На данный момент этот инструмент плотно вошёл в нашу жизнь, следя за единым стилем кода и уберегая от самых разных видов ошибок. Поиск ошибок происходит при сборке на CI или перед принятием pull request в версионное хранилище. Все найденные ошибки отображаются в Web-интерфейсе, где можно изучать их и управлять ими.
Однако беда в том, что удобный Web-интерфейс не означает удобство по устранению найденных замечаний в коде проекта. Для того, чтобы внести исправление, приходится сначала смотреть, в каком именно файле это замечание обнаружено, потом открывать этот файл и только затем вносить исправление. Так-же это приводит к тому, что разработчик узнает о проблеме с очень большим отставанием (иногда анализ в SonarQube может занимать десятки минут), что не способствует поддержанию чистоты кода.
Для того, чтобы облегчить жизнь разработчикам нашей компании, использующим IntelliJ IDEA, я составил инструкцию. А в дальнейшем понял, что она может быть полезной более широкому кругу специалистов, и решил выложить её в публичный доступ.
Так как моя статья — первая в корпоративном блоге НПО «Криста», напишу несколько слов о своей компании.
Поле нашей деятельности — информационные технологии для государственного и муниципального управления. Мы озабочены результативностью государственных реформ, эффективностью деятельности органов власти, качеством государственных услуг, прозрачностью финансовой отчётности, открытостью бюджетных данных для населения и т.д.
История компании началась в Рыбинске. Туристы иногда посещают наш город, путешествуя на теплоходах по Волге. Ищите его на карте рядом с Рыбинским водохранилищем. Современная география наших производственных центров, филиалов и представительств значительно шире, но главный центр НПО «Криста» по-прежнему находится в Рыбинске.
Для начала посмотрим, какие инспекции вообще поддерживает SonarQube. Прежде всего, это собственные инспекции, идущие в поставке по умолчанию. Но, помимо этого, есть ещё и плагины для интеграции нескольких сторонних анализаторов:
- CheckStyle
- Spotbugs (ранее назывался FindBugs, но переименовался вместе с переименованием самого анализатора)
- PMD
Каждую отдельную инспекцию можно настраивать индивидуально, а так-же объединять их в профили, позволяя иметь единый набор инспекций для всего предприятия. Так, у нас в основном профиле активировано более 1200 разных инспекций. Понятно, что ни один человек не в состоянии удержать столько правил в голове, а значит, после каждого этапа написания кода следует этап правки замечаний от SonarQube. И чем короче этот этап, тем он менее болезненный для разработчика. Так как же его можно упростить?
Для решения этой проблемы различные IDE имеют плагины, позволяющие вынимать информацию с сервера SonarQube и отображать её прямо в редакторе кода. В случае с IntelliJ IDEA это, прежде всего, SonarLint — официальный плагин от разработчиков самого SonarQube. Он берёт с сервера только профиль с настройками активных инспекций, а сам анализ делает налету прямо в IDE. Это значительно повышает качество разработки, позволяя сразу видеть все новые замечания и оперативно их исправлять. Но тут есть ложка дёгтя. SonarLint работает исключительно с собственными инспекциями SonarQube, полностью игнорируя все остальные инспекции. Замечаний ни от FindBugs, ни от CheckStyle или PMD вы не увидите. А ведь там может содержаться весьма много ценной информации.
Но не стоит отчаиваться: сервер SonarQube умеет экспортировать настройки для всех анализаторов, а значит, имеется возможность настроить штатные плагины IDEA так, чтобы они выдавали результат, эквивалентный серверному.
Давайте разберёмся с этими настройками по порядку.
Настройка SonarLint
Тут нет никаких хитростей. Идём в настройки IDEA и в разделе Plugins
находим плагин SonarLint и устанавливаем его.
Изначально плагин использует настройки инспекций по умолчанию. Теперь можно перейти в окно плагина и сконфигурировать подключение к серверу SonarQube. Т.к. лучше один раз увидеть, чем сто раз прочитать, то просто приведу серию скриншотов последовательности настройки. Здесь и далее красным будут обведены места, требующие к себе внимания. Это или поля для заполнения, или кнопки, которые требуется нажать, или флаги, которые требуется привести к указанному виду:
Главное — не забыть нажать Update binding
после добавления нового сервера, чтобы плагин загрузил профиль с настройками. Эту кнопку придётся нажимать всякий раз, когда профиль изменится на сервере (добавили/удалили инспекции, изменили их настройки).
Если у вас подключено несколько модулей в один проект IDEA, то в настройках придётся переключаться на конкретный модуль всякий раз, когда вам его надо будет проанализировать на предмет замечаний. Это не очень удобно, но так есть.
Список замечаний будет обновляться автоматически в фоновом режиме всякий раз, когда открывается новый файл или в этот файл вносятся изменения. Если такое поведение нежелательно, то его можно отключить там же, в настройках плагина.
Пример того, как выглядит работа с SonarLint можно увидеть ниже (картинка кликабельна):
Бывают ситуации, когда SonarLint по какой-либо причине отказывается работать. В таком случае в окне самого SonarLint можно перейти на вкладку логов и посмотреть, что случилось. Но, к сожалению, информация в этом логе не всегда понятна и достаточна.
Например, после последнего релиза IntelliJ IDEA (2019.2) у меня перестало работать вот с такой ошибкой:
Очень информативно… И самостоятельно догадаться, как получить больше информации, не получилось.
Ситуацию спас F.A.Q. на сайте SonarQube. Оказывается, в окне SonarLint в IDEA можно изменять уровень логирования ошибок:
Если отметить выбранные пункты, то начнёт появляться более подробный лог, из которого уже можно понять, что происходит:
Ага! Теперь ошибка появилась, и стало понятно, что происходит.
По сути, случился неприятный конфликт версий. Наши приложения до сих пор используют Java 8 и проверяются на SonarQube 7.1. При этом весь производственный процесс завязан на возможности SonarQube анализировать разницу в ошибках между основной веткой разработки и Pull Request'ом.
Но самое неприятное, что с версии SonarQube 7.2 эта функция стала платной, из-за чего мы до сих пор не обновились до последней версии. А поддержка Java 11 была реализована только в SonarQube 7.3.
Ещё одним важным моментом является то, что плагин SonarLint при анализе кода в обязательном порядке компилирует исходники с помощью той JRE, на которой запущена IntelliJ IDEA. Пока IDEA работала на Java 8, у нас было всё хорошо. Но вот когда она в версии 2019.2 перешла на использование Java 11, то всё посыпалось, т. к. по факту происходит компиляция в байткод от Java 11 (class file major version 55), а анализируется той версией анализатора, которая установлена на сервере. Т. е. не поддерживающей этот формат байткода. И это известная проблема.
Видимо, придётся срочно искать пути обновления SonarQube до последней версии. Возможно, с использованием стороннего плагина sonarqube-community-branch-plugin, предлагающего необходимые нам функции.
Выгрузка настроек анализаторов из SonarQube
Для каждого из плагинов, кроме SonarLint, необходимы свои файлы настроек, каждый — в собственном формате. К счастью, SonarQube умеет выгружать эти файлы. Они находятся в окне настройки профиля анализа.
Для того, чтобы туда попасть, необходимо в Web-интерфейсе сервера SonarQube перейти в раздел Quality Profile
и выбрать тот профиль, который используется для анализа проекта:
На открывшейся странице появится раздел, предоставляющий ссылки для экспорта настроек под каждый из анализаторов:
Настройки для FindBugs и PMD необходимо выгрузить на локальный диск с расширением XML
, а вот настройки для CheckStyle можно использовать прямо по URL с сайта.
Настройка CheckStyle
В IDEA плагин называется CheckStyle-IDEA. Это, пожалуй, самый беспроблемный с точки зрения использования плагин, т. к. позволяет загрузить настройки прямо по URL и не требует переключения между модулями, как SonarLint.
Для подключения конфигурации необходимо перейти в настройки IDEA и выбрать раздел CheckStyle
. Далее необходимо добавить новый пункт в таблицу Configuration File
:
И указать источник конфигурации:
Так-же не забываем отметить вновь добавленную конфигурацию как активную в таблице окна настроек.
Всё, теперь можно переходить в окно CheckStyle и запускать анализ (верхняя отмеченная кнопка):
В случае, если профиль на сервере SonarQube поменялся, необходимо обновить настройки путём нажатия соответствующей кнопки в том же окне (нижняя отмеченная кнопка).
В случае ошибки "The Checkstyle rules file could not be parsed", а именно "SuppressionCommentFilter is not allowed as a child in Checker", нужно понизить версию Checkstyle в настройках плагина, которая используется на сервере SonarQube. Соответствие версий можно посмотреть в таблице в описании плагина Checkstyle для SonarQube.
Настройка FindBugs
В IDEA плагин называется FindBugs-IDEA. В отличие от предыдущих рассмотренных плагинов, этот не умеет брать настройки напрямую с сервера и требует наличия локального файла.
Для подключения конфигурации необходимо перейти в настройки IDEA и выбрать раздел FindBugs-IDEA
. Далее на вкладке Filter
добавить новый пункт в таблицу Include filter files
:
Плагин готов к работе. В его окне можно запустить анализ как отдельного файла, так и всего проекта или любого другого скопа на выбор:
Важное замечание 1: в настройках плагина имеется вкладка Share
, в которой предлагается подключить файл настроек SonarQube. Пользоваться этой настройкой не рекомендую, т. к. корректно не заработало, а вот последствия лечатся нетривиально. Дело в том, что просто удаление этой настройки ничего не дало. Плагин не начал работать нормально. Для восстановления работы пришлось удалить файл .idea/findbugs-idea.xml
в каталоге проекта и перенастроить всё заново.
Важное замечание 2: если настройки на сервере SonarQube изменились, то необходимо выгрузить заново на диск.
Важное замечание 3: к огромному сожалению, развитие данного плагина застопорилось после того, как разработка самого FindBugs была переведена в его форк SpotBugs. В багтреккере JetBrains есть тикет на эту тему. Так что если вы наравне с нами захотите полноценную поддержку всех замечаний SonarQube прямо у себя, в любимой IDE, то можно проголосовать за этот тикет. Может, телега-таки сдвинется с места.
Настройка PMD
В IDEA плагин называется PMDPlugin. Аналогично с FindBugs, этот плагин требует наличия файла настроек на диске. Для конфигурирования идём в настройки IDEA и добавляем файл, выгруженный из SonarQube:
Имя файла играет важную роль, т. к. в дальнейшем оно будет использовано плагином для формирования соответствующего пункта меню для запуска анализа.
Также в соседней вкладе необходимо указать ту версию Java, которую использует проект (ну, и кодировку заодно):
Теперь можно запустить анализ текущего файла, воспользовавшись контекстным меню:
Run PMD->Custom Rules-><Имя файла настроек>
Важное замечание 1: PMD можно так-же запустить через главное меню, но делать это не рекомендуется, т. к. в этом случае проверке подвергнется не один файл, а весь открытый в IDE проект. Это может занять много времени и значительно перегрузить систему.
Важное замечание 2: как и FindBugs, PMD требует наличия файла конфигурации на диске. Следовательно, необходимо обновлять его каждый раз, когда настройки профиля SonarQube меняются.
Заключение
Резюмируя сказанное, отмечу следующее. Несмотря на то, что для отслеживания замечаний приходится управлять настройками целых 4-х плагинов, это всё же лучше, чем каждый раз ждать, пока результаты редактирования появятся на сервере SonarQube, и позволяет сразу коммитить более чистый код.
Надеюсь, что изложенная здесь информация поможет кому-нибудь легче подружиться со статическими анализаторами вообще и с SonarQube в частности.
Так же хочу поблагодарить коллег, помогавших мне с написанием и поддержкой актуальности этой статьи: Дмитрия Зимичева, Юрия Крупина и Артёма Ганева.