IT
April 4, 2024

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

С помощью плагина 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
    • PDF-отчеты
    • Отчеты безопасности
    • Нормативные отчеты
    • Параллельная обработка репортов
  • Data Center Edition
    • Горизонтальное масштабирование
    • Улучшенный перфоманс и high load
Разница в одной картинке

Типовые проблемы кодовой базы

Команда Sonarqube выделяет несколько "грехов" разработчиков:

  • Баги и потенциальные баги
  • Нарушение стандартов кодирования
  • Дублирование кода
  • Недостаточное покрытие модульными тестами
  • Плохое распределение сложности
  • Спагетти-дизайн
  • Недостаточно или слишком много комментариев

Посмотрим, как SonarQube отслеживает эти проблемы.

Метрики SonarQube

В каждом анализе SonarQube есть несколько метрик.

Метрики оцениваются по шкале A до E, где E - наихудший рейтинг, говорящий о том, что был найден минимум один блокирующий баг.

Рассмотрим основные метрики.

Issues (Найденные проблемы)

Показывает найденные проблемы в коде

  • 🐞 Bug — приоритетные ошибки, которые нужно исправить как можно скорее
  • 💩 Code smell — незначительные огрехи, которые больше относятся к культуре кода и его оформлению
  • 🔒 Vulnerability – уязвимости, связанные с безопасностью.
  • 🛡️ Security HotSpot - потенциальные точки уязвимости

У каждой ошибки есть состояния:

  • Открытые
  • Переоткрытые
  • Подтвержденные
  • Ложные
  • Won't fix

Security (Безопасность)

Это отдельная вкладка где собрана информация о количестве уязвимостей и их рейтинге безопасности (от A до E). Подробнее тут.

  • A = 0 проблем
  • B = как минимум 1 Minor проблема
  • C = как минимум 1 Major проблема
  • D = как минимум 1 Critical проблема
  • E = как минимум 1 Blocker проблема

Reliability (Надежность)

SonarQube анализирует код на предмет надежности, выявляя проблемы, которые могут привести к сбоям, ошибкам выполнения, или другим нежелательным результатам при работе программы.

Maintainability (Поддерживаемость)

Во вкладке Measures в разделе Maintainability содержится информация о техническом долге в проекте.

  • Duplications
  • Technical debt
  • Code complexity

Coverage (Покрытие тестами)

Во вкладке Measures в разделе Coverage собрана информация о покрытии кода тестами.

Может быть полезно для:

  • Оценки качества тестирования
  • Выявление неиспользуемого кода
  • Стимулирование написания новых тестов

Duplications (Дублирование)

Во вкладке Measures в разделе Duplications можно найти информацию о наличии дублирующегося кода.

Настройка исключений для дублей

При настройке проекта нужно подумать над тем какие кейсы могут быть ложно-положительными и настройте исключения для них.

К таким же исключениям потенциально можно отнести любой автоген который хранится в репозитории, например, GQL-схемы.

Настройка проекта

Quality Profile (Профиль качества):

  • Это набор правил статического анализа кода, определяющий ожидаемый стандарт качества кода.
  • Включает в себя набор правил по стилю кода, безопасности, производительности и другим аспектам.
  • Позволяет настроить параметры анализа для конкретного проекта или команды разработчиков.

Quality Gate (Контроль качества):

  • Это набор условий, которые определяют уровень качества кода, который необходим для успешного прохождения анализа.
  • Включает в себя метрики, такие как покрытие кода тестами, процент дублирования кода, количество критических ошибок и т. д.
  • Если код не соответствует установленным критериям качества, Quality Gate не проходит, и разработчики получают уведомления о необходимости исправлений.

Список правил

У SonarQube есть готовые правила валидации для разных языков. Основные правила работают из коробки.

Правила – это набор валидаций которые помогают найти баги, "code smells" и проблемы безопасности в ходе статистического анализа.

Список правил:

Также можно добавлять свои правила (подробнее тут).

Интеграция сторонних линтеров

Для улучшения качества репортов SonarQube можно дать ему больше информации, например отчеты Stylelint, ESLint, TSLint через параметры.

  • sonar.css.stylelint.reportPaths
  • sonar.eslint.reportPaths
  • sonar.typescript.tslint.reportPaths

Подробнее в документации.

Создание проекта в 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.

Пример джобы в Gitlab CI.

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 - папки для сканирования

Далее для начала генерации отчетов запустите скрипт.

node index.js

Если релизов много, скрипт может выполняться несколько часов. После этого в дашборде появится стата по каждому релизу.

Интеграция через вебхуки

А с помощью вебхуков можно настраивать различные автоматизации. Например, отчет о проверке релиза в чат команды.

На этом всё, надеюсь статья была полезной.

Если вам было интересно, подписывайтесь на телеграм-канал @trash_js – там я пишу более короткие заметки об экосистеме фронтенда и frontops. 🎩