SonarQube – попытка обуздать техдолг?
Мотивация
Большой продукт сложен в поддержке и сколько разработчиков не бери, всё равно качество кода будет страдать.
Технический долг - это как невыплаченный кредит: когда разработчики берут "заем" времени, выбирая быстрые и простые решения для достижения цели, но забывают вернуть его обратно, оставляя за собой задолженность в виде неоптимизированного кода.
Например, это может быть копипаст кода вместо создания повторно используемых функций или игнорирование необходимости написания тестов для обеспечения корректной работы кода, что в итоге увеличивает время и затраты на исправление проблем в будущем.
Поговорим о том как контроллировать техдолг.
Основная информация
SonarQube - это инструмент для статического анализа кода, позволяет автоматизировать процесс обнаружения проблем в коде, таких как потенциальные ошибки, нарушения стандартов кодирования, пропущенные возможности оптимизации и другие виды нарушений.
- Выявление потенциальных ошибок, такие как неправильное использование переменных, типов или функций.
- Поддержание стандартов кодирования.
- Анализ производительности, обнаружение участков кода, которые могут вызвать утечки памяти или замедлить производительность приложения.
- Управление техническим долгом, контроль метрик. Также с помощью плагинов, можно например ставить задачи в Jira на исправление участка кода.
- Сохраняет историю метрик качества кода
- Интеграция с IDE, Jira
Отличие от линтеров
Основная задача линтера — это проверка кода на соответствие определенным стилям и правилам программирования, таким как отступы, использование пробелов, нейминг переменных и т.д.
Статический анализ кода ориентирован на более широкий аспект анализа кода, включая выявление ошибок, определение потенциальных уязвимостей безопасности, анализ архитектуры и т.д.
Почему не хватит ESLint, TSLint, Stylelint?
Например для ESLint можно подключить плагин eslint-plugin-sonarjs, который также сможет обнаруживать баги, code smells и т.д.
Но теряется главное преимущество SonarQube – отслеживание эволюции кода в дашбордах с настройкой quality gate и подсвечиванием проблем в динамике.
Также, ESLint, TSLint, Stylelint заточены на определенные языковые эвристики, а SonarQube оценивает картину целиком, например, может найти утекший секрет в CI-конфигурации. Покрыть такой кейс линтером довольно сложно.
Линтеры являются хорошим инструментом, но они должны использоваться в сочетании с другими практиками и инструментами, такими как код-ревью, тестирование (e2e, sl, unit), анализ безопасности и регулярную работу над техдолгом, чтобы обеспечить достойное качество кода на протяжении всего жизненного цикла продукта.
Аналоги и альтернативы
Среди похожих решение есть CodeScene, CodeCov. Также есть статические анализаторы вроде PVS Studio, но он не работает с экосистемой JS/TS.
CodeScene выделяется своей способностью анализа эволюции кода и предсказания будущих изменений. Но к сожалению, у него нет Community Edition (бесплатен для open source) и для получения ключа нужен VPN (не работает в РФ).
CodeCov больше про покрытие кода тестами.
Поэтому SonarQube является более выигрышным из-за Community Edition, а также обширного набор инструментов для оценки качества кода, покрытия и т.д.
Плюсы и минусы
- Статический анализ кода – выявляет ошибки, code smells и потенциальные уязвимости.
- Множество поддерживаемых языков (зависит от версии - community, developer, enterprise, data)
- Интеграция с CI системами
- Дашборды и отчеты
- Интеграция сторонних линтеров
- Ресурсозатратность – запуск полного анализа проекта может занимать длительное время
- Сложность настройки – перед внедрением нужно тщательно обдумать какие папки анализировать, какие исключить из анализы, подкрутить правила. Также присутствует некоторая специфичность к версии Java.
- Не всегда точные результаты – результаты анализы могут давать ложные срабатывания или пропуски, и иногда требуется ручная проверка.
- Слабая ролевая модель – довольно неудобно настраивать права доступа, назначать фикс багов на определенных людей
Экосистема
У SonarQube отличная экосистема плагинов как платных, так и бесплатных.
Например, интеграция с Jira, PDF-отчеты. Есть на что посмотреть.
sonarqube-community-branch-plugin
В Community Edition нет анализа веток. Но можно использовать плагин sonarqube-community-branch-plugin.
С помощью плагина sonar-gitlab-plugin можно оставлять комментарии к МР.
Интеграция с IDE
Плагин SonarLint доступен во всех популярных редакторах кода.
На примере VS Code, в данном случае редактор подсветит ошибку с подробным описанием, так же можно перейти прямо в анализатор в браузере и проверить историю.
Отличия версий
У SonarQube есть несколько версий. Подробнее о разнице версий тут.
- Community Edition
- Статический анализ кода для 19 языков
- Обнаружение ошибок и базовых уязвимостей
- Ревью security hotspots
- Отслеживание code smells и техдолга
- Метрики code quality и истории
- Интеграция CI/CD
- Плагины от сообщества
- Developer Edition
- Поддержка C, C++, Swift, Objective C, T-SQL, PL/SQL.
- Обнаружение сложных ошибок и уязвимостей
- Обнаружение ошибок крашей Python/Java
- Анализ Merge Requests
- Enterprise Edition
- Data Center Edition
Типовые проблемы кодовой базы
Команда Sonarqube выделяет несколько "грехов" разработчиков:
- Баги и потенциальные баги
- Нарушение стандартов кодирования
- Дублирование кода
- Недостаточное покрытие модульными тестами
- Плохое распределение сложности
- Спагетти-дизайн
- Недостаточно или слишком много комментариев
Посмотрим, как SonarQube отслеживает эти проблемы.
Метрики SonarQube
В каждом анализе SonarQube есть несколько метрик.
Метрики оцениваются по шкале A до E, где E - наихудший рейтинг, говорящий о том, что был найден минимум один блокирующий баг.
Issues (Найденные проблемы)
Показывает найденные проблемы в коде
- 🐞 Bug — приоритетные ошибки, которые нужно исправить как можно скорее
- 💩 Code smell — незначительные огрехи, которые больше относятся к культуре кода и его оформлению
- 🔒 Vulnerability – уязвимости, связанные с безопасностью.
- 🛡️ Security HotSpot - потенциальные точки уязвимости
У каждой ошибки есть состояния:
Security (Безопасность)
Это отдельная вкладка где собрана информация о количестве уязвимостей и их рейтинге безопасности (от A до E). Подробнее тут.
- A = 0 проблем
- B = как минимум 1 Minor проблема
- C = как минимум 1 Major проблема
- D = как минимум 1 Critical проблема
- E = как минимум 1 Blocker проблема
Reliability (Надежность)
SonarQube анализирует код на предмет надежности, выявляя проблемы, которые могут привести к сбоям, ошибкам выполнения, или другим нежелательным результатам при работе программы.
Maintainability (Поддерживаемость)
Во вкладке Measures в разделе Maintainability содержится информация о техническом долге в проекте.
Coverage (Покрытие тестами)
Во вкладке Measures в разделе Coverage собрана информация о покрытии кода тестами.
Duplications (Дублирование)
Во вкладке Measures в разделе Duplications можно найти информацию о наличии дублирующегося кода.
Настройка исключений для дублей
При настройке проекта нужно подумать над тем какие кейсы могут быть ложно-положительными и настройте исключения для них.
К таким же исключениям потенциально можно отнести любой автоген который хранится в репозитории, например, GQL-схемы.
Настройка проекта
Quality Profile (Профиль качества):
- Это набор правил статического анализа кода, определяющий ожидаемый стандарт качества кода.
- Включает в себя набор правил по стилю кода, безопасности, производительности и другим аспектам.
- Позволяет настроить параметры анализа для конкретного проекта или команды разработчиков.
Quality Gate (Контроль качества):
- Это набор условий, которые определяют уровень качества кода, который необходим для успешного прохождения анализа.
- Включает в себя метрики, такие как покрытие кода тестами, процент дублирования кода, количество критических ошибок и т. д.
- Если код не соответствует установленным критериям качества, Quality Gate не проходит, и разработчики получают уведомления о необходимости исправлений.
Список правил
У SonarQube есть готовые правила валидации для разных языков. Основные правила работают из коробки.
Правила – это набор валидаций которые помогают найти баги, "code smells" и проблемы безопасности в ходе статистического анализа.
Также можно добавлять свои правила (подробнее тут).
Интеграция сторонних линтеров
Для улучшения качества репортов SonarQube можно дать ему больше информации, например отчеты Stylelint, ESLint, TSLint через параметры.
Подробнее в документации.
Создание проекта в SonarQube
В UI SonarQube в разделе создания проекта, укажите ключ и название проекта.
Рекомендация: ключ должен совпадать с путем в Gitlab/Github. Например, путь в Gitlab gitlab.com/frontend/awesome-project, значит ключ awesome-project.
Создание токена
Рекомендация: используйте формат sonar-token-{PROJECT_KEY}. Например, sonar-token-awesome-project.
Настройка репозитория
Добавьте в .gitignore игнор файлов результатов анализа SonarQube.
# SonarQube .sonar/ .scannerwork/
В корне репозитория нужно создать файл sonar-project.properties. В нем указываются основные проекты, такие как хост SonarQube, название и ключ проекта, папки для сканирования.
Описание всех параметров можно найти тут.
# Хост SonarQube sonar.host.url=https://sonarqube.company.domain # Ключ и название проекта sonar.projectKey=awesome-project sonar.projectName=awesome-project # Список относительных путей, где хранится исходный код sonar.sources=src # Кодировка для проекта, обычно UTF-8 sonar.sourceEncoding=UTF-8 # Список относительных путей, которые необходимо исключить для анализа sonar.exclusions= # Список относительных путей, где хранятся тесты sonar.tests= # Ожидание завершения анализа на сервере (пригодится для вебхуков) sonar.qualitygate.wait=true
Настройка в Gitlab CI
Это пример настройки в Gitlab CI.
Переменные sonar.login, sonar.projectVersion, sonar.projectDate передаются через аргументы CLI.
- sonar.login – токен, полученный при создании проекта в SonarQube.
- sonar.projectVersion – тег релиза, например
CI_COMMIT_TAG
- sonar.projectDate – уникальная дата релиза. SonarQube выдаст ошибку если дата актуальной статы старше последней существующей статы. Например релизы 36.0.0 и 36.0.1 сделаны 01.10.2024, в таком случае SonarQube выдаст ошибку
Validation of project failed: Date of analysis cannot be older than the date
of the last known analysis on this project. Value: "2023-10-01T07:02:00+0000". Latest analysis: "2024-10-01T07:01:57+0000". It's only possible to rebuild the past in
a chronological order.
sonarqube-check: stage: check tags: - prod image: name: sonarsource/sonar-scanner-cli:4.8.1 entrypoint: [''] cache: key: '${CI_JOB_NAME}' paths: - .sonar/cache variables: SONAR_USER_HOME: '${CI_PROJECT_DIR}/.sonar' GIT_DEPTH: '0' script: - current_tag=${CI_COMMIT_TAG} - echo $current_tag - current_date=$(date -u +"%Y-%m-%dT%H:%M:%S%z") - echo $current_date - sonar-scanner -Dsonar.login=${SONAR_LOGIN} -Dsonar.projectVersion=$current_tag -Dsonar.projectDate=$current_date allow_failure: true rules: - if: $CI_COMMIT_BRANCH == "master"
Генерация истории статов
Для того чтобы сразу начать работу с техдолгом, нужно сгенерировать историю отчетов.
Для этого написан скрипт, который переходит в указанный репозиторий, перемещается по тегам релизов и сканирует релизы через sonar-scanner
.
Сохраните скрипт index.js
в любую папку на компьютере и выполните:
npm init npm i simple-git
В переменной repositoryPath
указывается путь до репозитория проекта.
В переменной sonarScannerCliPath
указывается путь до sonar-scanner-cli
. Скачать можно тут.
В объекте config указывается основная информация
- sonar.host.url - хост SonarQube
- sonar.login - токен проекта SonarQube
- sonar.projectKey - ключ проекта
- sonar.projectName - название проекта (рекомендую чтобы совпадал с ключом)
- sonar.sources - папки для сканирования
Далее для начала генерации отчетов запустите скрипт.
Если релизов много, скрипт может выполняться несколько часов. После этого в дашборде появится стата по каждому релизу.
Интеграция через вебхуки
А с помощью вебхуков можно настраивать различные автоматизации. Например, отчет о проверке релиза в чат команды.
На этом всё, надеюсь статья была полезной.
Если вам было интересно, подписывайтесь на телеграм-канал @trash_js – там я пишу более короткие заметки об экосистеме фронтенда и frontops. 🎩