SonarQube с нуля для монорепозитория React/TS на Bitbucket и Jenkins

Курс поможет развернуть SonarQube, подключить анализ к монорепозиторию с UI kit на React и TypeScript и встроить проверки в Jenkins. Вы научитесь настраивать качество кода, покрытие тестами, PR-анализ в Bitbucket и Quality Gates для блокировки плохих сборок.

1. Что дает SonarQube: метрики, баги, уязвимости и Quality Gate

Что дает SonarQube: метрики, баги, уязвимости и Quality Gate

SonarQube — это платформа статического анализа, которая помогает превратить «качество кода» из субъективного ощущения в набор измеримых правил и автоматических проверок. Для монорепозитория с React/TypeScript это особенно полезно: команд много, пакетов много, изменения идут параллельно, а единый стандарт качества нужен всем.

Ниже — что именно дает SonarQube и как читать его результаты.

1) Что SonarQube проверяет: три класса проблем

Bugs (баги)

Это потенциальные ошибки выполнения: то, что с высокой вероятностью приведет к некорректному поведению.

Примеры в контексте TS/React:

  • ветка кода, которая никогда не выполнится;
  • неправильная работа с Promise (например, забыли обработать ошибку);
  • сравнение, которое всегда истинно/ложно;
  • подозрительные преобразования типов.
  • Смысл: ловим дефекты до запуска в проде.

    Vulnerabilities (уязвимости)

    Это проблемы, которые могут привести к компрометации данных или выполнению нежелательных действий.

    Примеры:

  • небезопасная обработка пользовательского ввода (риск XSS);
  • использование небезопасных криптографических практик;
  • опасные API/паттерны, которые открывают поверхность атаки.
  • Смысл: безопасность — часть Definition of Done, а не ручной аудит раз в квартал.

    Code Smells (code smells)

    Это не «ошибка», а сигнал о сложном или неудачно поддерживаемом коде.

    Примеры:

  • чрезмерная вложенность и сложные условия;
  • дублирование логики;
  • слишком большие функции/компоненты;
  • неочевидные именования, мертвый код.
  • Смысл: повышаем поддерживаемость и скорость разработки.

    2) Метрики: чем измеряется качество

    SonarQube показывает не только список проблем, но и метрики проекта. Важно понимать, что метрики — это индикаторы: они помогают обнаружить риски и тренды.

    Ключевые метрики, которые обычно используют в командах:

  • Coverage (покрытие тестами) — процент строк/веток, покрытых тестами (при наличии отчета о покрытии). Полезно отслеживать именно «на новых изменениях», чтобы не спорить о наследии.
  • Duplications (дублирование) — доля дублированных фрагментов. Рост дублирования почти всегда ведет к расхождению поведения и сложности изменений.
  • Maintainability rating — оценка поддерживаемости на основе объема «технического долга» (сколько времени нужно, чтобы исправить smells по правилам).
  • Reliability rating — оценка надежности по найденным багам.
  • Security rating — оценка безопасности по найденным уязвимостям.
  • Security Review (Security Hotspots) — отдельный класс «подозрительных мест», которые не всегда являются уязвимостью, но требуют ручного подтверждения.
  • Практичный подход: метрики важнее всего на новом коде (new code). Так вы не блокируете работу из-за старых проблем, но перестаете увеличивать долг.

    3) Правила, профили и «стандарт качества»

    SonarQube работает по правилам. Набор правил объединяется в Quality Profile (профиль качества). Один профиль можно применять к многим проектам/папкам/языкам.

    Зачем это нужно:

  • вы фиксируете единый стандарт для всей компании/монорепозитория;
  • можно включать/отключать спорные правила без хаоса в обсуждениях;
  • правила становятся частью процесса, а не «рекомендацией».
  • Важно: SonarQube не заменяет линтер (ESLint) и форматтер. Он дополняет их управлением качеством на уровне проекта, метриками, «воротами» (gate) и отчетностью.

    4) Quality Gate: автоматическое «проходит/не проходит»

    Quality Gate — это набор условий, которые определяют, можно ли считать анализ успешным.

    Примеры условий, которые часто ставят именно на новый код:

  • 0 новых уязвимостей;
  • 0 новых багов (или только низкая/средняя критичность допускается по политике);
  • покрытие нового кода не ниже N%;
  • дублирование нового кода не выше M%.
  • Если Quality Gate не пройден, SonarQube помечает анализ как failed — и это можно использовать как сигнал для CI (например, в Jenkins) и для проверок в pull request.

    Почему Quality Gate критичен:

  • он превращает результаты анализа в решение, а не «отчет для чтения»;
  • снижает вариативность ревью: меньше вкусовщины, больше правил;
  • помогает стабильно удерживать качество в большом монорепозитории.
  • 5) PR-анализ: качество как часть code review

    При анализе pull request SonarQube умеет показывать проблемы, появившиеся именно в рамках этого PR (новые issues, падение покрытия, рост дублирования). Это удобнее, чем «раз в неделю смотреть на дашборд».

    Типичный эффект:

  • автор PR сам видит, что именно не проходит gate;
  • ревьюер обсуждает логику и архитектуру, а не мелкие нарушения правил;
  • качество не деградирует незаметно.
  • 6) Как читать результаты: быстрый чек-лист

  • Смотрите статус Quality Gate — это итог.
  • Откройте проблемы на новом коде — это приоритет.
  • Разделите по типам: баги и уязвимости правим в первую очередь.
  • Smells рассматривайте как инвестиции в поддержку: выбирайте самые дорогие/частые.
  • Отслеживайте тренды: рост дублирования и падение покрытия — ранние сигналы.
  • ---

    Задания для закрепления

    1) Объясните разницу между Bugs, Vulnerabilities и Code Smells (по 1–2 предложения).

    2) Почему метрики «на новом коде» обычно полезнее, чем метрики «по всему проекту» в старом монорепозитории?

    3) Придумайте 3 условия для Quality Gate для UI-kit на React/TS. Укажите, какие из них вы бы применяли именно к новому коду.

    4) Что такое Security Hotspots и чем они отличаются от Vulnerabilities?

    <details> <summary> Ответы </summary>

    1) Bugs — потенциальные дефекты поведения (риск неправильного результата/падений). Vulnerabilities — потенциальные проблемы безопасности (риск атаки/утечки). Code Smells — ухудшение поддерживаемости (сложно читать/менять), не обязательно приводит к ошибке прямо сейчас.

    2) В монорепозитории обычно есть «исторический долг»: старые нарушения могут быть многочисленными и не дают двигаться, если требовать исправить всё сразу. Фокус на новом коде позволяет не увеличивать долг и постепенно улучшать качество без остановки разработки.

    3) Пример условий:

  • 0 новых уязвимостей — на новый код.
  • покрытие нового кода ≥ 80% — на новый код.
  • дублирование нового кода ≤ 3% — на новый код.
  • (Дополнительно можно иметь правила «по всему проекту» как мониторинг, но gate обычно держат на новом коде.)

    4) Security Hotspots — места, где код может быть небезопасным в зависимости от контекста (нужна ручная проверка/подтверждение). Vulnerabilities — уже классифицированные уязвимости, которые трактуются как проблема безопасности и обычно должны быть исправлены.

    </details>

    2. Установка SonarQube и создание проекта: токены, права, базовые настройки

    Установка SonarQube и создание проекта: токены, права, базовые настройки

    Эта статья — практический минимум, чтобы поднять SonarQube, зайти в него как администратор, создать проект под монорепозиторий и подготовить доступ для CI (Jenkins): токены, права и несколько настроек, без которых дальше обычно «не взлетает».

    1) Установка SonarQube: что выбрать и что подготовить

    Вариант A: Docker (быстрее для старта)

    Подходит для пилота и небольших команд. Важно заранее подготовить:

  • Постоянное хранилище для данных SonarQube (иначе после перезапуска всё пропадёт).
  • Базу данных. В проде обычно используют PostgreSQL (встроенная H2 — только для тестов/демо).
  • Открытый порт для веб-интерфейса (часто 9000) и понятный DNS/URL.
  • Для удобства зафиксируйте параметры окружения (как чек-лист):

    Вариант B: Установка на VM/сервер

    Уместна, если уже есть стандарты эксплуатации (мониторинг, бэкапы, отдельная БД). Минимально проверьте:

  • ОЗУ/CPU: SonarQube индексирует и хранит метаданные анализа — слабая машина будет «задыхаться».
  • Диск: место нужно под БД и под данные SonarQube.
  • Резервное копирование: отдельно бэкапят БД и каталоги данных SonarQube.
  • > Практика: для командного использования сразу планируйте PostgreSQL и бэкапы. Это экономит время при переносах/обновлениях.

    2) Первый вход и базовая гигиена админа

    После запуска:

  • Зайдите в веб-интерфейс SonarQube.
  • Выполните первый вход под админом (в зависимости от дистрибутива может быть стандартная пара учётных данных).
  • Сразу смените пароль администратора.
  • Создайте отдельного пользователя-админа под себя и отключите использование «дефолтного» аккаунта в работе команды.
  • Почему это важно: все дальнейшие действия (токены, права, интеграции) должны быть привязаны к реальным пользователям/сервисным аккаунтам, а не к «общему admin».

    3) Создание проекта под монорепозиторий

    В SonarQube проект — это «контейнер» для метрик, правил и истории анализа.

    Что заполнить при создании

  • Project key — уникальный ключ проекта.
  • - Рекомендация: используйте стабильное имя без пробелов, например ui-monorepo. - Важно: смена ключа позже может ломать привязки в CI и историю.
  • Display name — человекочитаемое название (например, UI Monorepo).
  • Main branch — основная ветка (часто main или master). Укажите корректно, иначе анализ «по умолчанию» будет привязываться не к той ветке.
  • Один проект или несколько?

    Для монорепозитория возможны два подхода:

  • Один проект на весь репозиторий — проще стартовать, один Quality Gate.
  • Несколько проектов по пакетам (apps/packages) — точнее ответственность и метрики, но больше администрирования.
  • Для начала обычно выбирают один проект, а детализацию вводят позже, когда стабилизированы правила и процесс.

    4) Токены: какие бывают и какой нужен Jenkins

    Токен — это способ дать CI доступ к SonarQube без пароля.

    Виды токенов (практический смысл)

  • User token (токен пользователя)
  • - Привязан к конкретному пользователю. - Подходит, но хуже контролируется (увольнение/ротация людей = ротация токенов).
  • Service account token (лучший вариант для CI)
  • - Создайте отдельного пользователя, например jenkins-sonar. - Выпустите токен для него и храните в Jenkins Credentials.
  • Project-level ограничения
  • - На практике достигаются не «особым типом токена», а правами: сервисному пользователю дают доступ только к нужному проекту.

    Правило эксплуатации:

  • Токен показывается один раз при создании.
  • Не храните токен в репозитории.
  • Ротируйте токены по политике (например, раз в 90–180 дней).
  • 5) Права доступа: минимально необходимые роли

    В SonarQube есть глобальные права и права на проект.

    Рекомендованный минимум

  • Администраторы SonarQube
  • - 1–2 человека (не вся команда).
  • Сервисный пользователь CI (Jenkins)
  • - Права на проект: возможность выполнять анализ (публиковать результаты). - Не давайте ему админские права.
  • Команда разработки
  • - Доступ на чтение к проекту (чтобы смотреть проблемы и метрики).

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

    6) Базовые настройки проекта, которые стоит сделать сразу

    1) Quality Gate по умолчанию

    Убедитесь, что проект использует правильный Quality Gate (корпоративный или дефолтный). В прошлой статье мы обсуждали смысл gate; здесь важно только выбрать его на проект.

    2) New Code Definition (определение «нового кода»)

    Чтобы SonarQube корректно сравнивал изменения, выберите подход:

  • По предыдущей версии (если вы релизитесь версиями).
  • По дате (например, «новый код — всё после даты внедрения SonarQube»).
  • По ветке (если есть эталонная ветка).
  • Для старого монорепозитория часто проще начать с даты, чтобы не блокироваться историческим долгом.

    3) Настройка видимости проекта

    Если SonarQube доступен нескольким командам, решите: проект будет Private (рекомендуется по умолчанию) или публичный внутри инстанса.

    4) Полезная мелочь: Base URL

    Проверьте, что в глобальных настройках указан корректный публичный URL SonarQube. Это влияет на ссылки из CI/уведомлений и (когда подключите) интеграции с PR.

    ---

    Задания для закрепления

    1) Придумайте Project key и Display name для монорепозитория, где есть apps/storybook и packages/ui-kit.

    2) Опишите, какого пользователя вы заведёте для Jenkins и какие права ему дадите (глобальные и проектные).

    3) Выберите вариант New Code Definition для старого монорепозитория с большим историческим долгом и объясните почему.

    <details> <summary> Ответы </summary>

    1) Пример:

  • Project key: ui-monorepo (стабильно, без пробелов, понятно в CI)
  • Display name: UI Monorepo (Storybook + UI Kit)
  • 2) Пример:

  • Пользователь: jenkins-sonar (отдельный сервисный аккаунт)
  • Глобальные права: без админских прав
  • Права на проект: разрешение выполнять анализ/публиковать результаты (и только на нужный проект), чтение не обязательно, но обычно не мешает
  • 3) Для старого монорепозитория часто выбирают «новый код с даты» (например, с дня внедрения SonarQube), чтобы Quality Gate применялся к изменениям команды сегодня и не блокировал работу из-за накопленного ранее долга.

    </details>

    3. Подготовка монорепозитория React/TS: tsconfig, eslint, тесты и coverage

    Подготовка монорепозитория React/TS: tsconfig, eslint, тесты и coverage

    Чтобы SonarQube давал корректные результаты в монорепозитории (особенно для TypeScript и покрытия), репозиторий нужно подготовить: унифицировать tsconfig, настроить ESLint как источник “внешних” замечаний (по желанию) и обеспечить стабильную генерацию отчетов тестов/coverage в CI.

    Ниже — практичный набор решений, который обычно работает для структуры вида:

    1) TypeScript: стратегия tsconfig для монорепозитория

    1.1. Базовый tsconfig на корне

    Идея: держать общие настройки в одном месте (например, tsconfig.base.json), а в каждом пакете иметь tsconfig.json, который extends базовый.

    Что важно для анализа:

  • Единые compilerOptions, влияющие на понимание кода:
  • - strict (желательно включить и не “плавать” по пакетам). - jsx (для React-пакетов). - baseUrl/paths (если используете алиасы импорта).
  • Стабильные include/exclude:
  • - включайте исходники (src/**), - исключайте сборку (dist/), временное (coverage/), артефакты (node_modules/**).
  • Source maps: если в тестах и coverage участвует TS-код, наличие sourcemap-настроек/корректной трансформации помогает сопоставить покрытие с исходниками.
  • 1.2. Tsconfig на уровне пакета

    В каждом пакете лучше иметь собственный tsconfig.json (или пару: tsconfig.json + tsconfig.build.json), чтобы:

  • TypeScript и инструменты понимали границы пакета.
  • Анализатор мог “привязать” файлы к правильному контексту.
  • Минимальные принципы:

  • extends от корневого базового.
  • include ограничен папкой пакета (обычно src).
  • Если используете project references, следите, чтобы они не тянули лишние части репо (иначе анализ и IDE становятся медленнее).
  • 1.3. Почему это критично именно для SonarQube

    SonarQube для JS/TS опирается на информацию из конфигурации TypeScript (в том числе для разрешения импортов и типов). Практическое правило: если IDE/tsc “теряются” в импортах — SonarQube тоже будет теряться. Поэтому сначала добиваемся прозрачной сборки/типизации, потом подключаем анализ.

    2) ESLint: единый стандарт и (опционально) импорт замечаний в SonarQube

    SonarQube и ESLint частично пересекаются по правилам, но выполняют разные задачи: ESLint — быстрый линт в дев-цикле, SonarQube — централизованные метрики, история и Quality Gate.

    2.1. Как организовать ESLint в монорепо

    Подход, который проще всего поддерживать:

  • Один корневой конфиг (flat config или классический) с общими правилами.
  • Overrides по типам файлов/пакетам (React, тесты, storybook, конфиги).
  • Единые плагины/версии (иначе одинаковый код в разных пакетах будет оцениваться по-разному).
  • 2.2. Не дублируйте проверки

    Чтобы команды не раздражались “двойными” замечаниями:

  • Решите, что является источником истины для конкретного класса правил.
  • Для спорных правил оставляйте проверку только в одном месте (или понижайте серьезность в одном из инструментов).
  • 2.3. Внешние замечания (по желанию)

    Если в вашей практике важно видеть ESLint-issues прямо в SonarQube, можно настроить генерацию ESLint-отчета в CI и импорт как external issues. Это полезно, когда:

  • Хотите один дашборд качества.
  • Нужно показывать замечания на PR в едином месте.
  • 3) Тесты и coverage: чтобы SonarQube видел реальное покрытие

    SonarQube сам по себе тесты не запускает — он читает отчеты, которые вы заранее сгенерировали.

    3.1. Что нужно получить на выходе

    Минимальный артефакт для покрытия JS/TS — LCOV (lcov.info). Обычно его создают Jest или Vitest.

    Практические требования к coverage в монорепо:

  • Coverage должен собираться из исходников, а не из dist.
  • Пути в lcov.info должны совпадать с тем, что сканирует SonarQube (иначе покрытие будет 0% или “дырявое”).
  • Для нескольких пакетов:
  • - либо генерируйте coverage в каждом пакете, - либо объединяйте в один общий LCOV (главное — не потерять пути).

    3.2. Что исключать из покрытия

    Чтобы метрика не искажалась и не провоцировала “тестируйте то, что не имеет смысла”, часто исключают:

  • .stories., .story. (Storybook).
  • *.d.ts.
  • index.ts-реэкспорты (по договоренности команды).
  • Моки/фикстуры/генерируемый код.
  • Важно: исключения для покрытия не должны “прятать” реальный продакшен-код.

    3.3. Тестовые окружения и стабильность в CI

    Чтобы coverage был воспроизводимым в Jenkins:

  • Тесты должны работать в headless-режиме.
  • В монорепо избегайте “плавающих” зависимостей окружения (таймзона, локаль, разные Node-версии).
  • Если тестов много, следите за предсказуемым временем выполнения (иначе анализ будет нестабильным по SLA).
  • 4) Мини-чек-лист перед подключением SonarQube анализа

  • TypeScript компилирует каждый пакет (или хотя бы корректно резолвит импорты).
  • Есть понятные tsconfig на корне и на пакетах.
  • ESLint запускается из корня и применяет единые правила.
  • Тесты генерируют lcov.info (в одном месте или по пакетам).
  • Coverage не указывает на dist и не содержит “битых” путей.
  • ---

    Задания для закрепления

    1) Для структуры apps/storybook и packages/ui-kit опишите, какие tsconfig файлы вы заведёте (на корне и в пакетах) и что в них принципиально должно быть.

    2) Перечислите 5 категорий файлов/папок, которые вы бы исключили из анализа/типизации/покрытия в монорепозитории (и почему).

    3) У вас coverage генерируется в packages/ui-kit/coverage/lcov.info и apps/storybook/coverage/lcov.info. Какой практический подход выберете для SonarQube: объединять в один LCOV или передавать несколько путей? Обоснуйте.

    4) Назовите 3 причины, почему SonarQube может показывать 0% coverage, даже если тесты “точно запускались”.

    <details> <summary> Ответы </summary>

    1) Обычно:

  • На корне: tsconfig.base.json с общими compilerOptions (strict, paths/aliase-ы, целевая версия, jsx-настройки для React-пакетов или вынести их в отдельный базовый для фронта) и глобальными исключениями.
  • В каждом пакете: tsconfig.json, который extends базовый, имеет свой include (обычно src/**) и exclude (dist/coverage). При необходимости отдельный tsconfig.build.json для сборки.
  • 2) Примеры:

  • node_modules/** (внешний код).
  • dist/ или build/ (артефакты сборки, иначе будет дублирование исходников).
  • coverage/** (артефакты тестов).
  • */.d.ts (декларации типов обычно не “покрывают” тестами).
  • */.stories.* (storybook-сценарии — не продовый код).
  • 3) Оба варианта рабочие:

  • “Несколько путей” проще: меньше риск испортить пути в LCOV, меньше шагов в CI.
  • “Один объединенный LCOV” удобнее, если хотите один артефакт и одинаковую схему для разных пайплайнов.
  • Чаще начинают с нескольких путей (быстрее внедрить), а объединение добавляют при усложнении.

    4) Частые причины:

  • SonarQube сканирует другие пути, чем указаны в lcov.info (несовпадение root, относительные/абсолютные пути).
  • Coverage собран по dist/transpiled JS без корректного сопоставления к исходникам.
  • Отчет coverage не попадает в workspace Jenkins (не сохраняется, генерируется в другом каталоге, чистится до шага анализа).
  • </details>

    4. Настройка sonar-project.properties для монорепо и нескольких пакетов

    Настройка sonar-project.properties для монорепо и нескольких пакетов

    sonar-project.properties — это «паспорт анализа»: что сканируем, что считаем тестами, где брать coverage, какие каталоги исключать. В монорепозитории важно настроить файл так, чтобы SonarQube:

  • не анализировал сборочные артефакты и зависимости;
  • корректно сопоставлял TS/React код с tsconfig;
  • подхватывал coverage из нескольких пакетов.
  • Подготовка tsconfig и coverage-отчетов описана в предыдущей статье; здесь — только связывание этого в конфиг SonarScanner.

    1) Где хранить и как читается файл

    Обычно sonar-project.properties кладут в корень репозитория. Все пути внутри — относительно директории, откуда запускается scanner (в Jenkins это обычно workspace). Если запускаете анализ не из корня, используйте одно из двух:

  • запускать scanner из корня;
  • либо задавать sonar.projectBaseDir в параметрах запуска (чаще удобнее, чем «ломать» пути в файле).
  • 2) Базовые поля: идентичность проекта и “что сканируем”

    Минимальный набор, который почти всегда нужен:

  • sonar.projectKey — ключ проекта в SonarQube (должен совпадать с созданным проектом).
  • sonar.projectName — отображаемое имя (можно не задавать, но удобно).
  • sonar.sourceEncoding=UTF-8 — чтобы не было сюрпризов с кодировками.
  • sonar.sources — откуда брать исходники.
  • Практика для монорепо: оставлять sonar.sources=., а точную область анализа регулировать исключениями/включениями. Так проще переживать появление новых пакетов.

    3) Источники vs тесты: разделяйте явно

    Чтобы SonarQube правильно считал метрики и не «смешивал» тесты с прод-кодом:

  • sonar.sources — продовый код (и то, что вы хотите анализировать как код продукта).
  • sonar.tests — тестовые файлы.
  • sonar.test.inclusions — маски тестов, если тесты лежат рядом с исходниками.
  • Важно: если в монорепо тесты лежат прямо в src, можно не выносить их физически, но логически отделить через sonar.test.inclusions.

    4) Исключения: обязательный слой против “шума”

    В монорепозитории без исключений вы почти гарантированно получите:

  • анализ dist/build (дублирование и мусор);
  • сканирование node_modules (огромный объем и нерелевантные issue);
  • попадание coverage (артефакты тестов);
  • шум от Storybook stories и моков.
  • Вынесите это в sonar.exclusions. Пример ниже.

    5) TypeScript: привязка к нескольким tsconfig

    Для TS-проектов SonarJS корректнее работает, когда знает, какими tsconfig описаны пакеты. В монорепо используйте список путей:

  • sonar.typescript.tsconfigPaths — несколько tsconfig.json (через запятую).
  • Рекомендация: указывать пакетные tsconfig.json, а не только корневой базовый.

    6) Coverage из нескольких пакетов

    Для JS/TS coverage SonarQube читает LCOV. Если отчеты лежат в разных местах (например, packages//coverage/lcov.info и apps//coverage/lcov.info), укажите несколько путей:

  • sonar.javascript.lcov.reportPaths — список файлов через запятую.
  • Критично: пути в lcov.info должны соответствовать путям, которые видит scanner в workspace (это решается на этапе генерации отчета; см. статью про coverage).

    7) Пример sonar-project.properties для монорепо (один проект)

    Подход «один проект на весь монорепо» обычно проще для старта: один Quality Gate и единая картина качества. Если позже потребуется раздельная отчетность по пакетам — чаще делают отдельные проекты/отдельные запуски анализа, чем усложняют один конфиг.

    8) Что не стоит класть в sonar-project.properties

  • Токены доступа — храните в Jenkins Credentials.
  • PR-специфичные параметры — удобнее задавать при запуске (в Jenkins), чтобы они подставлялись динамически (ключ PR, ветки и т.д.).
  • ---

    Задания для закрепления

    1) Для монорепо со структурой apps/storybook, packages/ui-kit, packages/icons составьте минимальный sonar-project.properties: ключ проекта, исключения и пути к coverage.

    2) У вас тесты лежат в src/__tests__ и рядом с кодом как *.spec.tsx. Какие значения вы зададите для sonar.tests и sonar.test.inclusions, чтобы SonarQube корректно выделял тесты?

    3) SonarQube показывает 0% coverage только для packages/icons, хотя lcov.info есть. Назовите 3 наиболее вероятные причины, связанные именно с настройками sonar-project.properties/путями.

    <details> <summary> Ответы </summary>

    1) Пример (минимум):

    2) Один из рабочих вариантов:

  • sonar.tests=. (потому что тесты размазаны по репозиторию)
  • sonar.test.inclusions=/src/__tests__/,/.spec.ts,/.spec.tsx
  • И дополнительно держать sonar.exclusions так, чтобы не попадали dist/build/node_modules/coverage.

    3) Частые причины на уровне свойств/путей:

  • sonar.javascript.lcov.reportPaths не содержит путь к coverage для packages/icons (или опечатка в пути).
  • Анализ запускается не из корня, и относительные пути в sonar.javascript.lcov.reportPaths/sonar.typescript.tsconfigPaths «съехали».
  • sonar.exclusions слишком широкие и случайно исключают исходники packages/icons (тогда coverage не к чему “приклеить”).
  • </details>

    5. Интеграция с Jenkins: SonarScanner, Jenkinsfile и Quality Gate в пайплайне

    Интеграция с Jenkins: SonarScanner, Jenkinsfile и Quality Gate в пайплайне

    Интеграция SonarQube в Jenkins решает две практические задачи:

  • запуск анализа на каждом билдe (ветки и PR), чтобы результаты были частью CI;
  • автоматическая остановка пайплайна, если Quality Gate не пройден.
  • Настройки проекта (sonar-project.properties, пути к coverage, tsconfig) считаем уже подготовленными (см. соответствующие статьи курса) — здесь фокус на Jenkins.

    1) Что настроить в Jenkins до Jenkinsfile

    1.1. Плагины и глобальная конфигурация

    Нужны два элемента:

  • Интеграция Jenkins ↔ SonarQube (обычно через плагин SonarQube Scanner for Jenkins).
  • SonarQube server в Manage Jenkins → Configure System:
  • 1. имя инстанса (например, sonarqube), 2. URL SonarQube, 3. аутентификация токеном (Credential).

    Токен и сервисного пользователя под CI вы уже заводили на стороне SonarQube; в Jenkins токен храните только как Secret Text в Credentials.

    1.2. Какой SonarScanner использовать

    На практике встречаются варианты:

  • SonarScanner CLI как tool в Jenkins (удобно, если Jenkins-агенты “голые”).
  • SonarScanner внутри Docker-образа (удобно для стабильных версий инструментов).
  • Node-пакет / обертки (реже нужно, чаще усложняет поддержку).
  • Для старта обычно проще: SonarQube server + токен в Jenkins + запуск sonar-scanner в stage.

    2) Jenkinsfile: базовый пайплайн для монорепо

    Ниже — минимальная схема стадий, которую удобно поддерживать в монорепозитории:

  • Checkout
  • Install
  • Test + Coverage
  • Sonar scan
  • Quality Gate
  • Пример Declarative Pipeline:

    text IF CHANGE_ID exists: sonar-scanner -Dsonar.pullrequest.key=... -Dsonar.pullrequest.branch=... -Dsonar.pullrequest.base=... ELSE: sonar-scanner -Dsonar.branch.name=... ``

    Важно: конкретный набор параметров PR зависит от того, как у вас настроена интеграция SonarQube с Bitbucket и какой сценарий PR-анализа вы используете.

    5) Частые проблемы и быстрые проверки

  • Coverage = 0%
  • 1. тесты не запускались до анализа; 2. lcov.info не попал в workspace (другой каталог/clean workspace); 3. анализ запускается не из того baseDir (пути “съехали”).

  • Анализ “видит” dist/build
  • 1. в Jenkinsfile случайно запускают сборку, которая генерирует артефакты в анализируемых директориях; 2. исключения настроены, но scanner запускается из другой директории.

  • Quality Gate всегда таймаутится
  • 1. не настроен webhook в SonarQube; 2. SonarQube не может достучаться до Jenkins (сеть, TLS, reverse proxy).

  • OOM/долгие анализы на монорепо
  • 1. задайте разумные лимиты Node/агента; 2. исключайте лишнее из анализа (артефакты, coverage-папки, node_modules); 3. по возможности не смешивайте “тяжелую сборку” и анализ в одном и том же каталоге.

    ---

    Задания для закрепления

    1) Перечислите 5 обязательных условий, чтобы стадия Quality Gate в Jenkins работала стабильно (не “по праздникам”).

    2) Почему Test + Coverage должна идти до SonarQube scan, даже если SonarQube «про покрытие уже настроен»?

    3) В Multibranch Pipeline у вас есть BRANCH_NAME=feature/x, а для PR появляются CHANGE_ID, CHANGE_BRANCH, CHANGE_TARGET. Опишите, какие параметры вы передадите в scanner для ветки и для PR (на уровне идеи, без привязки к Bitbucket).

    4) Составьте минимальный набор диагностических шагов, если после внедрения SonarQube пайплайн начал регулярно падать на waitForQualityGate по timeout.

    <details> <summary> Ответы </summary>

    1) Пример набора условий:

  • В Jenkins настроен SonarQube server (URL, имя), и Jenkinsfile использует это имя в withSonarQubeEnv(...).
  • Токен SonarQube хранится в Jenkins Credentials и доступен пайплайну.
  • Анализ реально публикуется (scanner завершает работу без ошибок и отправляет отчет).
  • В SonarQube создан webhook на Jenkins URL /sonarqube-webhook/.
  • SonarQube имеет сетевой доступ до Jenkins webhook (DNS/маршрутизация/TLS/reverse proxy настроены).
  • 2) Потому что SonarQube сам тесты не запускает, он только читает уже сгенерированные отчеты. Если lcov.info отсутствует или создан позже, анализ будет без данных покрытия.

    3) Идея:

  • Для обычной ветки: передать имя ветки, например -Dsonar.branch.name=CHANGE_ID, -Dsonar.pullrequest.branch=CHANGE_TARGET`.
  • 4) Диагностика:

  • Проверить в SonarQube, что анализ вообще завершился и Quality Gate посчитан (статус последнего анализа).
  • Проверить настройки webhook в SonarQube (URL, события, ошибки доставки).
  • Проверить доступность Jenkins webhook из сети SonarQube (маршрут, прокси, TLS).
  • Увеличить timeout на время диагностики и убедиться, что проблема именно в уведомлении, а не в “вечном” анализе.
  • </details>

    6. Интеграция с Bitbucket: PR-анализ, комментарии и политика merge

    Интеграция с Bitbucket: PR-анализ, комментарии и политика merge

    Интеграция SonarQube с Bitbucket нужна для двух вещей: 1) привязать анализ к pull request (PR) и показывать результат прямо в PR; 2) сделать качество кода частью политики merge (не «посмотрели дашборд», а «merge невозможен, пока не пройден Quality Gate»).

    Важно: полноценный PR-анализ и decoration обычно доступны не во всех редакциях SonarQube (часто требуется Developer Edition и выше). Перед настройкой проверьте, что ваш инстанс поддерживает PR/branch analysis.

    1) Определитесь, какой Bitbucket у вас: Cloud или Data Center/Server

    Настройка отличается в деталях, но принцип один: SonarQube должен уметь обращаться к API Bitbucket.

  • Bitbucket Cloud: чаще используются app password / OAuth-подходы.
  • Bitbucket Data Center/Server: чаще используются personal access token (PAT) или связка через приложение/плагин.
  • В любом случае вам нужен технический пользователь (бот), от имени которого SonarQube будет писать статусы/комментарии.

    2) Технический пользователь в Bitbucket: права и «границы ответственности»

    Заведите отдельного пользователя, например sonarqube-bot, и выдайте ему минимально достаточные права.

    Обычно нужны:

  • Доступ на чтение к репозиторию (чтобы SonarQube мог сопоставлять PR, ветки и файлы).
  • Права на взаимодействие с PR (оставлять комментарии, выставлять статус/decoration).
  • Практический принцип:

  • бот не должен иметь прав администратора репозитория;
  • доступ лучше выдавать на уровне проекта/репозитория, а не «на весь Bitbucket».
  • 3) Настройка интеграции в SonarQube (ALM/DevOps integration)

    Настройки делятся на два уровня:

    1) Глобальная интеграция (SonarQube ↔ Bitbucket как платформы) 2) Привязка проекта SonarQube к репозиторию

    Типовой путь в интерфейсе SonarQube выглядит так:

    Что важно заполнить:

  • URL Bitbucket (и, если нужно, base API URL).
  • Токен/секрет бота.
  • Настройки «как публиковать результаты» (статус PR, комментарии, summary).
  • Дальше в настройках конкретного проекта SonarQube (Project Settings) укажите, к какому репозиторию Bitbucket он привязан.

    Критично для монорепозитория: если у вас один проект SonarQube на весь репо, привязка делается одна (на этот репозиторий). Тогда в PR будут показаны issues только по изменённым файлам, но в рамках единого проекта.

    4) Как выглядит поток PR-анализа (что с чем разговаривает)

    Не путайте две разные вещи:

  • PR строит и анализирует CI (Jenkins + scanner)
  • PR украшает (decorates) SonarQube через интеграцию с Bitbucket
  • Схема:

    Параметры PR для scanner (например, ключ PR и base-ветка) передаются из Jenkins (см. статью про Jenkins). На стороне Bitbucket важно другое: чтобы SonarQube мог однозначно сопоставить анализ с конкретным PR.

    5) Что именно появится в PR: статусы и комментарии

    В Bitbucket обычно видны три типа сигналов:

  • Build status / check: “SonarQube Quality Gate: PASSED/FAILED”. Это главный элемент для автоматического блокирования merge.
  • Summary comment: короткая сводка (новые баги/уязвимости/смеллы, coverage на новом коде, дублирование). Часто SonarQube обновляет один и тот же комментарий при новых пушах в PR.
  • Inline annotations (если поддерживается вашим Bitbucket/редакцией): замечания прямо на строках diff.
  • Практика против «шума»:

  • Держите требования Quality Gate сфокусированными на new code (вы это настраивали ранее через New Code Definition и gate).
  • Договоритесь, что блокирующие причины — это, например, уязвимости и критичные баги, а не любой smell.
  • 6) Политика merge в Bitbucket: как сделать так, чтобы плохой код не попадал в main

    Есть два рабочих способа «запретить merge» при провале качества — часто их комбинируют.

    Способ A (часто самый надёжный): Bitbucket требует успешный билд Jenkins

    Идея: Jenkins пайплайн сам падает на стадии ожидания Quality Gate (см. waitForQualityGate в статье про Jenkins). Тогда Bitbucket видит билд как failed и не даёт merge.

    Плюсы:

  • единый контроллер — Jenkins;
  • меньше зависимостей от того, как именно Bitbucket отображает статусы SonarQube.
  • Минус:

  • в PR вы можете видеть “build failed”, но без красивого статуса SonarQube (если decoration не настроен).
  • Способ B: Bitbucket требует именно статус SonarQube

    Идея: Bitbucket настроен так, что merge разрешён только если присутствует успешный check/status от SonarQube.

    Плюсы:

  • максимально прозрачно для ревью: видно именно «качество прошло/не прошло».
  • Минусы:

  • вы сильнее зависите от корректной ALM-интеграции и прав бота;
  • при сетевых сбоях/ограничениях API статус может не проставиться вовремя.
  • Рекомендуемая «минимальная политика» для команд

  • Merge в main только через PR.
  • Для PR обязательны:
  • 1) минимум 1–2 approvals; 2) успешный билд Jenkins; 3) пройденный Quality Gate.

    7) Частые проблемы интеграции и быстрые проверки

  • В PR нет статуса/комментария от SonarQube:
  • 1) проверьте, что проект SonarQube привязан к правильному репозиторию Bitbucket; 2) проверьте права sonarqube-bot (может не иметь права комментировать PR/ставить статус); 3) проверьте, что SonarQube вообще «понимает», что анализ был PR-анализом (в анализе должны быть PR-атрибуты).

  • Статус есть, но не обновляется после новых коммитов:
  • 1) PR пересоздан/изменился ключ; 2) CI отправляет результаты не в тот проект/ветку; 3) есть задержка/ограничение на стороне Bitbucket API.

  • Неправильная привязка issues к строкам (плохие inline-комментарии):
  • 1) shallow clone/нет корректного SCM blame; 2) пути файлов в монорепо отличаются от того, что видит scanner.

    ---

    Задания для закрепления

    1) Опишите, какие минимальные права нужны пользователю sonarqube-bot в Bitbucket, чтобы работали статусы PR и комментарии.

    2) В чём разница между политикой merge «требуем успешный билд Jenkins» и «требуем статус SonarQube», и почему на практике их часто комбинируют?

    3) Составьте короткий чек-лист (5 пунктов) для диагностики ситуации: «PR собрался, анализ в SonarQube есть, но в Bitbucket нет decoration».

    4) Для монорепозитория с одним проектом SonarQube: какой риск вы получите, если привяжете проект SonarQube не к тому репозиторию/проекту в Bitbucket? Опишите 2 последствия.

    <details> <summary> Ответы </summary>

    1) Минимально обычно нужно: доступ на чтение репозитория и права на взаимодействие с PR (создавать/обновлять комментарии и выставлять статус/check). Админские права не нужны.

    2) Jenkins-policy блокирует merge через общий статус сборки (падает пайплайн, если gate не пройден). SonarQube-policy блокирует merge через отдельный статус SonarQube. Комбинируют, потому что Jenkins даёт «жёсткую» остановку процесса, а SonarQube даёт понятный для ревью сигнал в PR.

    3) Пример чек-листа:

  • Убедиться, что проект SonarQube привязан к правильному репозиторию Bitbucket.
  • Проверить, что анализ был запущен как PR-анализ (а не как ветка) и имеет PR-атрибуты.
  • Проверить права sonarqube-bot на репозиторий и PR.
  • Проверить настройки ALM integration в SonarQube (URL Bitbucket, токен, включён ли PR decoration).
  • Посмотреть логи SonarQube на ошибки обращения к Bitbucket API (авторизация/сеть/лимиты).
  • 4) Последствия:

  • SonarQube не сможет сопоставить анализ с PR, decoration не появится или появится «в другом месте».
  • Политика merge, завязанная на статусы SonarQube, начнёт работать некорректно: PR может быть ошибочно заблокирован (нет статуса) или ошибочно пропущен (статус не относится к этому PR).
  • </details>

    7. Траблшутинг и лучшие практики: исключения, скорость, ложные срабатывания

    Траблшутинг и лучшие практики: исключения, скорость, ложные срабатывания

    Эта статья — про то, что обычно «болит» после первого успешного подключения SonarQube: лишний шум, медленный анализ и спорные замечания. Конфиги (sonar-project.properties, coverage, PR/Jenkins/Bitbucket) считаем уже сделанными — при необходимости сверяйтесь с соответствующими статьями курса.

    1) Быстрая диагностика: где именно проблема

    Когда команда говорит «Sonar сломался», полезно за 2–3 минуты определить класс проблемы:

  • Анализ не публикуется: scanner завершился ошибкой, проект не обновился.
  • Quality Gate не приходит в Jenkins: анализ в SonarQube есть, но waitForQualityGate таймаутится (почти всегда webhook/сеть).
  • Метрики “странные”: 0% coverage, скачки дублирования, пропавшие файлы (обычно пути/исключения/не тот baseDir).
  • Шум/ложные срабатывания: много issues там, где «это нормально».
  • Долго: анализ стал медленным или нестабильным по времени.
  • Практика: начинайте с последнего анализа в SonarQube (статус, длительность, количество файлов) и логов Jenkins (какой каталог, какие параметры).

    2) Исключения: как убрать шум и не «ослепнуть»

    Исключения — самый мощный рычаг, но им легко спрятать важный код. Разделяйте цели:

  • sonar.exclusions — что вообще не анализировать (уменьшает шум и ускоряет).
  • sonar.coverage.exclusions — что не учитывать в покрытии (не скрывает issues, но «лечит» метрику).
  • 2.1. Принципы для монорепо

  • Исключайте артефакты и внешнее: node_modules, dist/build, coverage.
  • Отдельно решите судьбу storybook stories, моков и фикстур: они часто создают шум и портят покрытие.
  • Не делайте маски слишком широкими. Антипаттерн: исключить целиком packages/** «на время», а потом забыть.
  • 2.2. Проверка, что исключения работают

    Если подозреваете, что исключения “съели” код:

  • Сравните количество анализируемых файлов между успешным и проблемным запуском.
  • Проверьте, не запущен ли scanner из другого каталога (тогда относительные пути начинают «ехать»).
  • На время диагностики упростите маски до минимальных и добавляйте обратно по одному блоку.
  • Пример структуры исключений (как идея):

    3) Скорость анализа: что реально влияет

    3.1. Главные причины “медленно”

  • Сканируются лишние каталоги (см. исключения выше).
  • Монорепо «раздулся» за счет билд-артефактов в workspace.
  • TypeScript контекст слишком тяжелый: лишние tsconfig или они тянут слишком много файлов.
  • Агент CI не тянет по ресурсам (CPU/RAM), начинаются троттлинг и своп.
  • 3.2. Практики ускорения без потери качества

  • Держите анализ в чистом workspace: не смешивайте тяжелую сборку, генерацию артефактов и анализ в одной и той же директории, если это плодит dist.
  • Удерживайте sonar.typescript.tsconfigPaths на уровне реальных пакетов, а не «один огромный tsconfig на всё».
  • Убирайте из анализа то, что не является продуктовым кодом (storybook, демо, генераторы), но делайте это явно и осознанно.
  • Стабилизируйте окружение (одинаковая Node-версия, одинаковые команды), чтобы время анализа не «плавало».
  • 4) Ложные срабатывания: процесс, а не “отключить всё”

    4.1. Классы спорных issues

  • Архитектурные допущения: правило не понимает ваш паттерн.
  • Фреймворк/типизация: TS/React-реалии, где анализатор консервативен.
  • Тестовый код: правила полезны для прод-кода, но токсичны для тестов.
  • 4.2. Правильная иерархия действий

  • Починить код, если замечание действительно про дефект/уязвимость.
  • Если это допустимый паттерн — подтвердить как False Positive (точечно, чтобы история была видна).
  • Если FP повторяется массово — настроить Quality Profile (отключить/ослабить правило) для языка/проекта.
  • Если проблема только в тестах — не отключайте правило глобально; лучше отделите тесты корректно (см. конфиг в статье про sonar-project.properties).
  • Практика: любые изменения профиля качества делайте через короткий RFC внутри команды: «что отключаем, почему, чем компенсируем».

    4.3. Hotspots: не путайте с уязвимостями

    Security Hotspots требуют ручной проверки контекста. Для команды полезно назначить владельца (или ротацию), чтобы hotspots не превращались в вечный «красный индикатор».

    5) Лучшие практики для “здорового” Quality Gate

  • Держите gate сфокусированным на new code (иначе монорепо с историческим долгом будет постоянно блокировать работу).
  • Блокируйте строго то, что реально критично для вашей организации (уязвимости/критичные баги/падение покрытия нового кода).
  • Все остальное переводите в режим управляемого долга: бэклог, постепенная зачистка, тренды.
  • ---

    Задания для закрепления

    1) У вас резко выросло время анализа в Jenkins, хотя код почти не менялся. Назовите 5 наиболее вероятных причин и порядок проверки.

    2) Придумайте политику исключений для монорепо с apps/storybook, packages/ui-kit, packages/icons: что исключить из анализа, а что — только из coverage (по 3–5 пунктов).

    3) В PR стало много замечаний, которые команда считает ложными. Опишите процесс из 4 шагов: от первого анализа до изменения Quality Profile.

    4) Сформулируйте 3 правила «безопасной настройки исключений», чтобы случайно не спрятать продуктовый код.

    <details> <summary> Ответы </summary>

    1) Пример причин и порядок:

  • Проверить, не появились ли в workspace новые большие каталоги (dist, build, временные артефакты) → сравнить число анализируемых файлов.
  • Убедиться, что scanner запускается из ожидаемого baseDir (иначе исключения/пути к tsconfig не совпадают).
  • Проверить, не изменились ли sonar.exclusions (или они стали менее строгими).
  • Проверить tsconfigPaths: не добавили ли “корневой” tsconfig, который тянет весь репозиторий.
  • Проверить ресурсы агента CI (CPU/RAM) и параллельные процессы в пайплайне.
  • 2) Пример:

    Исключить из анализа:

  • /node_modules/
  • /dist/, /build/
  • /coverage/
  • */.d.ts
  • */.stories.* (если stories не являются продуктовым кодом)
  • Исключить только из coverage:

  • */.stories.*
  • /__mocks__/
  • /test-utils/
  • демо-страницы/примеры, если они публикуются отдельно и не критичны
  • 3) Процесс:

  • Разобрать 10–20 самых частых/болезненных issues и классифицировать: дефект, smell, FP.
  • Точечно отметить FP там, где это действительно FP, чтобы не спорить «на словах».
  • Если одно и то же правило регулярно дает FP — обсудить и принять решение: отключить, понизить severity или ограничить область.
  • Внести изменение в Quality Profile и закрепить договоренность: где теперь ловим аналогичные проблемы (линтер/ревью/тесты).
  • 4) Пример правил:

  • Любое новое исключение должно иметь владельца и причину (чтобы не превратилось в “кладбище масок”).
  • Нельзя исключать целиком продуктовые каталоги (packages/**) без временного окна и задачи на возврат.
  • После изменения исключений проверять: число анализируемых файлов, покрытие на новом коде и наличие issues в ключевых пакетах.
  • </details>