<?xml version="1.0" encoding="utf-8" ?><rss version="2.0" xmlns:tt="http://teletype.in/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>Emil Yangirov</title><generator>teletype.in</generator><description><![CDATA[Рефлексирующий разработчик]]></description><image><url>https://img4.teletype.in/files/71/10/711059f2-7bc8-482d-b362-34f216bd7e47.png</url><title>Emil Yangirov</title><link>https://blog.yangirov.ru/</link></image><link>https://blog.yangirov.ru/?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=yangirov</link><atom:link rel="self" type="application/rss+xml" href="https://teletype.in/rss/yangirov?offset=0"></atom:link><atom:link rel="next" type="application/rss+xml" href="https://teletype.in/rss/yangirov?offset=10"></atom:link><atom:link rel="search" type="application/opensearchdescription+xml" title="Teletype" href="https://teletype.in/opensearch.xml"></atom:link><pubDate>Wed, 06 May 2026 11:11:46 GMT</pubDate><lastBuildDate>Wed, 06 May 2026 11:11:46 GMT</lastBuildDate><item><guid isPermaLink="true">https://blog.yangirov.ru/sonarqube</guid><link>https://blog.yangirov.ru/sonarqube?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=yangirov</link><comments>https://blog.yangirov.ru/sonarqube?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=yangirov#comments</comments><dc:creator>yangirov</dc:creator><title>SonarQube – попытка обуздать техдолг?</title><pubDate>Thu, 04 Apr 2024 14:21:08 GMT</pubDate><media:content medium="image" url="https://img1.teletype.in/files/45/b0/45b028fd-ea2b-485a-afb5-24bd582d2015.png"></media:content><category>IT</category><description><![CDATA[<img src="https://img4.teletype.in/files/fb/9b/fb9b2dee-32fa-4e58-8d60-c54d27b815b4.png"></img>Что такое SonarQube, как настроить и как он может помочь в контроле технического долга.]]></description><content:encoded><![CDATA[
  <h2 id="Km5i">Мотивация</h2>
  <p id="QZQx">Большой продукт сложен в поддержке и сколько разработчиков не бери, всё равно качество кода будет страдать.</p>
  <p id="KmME"><strong>Причины:</strong></p>
  <ul id="WO5Z">
    <li id="PhYr">сроки</li>
    <li id="9MqJ">отсутствие тестов</li>
    <li id="JgJn">поверхностное код-ревью</li>
    <li id="DtD6"><strong>отсутствие контроля техдолга</strong></li>
  </ul>
  <p id="DbtC"><em>Технический долг</em> - это как невыплаченный кредит: когда разработчики берут &quot;заем&quot; времени, выбирая быстрые и простые решения для достижения цели, но забывают вернуть его обратно, оставляя за собой задолженность в виде неоптимизированного кода. </p>
  <p id="Gc1p">Например, это может быть копипаст кода вместо создания повторно используемых функций или игнорирование необходимости написания тестов для обеспечения корректной работы кода, что в итоге увеличивает время и затраты на исправление проблем в будущем.</p>
  <p id="BtIA">Поговорим о том как контроллировать техдолг.</p>
  <h2 id="uU4e">Основная информация</h2>
  <p id="NqMa"><strong>SonarQube</strong> - это инструмент для статического анализа кода, позволяет автоматизировать процесс обнаружения проблем в коде, таких как потенциальные ошибки, нарушения стандартов кодирования, пропущенные возможности оптимизации и другие виды нарушений.</p>
  <p id="XwjD"><strong>Краткие возможности:</strong></p>
  <ul id="hV7M">
    <li id="2GIm">Выявление потенциальных ошибок, такие как неправильное использование переменных, типов или функций.</li>
    <li id="dgNN">Поддержание стандартов кодирования.</li>
    <li id="GhYR">Анализ производительности, обнаружение участков кода, которые могут вызвать утечки памяти или замедлить производительность приложения.</li>
    <li id="guEb">Управление техническим долгом, контроль метрик. Также с помощью плагинов, можно например <a href="https://marketplace.atlassian.com/apps/1217471/sonarqube-connector-for-jira?hosting=server&tab=overview" target="_blank">ставить задачи в Jira</a> на исправление участка кода.</li>
    <li id="5EHJ">Сохраняет историю метрик качества кода</li>
    <li id="KjOy">Интеграция с IDE, Jira</li>
  </ul>
  <h2 id="id-ОбщаяинформацияоSonarQube-Отличиеотлинтеров">Отличие от линтеров</h2>
  <p id="Osuk">Основная задача линтера — это проверка кода на соответствие определенным стилям и правилам программирования, таким как отступы, использование пробелов, нейминг переменных и т.д.</p>
  <p id="RQY6">Статический анализ кода ориентирован на более широкий аспект анализа кода, включая выявление ошибок, определение потенциальных уязвимостей безопасности, анализ архитектуры и т.д.</p>
  <h3 id="id-ОбщаяинформацияоSonarQube-ПочемунехватитESLint,TSLint,Stylelint?">Почему не хватит ESLint, TSLint, Stylelint?</h3>
  <p id="JDL0">Например для ESLint можно подключить плагин <a href="https://github.com/SonarSource/eslint-plugin-sonarjs" target="_blank">eslint-plugin-sonarjs</a>, который также сможет обнаруживать баги, code smells и т.д.</p>
  <p id="vx5L">Но теряется главное преимущество SonarQube – отслеживание эволюции кода в дашбордах с настройкой quality gate и подсвечиванием проблем в динамике.</p>
  <p id="uvbz">Также, ESLint, TSLint, Stylelint заточены на определенные языковые эвристики, а SonarQube оценивает картину целиком, например, может найти утекший секрет в CI-конфигурации. Покрыть такой кейс линтером довольно сложно.</p>
  <p id="id-ОбщаяинформацияоSonarQube-Новыепроекты">Линтеры являются хорошим инструментом, но они должны использоваться в сочетании с другими практиками и инструментами, такими как код-ревью, тестирование (e2e, sl, unit), анализ безопасности и регулярную работу над техдолгом, чтобы обеспечить достойное качество кода на протяжении всего жизненного цикла продукта.</p>
  <h2 id="id-ОбщаяинформацияоSonarQube-Аналогииальтернативы">Аналоги и альтернативы</h2>
  <p id="egN4">Среди похожих решение есть <a href="https://codescene.com/" target="_blank">CodeScene</a>, <a href="https://about.codecov.io/" target="_blank">CodeCov</a>. Также есть статические анализаторы вроде <a href="https://pvs-studio.ru/ru/pvs-studio/" target="_blank">PVS Studio</a>, но он не работает с экосистемой JS/TS.</p>
  <p id="tZyE">CodeScene выделяется своей способностью анализа эволюции кода и предсказания будущих изменений. Но к сожалению, у него нет Community Edition (бесплатен для open source) и для получения ключа нужен VPN (не работает в РФ).</p>
  <p id="eztG">CodeCov больше про покрытие кода тестами.</p>
  <p id="GVDO">Поэтому SonarQube является более выигрышным из-за Community Edition, а также обширного набор инструментов для оценки качества кода, покрытия и т.д.</p>
  <h2 id="id-ОбщаяинформацияоSonarQube-Плюсыиминусы">Плюсы и минусы</h2>
  <p id="QUHw"><strong>Плюсы</strong></p>
  <ul id="U55z">
    <li id="kLV0">Статический анализ кода – выявляет ошибки, code smells и потенциальные уязвимости.</li>
    <li id="ubnh">Множество поддерживаемых языков (зависит от версии - community, developer, enterprise, data)</li>
    <li id="dK5R">Интеграция с CI системами</li>
    <li id="aFEe">Дашборды и отчеты</li>
    <li id="vSiN">Интеграция сторонних линтеров</li>
  </ul>
  <p id="Cppk"><strong>Минусы</strong></p>
  <ul id="enqn">
    <li id="dzEW">Ресурсозатратность – запуск полного анализа проекта может занимать длительное время</li>
    <li id="ABtt">Сложность настройки – перед внедрением нужно тщательно обдумать какие папки анализировать, какие исключить из анализы, подкрутить правила. Также присутствует некоторая специфичность к версии Java.</li>
    <li id="Gats">Не всегда точные результаты – результаты анализы могут давать ложные срабатывания или пропуски, и иногда требуется ручная проверка.</li>
    <li id="yRZY">Слабая ролевая модель – довольно неудобно настраивать права доступа, назначать фикс багов на определенных людей</li>
  </ul>
  <h2 id="DPWM">Экосистема</h2>
  <p id="FyyU">У SonarQube отличная экосистема плагинов как платных, так и бесплатных.</p>
  <p id="dNEp">Например, интеграция с Jira, PDF-отчеты. Есть на что <a href="https://github.com/SonarQubeCommunity" target="_blank">посмотреть</a>.</p>
  <figure id="s7Dg" class="m_retina">
    <img src="https://lh7-us.googleusercontent.com/slidesz/AGV_vUfzBdwTUb2hElTEtQ2Y0kx0o8m2pIIlXbQzo4MDID-dIszpNzNNNP9TSPj5n6UUr4lzju_9-X5S-VPVSYJTjOHw2ruLqPqhstdwVKOXfsl68KFJFjLN2xorPimoY_BGiFGrmOrdBqmsK9jipV7sU1JPb8P4k0IE=s2048?key=-Pe2jLKpkioMA9qQvveyLg" width="461.5" />
  </figure>
  <p id="DYpq"><strong>sonarqube-community-branch-plugin</strong></p>
  <p id="NRxY">В Community Edition нет анализа веток. Но можно использовать плагин <a href="https://github.com/mc1arke/sonarqube-community-branch-plugin" target="_blank">sonarqube-community-branch-plugin</a>.</p>
  <figure id="cFR4" class="m_retina">
    <img src="https://lh7-us.googleusercontent.com/slidesz/AGV_vUcDUVrcJOSSqs9DBjDmklO5p4mg5k9EF6D_XhZj_loC3_tXqFaEFqZQaeba7cDgwcLglQV1JpSEDI4JjRW-6WzymNzlA-j0KE7rsbpBuHHjBBxgyMjot53_m5caECRN9ZyxxNxroRYWArEqZPNpCuvM2OgDJe2-=s2048?key=-Pe2jLKpkioMA9qQvveyLg" width="341" />
  </figure>
  <p id="Ao8Z"><strong>sonar-gitlab-plugin</strong></p>
  <p id="Dkn4">С помощью плагина <a href="https://github.com/gabrie-allaigre/sonar-gitlab-plugin" target="_blank">sonar-gitlab-plugin</a> можно оставлять комментарии к МР.</p>
  <figure id="aeYE" class="m_retina">
    <img src="https://lh7-us.googleusercontent.com/slidesz/AGV_vUcX2z2a3Te0XmfIIrO4bp_OkQWtJ39O6yRo328nHLhUm8qwFi0jd0YvUgjejU1qjeCZAtcOfrXX_KVt64R9RXn_wCZj09kLEbJm1_3LspZXdEWQemHkbSa4Yx3eNXRO5sGa4BsoMs14oJiYfd7aGY8oZc6sHKsm=s2048?key=-Pe2jLKpkioMA9qQvveyLg" width="589" />
  </figure>
  <p id="xNn2"></p>
  <h3 id="b4am"><strong>Интеграция с IDE</strong></h3>
  <p id="R2Oe">Плагин <a href="https://www.sonarsource.com/products/sonarlint/" target="_blank">SonarLint</a> доступен во всех популярных редакторах кода.</p>
  <p id="BmI3">На примере VS Code, в данном случае редактор подсветит ошибку с подробным описанием, так же можно перейти прямо в анализатор в браузере и проверить историю.</p>
  <figure id="LjoT" class="m_column">
    <img src="https://lh7-us.googleusercontent.com/slidesz/AGV_vUfnK3vRshEcR4oh3f-eMV8n5R4Ud57DW3LAVdetPQ8ExBG6fJ1uBItrIkwKBQ6aZe3ifOvUhwtXAIfH2V2xP-9Zj1LS3ZJN6tqj_XHV2HoLbaGudK50sBR2jwoO6IwegLfrhMBJa_5KVQXgL0vhm6zxXYxEyy68=s2048?key=-Pe2jLKpkioMA9qQvveyLg" width="860" />
  </figure>
  <h2 id="1fiS">Отличия версий</h2>
  <p id="nXIi">У SonarQube есть несколько версий. Подробнее о разнице версий <a href="https://www.sonarsource.com/products/sonarqube/downloads/" target="_blank">тут</a>.</p>
  <ul id="dRzE">
    <li id="KjqT"><strong>Community Edition</strong></li>
    <ul id="vBhT">
      <li id="KDjc">Статический анализ кода для 19 языков</li>
      <li id="bkKz">Обнаружение ошибок и базовых уязвимостей</li>
      <li id="2hlV">Ревью security hotspots</li>
      <li id="K8lo">Отслеживание code smells и техдолга</li>
      <li id="Qf75">Метрики code quality и истории</li>
      <li id="yhwu">Интеграция CI/CD</li>
      <li id="6tFe">Плагины от сообщества</li>
    </ul>
    <li id="3wQN">Developer Edition</li>
    <ul id="XGBH">
      <li id="emBb">Поддержка C, C++, Swift, Objective C, T-SQL, PL/SQL.</li>
      <li id="Mz6Q">Обнаружение сложных ошибок и уязвимостей</li>
      <li id="6IHu">Обнаружение ошибок крашей Python/Java</li>
      <li id="1uvC">Анализ Merge Requests</li>
    </ul>
    <li id="luMs">Enterprise Edition</li>
    <ul id="4bX6">
      <li id="1afM">PDF-отчеты</li>
      <li id="EdUj">Отчеты безопасности</li>
      <li id="qnp9">Нормативные отчеты</li>
      <li id="JQy1">Параллельная обработка репортов</li>
    </ul>
    <li id="UJRJ">Data Center Edition</li>
    <ul id="t6fG">
      <li id="MPPy">Горизонтальное масштабирование</li>
      <li id="mJnb">Улучшенный перфоманс и high load</li>
    </ul>
  </ul>
  <figure id="O8jg" class="m_retina" data-caption-align="center">
    <img src="https://img4.teletype.in/files/3a/c7/3ac7f887-4eeb-460e-834c-94d68a0b2a39.png" width="575" />
    <figcaption>Разница в одной картинке</figcaption>
  </figure>
  <h1 id="id-ОбщаяинформацияоSonarQube-Типовыепроблемыкодовойбазы">Типовые проблемы кодовой базы</h1>
  <p id="kzjP">Команда Sonarqube выделяет несколько &quot;грехов&quot; разработчиков:</p>
  <ul id="EuTP">
    <li id="wY9D">Баги и потенциальные баги</li>
    <li id="Vj71">Нарушение стандартов кодирования</li>
    <li id="GTpB">Дублирование кода</li>
    <li id="fDE3">Недостаточное покрытие модульными тестами</li>
    <li id="6qMh">Плохое распределение сложности</li>
    <li id="mEOK">Спагетти-дизайн</li>
    <li id="z4vq">Недостаточно или слишком много комментариев</li>
  </ul>
  <p id="TQz8">Посмотрим, как SonarQube отслеживает эти проблемы.</p>
  <h2 id="id-ОбщаяинформацияоSonarQube-МетрикиSonarQube">Метрики SonarQube</h2>
  <p id="XYdG">В каждом анализе SonarQube есть несколько метрик.</p>
  <figure id="cZTm" class="m_column">
    <img src="https://lh7-us.googleusercontent.com/slidesz/AGV_vUfwudd4dRpLOKF5z0zV_l9wlTEayiRaSP4shstZu24OI9Sv9k0G0lWv-HVH1Oghw6ozG9c1SccaZYxLGKioRzYXHZSn5-uI_XSWsgKly52Cdi2K2YxMNuEhGbd_m3ZElrhViMIEobAiGyOqDzyW4_G7OGBrcr5E=s2048?key=-Pe2jLKpkioMA9qQvveyLg" width="1263" />
  </figure>
  <p id="l1x1">Метрики оцениваются по шкале A до E, где E - наихудший рейтинг, говорящий о том, что был найден минимум один блокирующий баг.</p>
  <p id="U9dz">Рассмотрим основные метрики.</p>
  <h3 id="id-ОбщаяинформацияоSonarQube-Issues(Найденныепроблемы)">Issues (Найденные проблемы)</h3>
  <p id="EglJ">Показывает найденные проблемы в коде</p>
  <ul id="7D47">
    <li id="sH9w">🐞 Bug — приоритетные ошибки, которые нужно исправить как можно скорее</li>
    <li id="cyEt">💩 Code smell — незначительные огрехи, которые больше относятся к культуре кода и его оформлению</li>
    <li id="4jrf">🔒 Vulnerability – уязвимости, связанные с безопасностью.</li>
    <li id="VfCp">🛡️ Security HotSpot - потенциальные точки уязвимости</li>
  </ul>
  <p id="JRi8">У каждой ошибки есть состояния:</p>
  <ul id="zn57">
    <li id="mxbI">Открытые</li>
    <li id="kb7E">Переоткрытые</li>
    <li id="UQfk">Подтвержденные</li>
    <li id="pYtl">Ложные</li>
    <li id="J0je">Won&#x27;t fix</li>
  </ul>
  <h3 id="id-ОбщаяинформацияоSonarQube-Security(Безопасность)">Security (Безопасность)</h3>
  <p id="QpF3">Это<em> отдельная вкладка </em>где собрана информация о количестве уязвимостей и их рейтинге безопасности (от A до E). Подробнее <a href="https://docs.sonarsource.com/sonarqube/latest/user-guide/metric-definitions/#security" target="_blank">тут</a>.</p>
  <ul id="jtuM">
    <li id="4c19">A = 0 проблем</li>
    <li id="zstr">B = как минимум 1 Minor проблема</li>
    <li id="ZfLS">C = как минимум 1 Major проблема</li>
    <li id="fsgc">D = как минимум 1 Critical проблема</li>
    <li id="mtDA">E = как минимум 1 Blocker проблема</li>
  </ul>
  <h3 id="id-ОбщаяинформацияоSonarQube-Reliability(Надежность)">Reliability (Надежность)</h3>
  <p id="ohkZ">SonarQube анализирует код на предмет надежности, выявляя проблемы, которые могут привести к сбоям, ошибкам выполнения, или другим нежелательным результатам при работе программы.</p>
  <h3 id="id-ОбщаяинформацияоSonarQube-Maintainability(Поддерживаемость)">Maintainability (Поддерживаемость)</h3>
  <p id="CJSK">Во вкладке <em>Measures в разделе Maintainability </em>содержится информация о техническом долге в проекте.</p>
  <ul id="RjT1">
    <li id="N20c">Duplications</li>
    <li id="eQNv">Technical debt</li>
    <li id="8bRN">Code complexity</li>
  </ul>
  <h3 id="id-ОбщаяинформацияоSonarQube-Coverage(Покрытиетестами)">Coverage (Покрытие тестами)</h3>
  <p id="zuhe">Во вкладке <em>Measures</em> в разделе <em>Coverage</em> собрана информация о покрытии кода тестами.</p>
  <p id="ibyn">Может быть полезно для:</p>
  <ul id="zJ53">
    <li id="XGjA">Оценки качества тестирования</li>
    <li id="Nrdv">Выявление неиспользуемого кода</li>
    <li id="LhEI">Стимулирование написания новых тестов</li>
  </ul>
  <h3 id="id-ОбщаяинформацияоSonarQube-Duplications(Дублирование)">Duplications (Дублирование)</h3>
  <p id="Cz3A">Во вкладке <em>Measures</em> в разделе <em>Duplications</em> можно найти информацию о наличии дублирующегося кода.</p>
  <p id="id-ОбщаяинформацияоSonarQube-Настройкаисключенийдлядублей"><strong>Настройка исключений для дублей</strong></p>
  <p id="E3fa">При настройке проекта нужно подумать над тем какие кейсы могут быть ложно-положительными и настройте исключения для них.</p>
  <p id="wQHD">К таким же исключениям потенциально можно отнести любой автоген который хранится в репозитории, например, GQL-схемы.</p>
  <h2 id="4Xnw">Настройка проекта</h2>
  <p id="sRCT"><strong>Quality Profile (Профиль качества):</strong></p>
  <ul id="w1hM">
    <li id="FHfy">Это набор правил статического анализа кода, определяющий ожидаемый стандарт качества кода.</li>
    <li id="mvuO">Включает в себя набор правил по стилю кода, безопасности, производительности и другим аспектам.</li>
    <li id="bNec">Позволяет настроить параметры анализа для конкретного проекта или команды разработчиков.</li>
  </ul>
  <p id="pHq2"><strong>Quality Gate (Контроль качества):</strong></p>
  <ul id="6Rue">
    <li id="1z96">Это набор условий, которые определяют уровень качества кода, который необходим для успешного прохождения анализа.</li>
    <li id="2WNw">Включает в себя метрики, такие как покрытие кода тестами, процент дублирования кода, количество критических ошибок и т. д.</li>
    <li id="waZB">Если код не соответствует установленным критериям качества, Quality Gate не проходит, и разработчики получают уведомления о необходимости исправлений.</li>
  </ul>
  <figure id="ltmF" class="m_retina">
    <img src="https://img3.teletype.in/files/a3/a6/a3a65063-3447-4bf8-b8c7-6084852e6de9.png" width="402" />
  </figure>
  <h1 id="id-ОбщаяинформацияоSonarQube-Списокправил">Список правил</h1>
  <p id="Ou3b">У SonarQube есть готовые правила валидации для разных языков. Основные правила работают из коробки.</p>
  <p id="7MXH">Правила – это набор валидаций которые помогают найти баги, &quot;code smells&quot; и проблемы безопасности в ходе статистического анализа.</p>
  <p id="Spg0">Список правил:</p>
  <ul id="hx4W">
    <li id="gTkv"><a href="https://rules.sonarsource.com/javascript/" target="_blank">JavaScript</a></li>
    <li id="fvEV"><a href="https://rules.sonarsource.com/typescript/" target="_blank">TypeScript</a></li>
    <li id="5FLE"><a href="https://rules.sonarsource.com/css/" target="_blank">CSS</a></li>
  </ul>
  <p id="02w3">Также можно добавлять <em>свои правила</em> (<a href="https://docs.sonarsource.com/sonarqube/latest/extension-guide/adding-coding-rules/" target="_blank">подробнее тут</a>).</p>
  <h2 id="id-ОбщаяинформацияоSonarQube-lintersИнтеграциястороннихлинтеров">Интеграция сторонних линтеров</h2>
  <p id="Ejym">Для улучшения качества репортов SonarQube можно дать ему больше информации, например отчеты Stylelint, ESLint, TSLint через параметры.</p>
  <ul id="z5VD">
    <li id="Clqe">sonar.css.stylelint.reportPaths</li>
    <li id="5S2G">sonar.eslint.reportPaths</li>
    <li id="N7Ay">sonar.typescript.tslint.reportPaths</li>
  </ul>
  <p id="6BPA">Подробнее в <a href="https://docs.sonarsource.com/sonarqube/latest/analyzing-source-code/importing-external-issues/external-analyzer-reports/" target="_blank">документации</a>.</p>
  <h3 id="id-ВнедрениеSonarQubeвпроект(инструкция)-СозданиепроектавSonarQube">Создание проекта в SonarQube</h3>
  <p id="da1m">В UI SonarQube в разделе создания проекта, укажите ключ и название проекта.</p>
  <p id="41Ba"><em>Рекомендация: ключ должен совпадать с путем в Gitlab/Github. Например, путь в Gitlab <u>gitlab.com/frontend/awesome-project</u>, значит ключ <u>awesome-project</u><strong>.</strong></em></p>
  <figure id="CfcW" class="m_original">
    <img src="https://img2.teletype.in/files/1d/6b/1d6bb90e-d152-472e-9225-b99566abbde9.png" width="473" />
  </figure>
  <h4 id="id-ВнедрениеSonarQubeвпроект(инструкция)-tokenСозданиетокена">Создание токена</h4>
  <p id="M0Z5"><em>Рекомендация: используйте формат <u>sonar-token-{PROJECT_KEY}</u>. Например, <u>sonar-token-awesome-project.</u></em></p>
  <figure id="ND0O" class="m_original">
    <img src="https://img2.teletype.in/files/1f/7c/1f7c26f2-86e8-407e-b2ab-d09158ce8920.png" width="682" />
  </figure>
  <figure id="ZYPe" class="m_original">
    <img src="https://img2.teletype.in/files/50/f9/50f987d6-98fa-46eb-95e5-e8786cb5512c.png" width="580" />
  </figure>
  <h3 id="id-ВнедрениеSonarQubeвпроект(инструкция)-Настройкарепозитория">Настройка репозитория</h3>
  <p id="gw7M">Добавьте в .gitignore игнор файлов результатов анализа SonarQube.</p>
  <section style="background-color:hsl(hsl(24,  24%, var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <pre id="iDau" data-lang="bash"># SonarQube
.sonar/
.scannerwork/ </pre>
  </section>
  <p id="Dopj">В корне репозитория нужно создать файл <strong>sonar-project.properties</strong>. В нем указываются основные проекты, такие как хост SonarQube, название и ключ проекта, папки для сканирования.</p>
  <p id="ifab">Описание всех параметров можно найти <a href="https://docs.sonarsource.com/sonarqube/latest/analyzing-source-code/analysis-parameters/" target="_blank">тут</a>.</p>
  <section style="background-color:hsl(hsl(24,  24%, var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <pre id="YEoM" data-lang="bash"># Хост 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</pre>
  </section>
  <h3 id="id-ВнедрениеSonarQubeвпроект(инструкция)-НастройкавGitlabCI">Настройка в Gitlab CI</h3>
  <p id="BKPO">Это пример настройки в Gitlab CI.</p>
  <p id="qLRM">Переменные <em>sonar.login, sonar.projectVersion, sonar.projectDate</em> передаются через аргументы CLI.</p>
  <ul id="nFMb">
    <li id="jIaO"><strong>sonar.login</strong> – токен, полученный при создании проекта в SonarQube.</li>
    <li id="w8Jd"><strong>sonar.projectVersion</strong><em> – </em>тег релиза, например <code>CI_COMMIT_TAG</code></li>
    <li id="PbGE"><strong>sonar.projectDate</strong> – уникальная дата релиза. SonarQube выдаст ошибку если дата актуальной статы старше последней существующей статы. Например релизы 36.0.0 и 36.0.1 сделаны 01.10.2024, в таком случае SonarQube выдаст ошибку<code>Validation of project failed: Date of analysis cannot be older than the date</code> <code>of the last known analysis on this project. Value: &quot;2023-10-01T07:02:00+0000&quot;. Latest analysis: &quot;2024-10-01T07:01:57+0000&quot;. It&#x27;s only possible to rebuild the past in</code> <code>a chronological order.</code></li>
  </ul>
  <p id="xKsB">Пример джобы в Gitlab CI.</p>
  <pre id="HChw" data-lang="yaml">sonarqube-check:
  stage: check
  tags:
    - prod
  image:
    name: sonarsource/sonar-scanner-cli:4.8.1
    entrypoint: [&#x27;&#x27;]
  cache: 
    key: &#x27;${CI_JOB_NAME}&#x27;
    paths:
      - .sonar/cache
  variables:
    SONAR_USER_HOME: &#x27;${CI_PROJECT_DIR}/.sonar&#x27;
    GIT_DEPTH: &#x27;0&#x27;
  script:
    - current_tag=${CI_COMMIT_TAG}
    - echo $current_tag
    - current_date=$(date -u +&quot;%Y-%m-%dT%H:%M:%S%z&quot;)
    - 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 == &quot;master&quot;</pre>
  <h3 id="id-ВнедрениеSonarQubeвпроект(инструкция)-Генерацияисториистатов">Генерация истории статов</h3>
  <p id="r6GD">Для того чтобы сразу начать работу с техдолгом, нужно сгенерировать историю отчетов.</p>
  <p id="Vxu3">Для этого написан <a href="https://gist.github.com/yangirov/92928bea113dbdf2a7cdd719d9b942c6" target="_blank">скрипт</a>, который переходит в указанный репозиторий, перемещается по тегам релизов и сканирует релизы через <code>sonar-scanner</code>.</p>
  <p id="mCER">Сохраните скрипт <code>index.js</code> в любую папку на компьютере и выполните:</p>
  <pre id="zWhF">npm init
npm i simple-git</pre>
  <p id="4yTB">В переменной <strong><code>repositoryPath</code></strong> указывается путь до репозитория проекта.</p>
  <p id="zd6k">В переменной <strong><code>sonarScannerCliPath</code></strong> указывается путь до <code>sonar-scanner-cli</code>. Скачать можно <a href="https://docs.sonarsource.com/sonarqube/latest/analyzing-source-code/scanners/sonarscanner/#running-from-zip-file" target="_blank">тут</a>.</p>
  <p id="kfDe">В <strong>объекте config</strong> указывается основная информация</p>
  <ul id="GQfH">
    <li id="G7lN">sonar.host.url - хост SonarQube</li>
    <li id="yAy3">sonar.login - токен проекта SonarQube</li>
    <li id="zfMx">sonar.projectKey - ключ проекта</li>
    <li id="CC0e">sonar.projectName - название проекта (рекомендую чтобы совпадал с ключом)</li>
    <li id="ymfA">sonar.sources - папки для сканирования</li>
  </ul>
  <p id="08HI">Далее для начала генерации отчетов запустите скрипт.</p>
  <p id="nieB"><code>node index.js</code></p>
  <p id="OPUJ">Если релизов много, скрипт может выполняться <strong>несколько часов</strong>. После этого в дашборде появится стата по каждому релизу.</p>
  <h3 id="aLNV">Интеграция через вебхуки</h3>
  <p id="RtXf">А с помощью вебхуков можно настраивать различные автоматизации. Например, отчет о проверке релиза в чат команды.</p>
  <figure id="VdZw" class="m_original">
    <img src="https://img1.teletype.in/files/0f/c4/0fc41d40-211f-4523-b3b0-fa43ce53a556.png" width="294" />
  </figure>
  <p id="hIPl">На этом всё, надеюсь статья была полезной.</p>
  <p id="XKq1">Если вам было интересно, подписывайтесь на телеграм-канал <a href="https://t.me/s/trash_js" target="_blank">@trash_js</a> – там я пишу более короткие заметки об экосистеме фронтенда и frontops. 🎩 </p>

]]></content:encoded></item><item><guid isPermaLink="true">https://blog.yangirov.ru/apache-kafka-notes</guid><link>https://blog.yangirov.ru/apache-kafka-notes?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=yangirov</link><comments>https://blog.yangirov.ru/apache-kafka-notes?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=yangirov#comments</comments><dc:creator>yangirov</dc:creator><title>Заметки об Apache Kafka</title><pubDate>Tue, 23 Aug 2022 07:46:51 GMT</pubDate><media:content medium="image" url="https://img4.teletype.in/files/76/77/76776b1b-8ef7-470f-aee6-0e57a2464809.png"></media:content><category>Разработка</category><description><![CDATA[<img src="https://lh3.googleusercontent.com/xubAXA3t4lfSVI-9pCBLAxyqsDE2CdNKszps7INiX3GqGsDi3AJfPitd0LbzEgPlZrVT0S5cbhtGr-JvOLjJaHOljieDqusLYH0i2suEGS8UwSvwwkgrEBV-3dN8dtHg5YlpEorJmK1VRzzgdC9C_UpfEFzxA--ehZzvUkAtE92rDQP6keVjbJ3LcTA"></img>Apache Kafka — распределенный, масштабируемый и отказоустойчивый лог, способный записывать миллионы записей в секунду. 💪]]></description><content:encoded><![CDATA[
  <p id="qCS5"><strong>Apache Kafka </strong>— распределенный, масштабируемый и отказоустойчивый лог, способный записывать миллионы записей в секунду. 💪</p>
  <p id="Zoxz"><strong>Можно</strong></p>
  <ul id="gGPN">
    <li id="RHUM">записать сообщение в топик</li>
    <li id="d9lH">прочитать записи из топика</li>
    <li id="irDi">закоммитить место до которого дочитали</li>
  </ul>
  <p id="ZKz2"><strong>Ограничения</strong></p>
  <ul id="IcBz">
    <li id="UNlk">нельзя удалить сообщение</li>
    <li id="Fcko">нельзя изменить сообщение</li>
    <li id="2pzJ">поиск работает только по идентификатору</li>
  </ul>
  <p id="6xK2"><strong>Компоненты</strong></p>
  <ul id="vKN5">
    <li id="OjFR"><strong>Topic</strong>: категория сообщений по какому-то типу.</li>
    <li id="XQ4t"><strong>Broker</strong>: кластер (нода).</li>
    <li id="q53A"><strong>Producer</strong>: производители публикуют данные в топиках.</li>
    <li id="MrBl"><strong>Consumer</strong>: потребители это сервисы, которые подписываются на топики.</li>
    <li id="SfZM"><strong>Zookeeper</strong>: интерфейс координации между брокерами и потребителями Кафки.</li>
  </ul>
  <figure id="mXlt" class="m_custom">
    <img src="https://lh3.googleusercontent.com/xubAXA3t4lfSVI-9pCBLAxyqsDE2CdNKszps7INiX3GqGsDi3AJfPitd0LbzEgPlZrVT0S5cbhtGr-JvOLjJaHOljieDqusLYH0i2suEGS8UwSvwwkgrEBV-3dN8dtHg5YlpEorJmK1VRzzgdC9C_UpfEFzxA--ehZzvUkAtE92rDQP6keVjbJ3LcTA" width="682" />
  </figure>
  <h2 id="Oghp">Подробнее</h2>
  <h3 id="BYlO"><strong>Топик</strong></h3>
  <p id="W5vk">В Кафке, темы разделены и каждый раздел представлен упорядоченным списком последовательных сообщений. Кластер Кафки поддерживает раздельное журналирование (логирование) для каждой темы. Каждому сообщению в разделе присваивается уникальный идентификатор. </p>
  <p id="Abqb">Топик это по сути файл, лог. Топик разбит на партиции, нумеруются с нуля. А уже внутри партиции есть сообщения, в пределах одной партиции сообщения приходят по принципу FIFO, FIRST IN, FIRST OUT.</p>
  <p id="tXZh">Кафка гарантирует что <strong>то что попало в Кафку, из нее не пропадет.</strong></p>
  <h3 id="rTXF"><strong>Брокер</strong></h3>
  <p id="FlqQ">Обычно состоит из одного или нескольких серверов, и каждый из них может иметь один или несколько запущенных серверных процесса которые называются брокером. Топики создаются в контексте процессов брокера.</p>
  <h3 id="29zv"><strong>Zookeeper</strong></h3>
  <p id="fQtK">По сути это распределенная система необходимая для отказоустойчивости брокеров. В этой системе хранятся метаданные необходимые кафке. Например, через нее выбираются лидирующие брокеры для определенных партиций или происходит ребалансировка если отказывает какая-то нода.</p>
  <h2 id="y8TT">Отказоустойчивость</h2>
  <figure id="RG9g" class="m_custom">
    <img src="https://lh4.googleusercontent.com/ZFArOND3kELoSkwoJDULC1xKQDoT0Gh9NK12OUWOgCDOuJ0q8C6rGM2UgEj7rAIN8wElhwAxwCdYJT5J_bMo6rFI-F9eFHlogUX5Q-HlOfXE5MmZomtQEzwCiJizjnb1keGp9whsZ4hIdCDGfs7LFTgbIbM6DFXG1fGoyP74HyoK95cyIUedYOUuA2E" width="600" />
  </figure>
  <p id="nbwb">Такая устойчивость возникает за счёт репликаций партиций.</p>
  <p id="5N3h">Каждый  брокер может быть для партиции лидирующим. И кроме того эти партиции реплицируются на соседние брокеры (по мере возможности). Таким образом запись идет на несколько нод в кластере.</p>
  <p id="PU7r"><em>Допустим один из брокеров упал. Что произойдет?</em></p>
  <p id="oJif">Произойдет ребалансировка, переопределение лидера, а так как у нас есть реплика партиции, то данные мы не теряем и продолжаем читать данные оттуда где они есть. После того как упавший брокер возобновит работу (или мы поднимем новый) у нас произойдет репликация партиции и всё становится как прежде. Через какое-то время ребалансировка снова произойдет.</p>
  <p id="pa8c">И это всё работает магически под капотом, нам не нужно думать о том как работает кафка для сохранения наших данных.</p>
  <h2 id="gFdq">Сообщение</h2>
  <figure id="x2gN" class="m_custom">
    <img src="https://lh6.googleusercontent.com/2oqmLnYwrTj2Xw-wz_q9Jy2Z-FZ_hHLz4vPjWT8FJucitH82uxgbZ-IIDw3IREzivZDqiqtYDRpXTISd4jx0i1KIXEtvCBzFqnxnfp16lXSs0Lm7S6QvfqAQf1ncCqhp9yjMXzdonqTZK-k7o2sJotCWoq7rK3O2rIFLyA-QQyJuk9bIiU2xfkyHHyY" width="465" />
  </figure>
  <ul id="nbJG">
    <li id="jS1g"><strong>Номер партиции</strong> - потому что сообщение отправляется не прямо в топик, а в конкретную партицию.</li>
    <li id="7I18"><strong>Ключ</strong> - обычно байтовые значения или гуид. Так то неважно.</li>
    <li id="7p4h"><strong>Значение</strong> - полезная инфа.</li>
    <li id="MCo3"><strong>Заголовки</strong> - мета-данные.</li>
  </ul>
  <p id="sSse">Номер партиции можно выбирать самостоятельно так и автоматически через ключ (мы берем ключ, вычисляем хэш-функцию и делим на количество партиций, таким образом записи равномерно распределяется по партициям).</p>
  <h3 id="sudW">Пропускная способность и время ожидания</h3>
  <p id="4ojB">Представим, что нам нужно посылать очень много маленьких сообщений. Если мы каждое сообщение будем отправлять как отдельный вызов апи, это будет неэффективно.</p>
  <p id="0Z0L">Кафка-продюсер умеет группировать  сообщения. Мы можем настроить размер группы и время ожидания. По сути это как маршрутка :-)</p>
  <figure id="1bli" class="m_custom">
    <img src="https://lh6.googleusercontent.com/tTfJfqJpJrx0QA5xDAzmlg1YhFwA2BdNqLbvaOj4vPeATwmXvgkDnsD4Qk_lrOB3mjThhsPe6C7VlDtXyRxDGia_0Oxu1duz-nZn5y9w4H6FdpehxeFS3UdYxUzwlhO26oUnkYmpI3dEeqJeJVosBUNvMuFxfcwVnY281sz_WYEaFt5VD5Cev8kFWdA" width="704" />
  </figure>
  <h2 id="FxsM">Запись</h2>
  <p id="xnW1"><em>Как убедиться что записи отправленные в Кафку вообще там сохранены? </em></p>
  <p id="9F4Z">Есть несколько режимов (acks)</p>
  <ul id="5pX3">
    <li id="2Zwo">Простой режим, кафка просто подтверждает что сообщение дошло. Если упал брокер до записи сообщения, то сообщение потеряется.</li>
    <li id="NhyK">При записи. Подтверждаем запись только в момент записи на диск. На случай если хард отлетит.</li>
    <li id="1vIv">Бронебойный. Подтверждаем только когда сообщение реплицировались на все брокеры. Медленно, но гарантия ~100%.</li>
  </ul>
  <p id="zpEO">Чем более параноидальный режим тем больше задержка и проблем. Можно отлететь по таймауту. И что выбирать зависит от задачи.</p>
  <h2 id="2Wwu">Чтение</h2>
  <p id="NcbA">Как устроено чтение? Каждый консьюмер входит в какую-то группу.</p>
  <p id="aBpj">Если консьюмер один, он читает данные из всех партиций. Но что если данных слишком много?</p>
  <figure id="pXS9" class="m_retina">
    <img src="https://lh3.googleusercontent.com/AVB4RQB9QBoZH6zZ7zyZeL-B3_GQ6KrAeucKQd62mSJPTywaZzLO50jycmfi3utzu3ttru1KCNqP5WIV2X6wEinij8Pqov-IUTpIuSfwaCBQ4CQhx2okrBi60XO22i5IEMDK8poW1H97Tv17DtOYhqIAOxCYv2dD9ab1HOMF1vjhhF23hhfCCdKQPFM" width="355" />
  </figure>
  <p id="TLbu">Мы можем сделать больше консьюмеров. И кафка сама ребалансирует те партиции которые назначены на определенный консьюмер.</p>
  <figure id="FMNM" class="m_retina">
    <img src="https://lh4.googleusercontent.com/Ku65AwF2V143rk5f3Zw_N15LQbFkhi609DImhFGZ0gonZzJCdupjhdbR3KVDfi-Vz8xI01JHgCWz6zytWR2yhAWPARMtDyBzOMEVhHPB77hwaqWOFH1IHKv7xhs0QYYaRNtfJBgXvkq59TVwVQK_5hqIdDmYPgFlBmKq8I6HTuddhbBgE_Di940JHMA" width="355" />
  </figure>
  <p id="bGae">Но количество консьюмеров не должно быть больше чем количество партиций. Т.е. число партиций определяет максимальный параллелизм с которым мы можем обрабатывать данные.</p>
  <p id="9qEX">Конечно мы можем сделать лишний, но он ничего не будет делать.</p>
  <figure id="oTYc" class="m_retina">
    <img src="https://lh6.googleusercontent.com/t-TSoxHqdRj68xtoYWogv565mHeAffjJgnOrTni3gPIpnfpPtpbVpmkNd88qQ3diKMlxHcnal0i9jRVYnotBFaEMl5JamSicwPNNnACtnCr8S-ZMM4EVpkX5cpTnNmYS4EENgrZaEoS4aXM24k-RHRs54jDpcb4Zl3LnG5gQ5N8Sx3swPwnGYL-UYQA" width="355" />
  </figure>
  <h2 id="9Jlb">Про offset commit</h2>
  <p id="wdqY">Для надежного чтения предусмотрена такая вещь как офсет коммит.</p>
  <p id="SX89">Вот мы прочитали батч записей, обработали и перед чтением следующего блока в кафку отправляется коммит с офсетом.</p>
  <p id="Inqk">Например, консьюмер умер при чтении какого-то сообщения. В таком случае произойдет ребалансировка и сообщения прочитаются с последнего офсета.</p>
  <p id="aJFB">Таким образом мы избавляемся от необходимости повторного чтения записей с самого начала, но мы не полностью гарантированы конечно от повторного чтения.</p>
  <p id="h2su">В кафке чтения это запись в служебный топик.</p>
  <figure id="l1FX" class="m_retina">
    <img src="https://lh3.googleusercontent.com/Cjb83dE1_SQdG1W6_FfiOMA0Iy0yLS6az6e1V09tRNv-s4WHJqug3eSAseP_QHpMWcG-l6VjIFz4DCPTctUgVfN8v-7MXMUzoW6BIlEqF82j_E5bRiSzHO7S_l-zQTZLUX85KAOSO7CsyJtPcQkh6uADW0i2F-TBuGWW2GxS0RnoD7--RGGfRQ5SUb0" width="403.5" />
  </figure>
  <h2 id="rfqH">Retention policy</h2>
  <p id="mW3Y">Я говорил что из кафки нельзя удалять сообщения. Но диск не бесконечный. Поэтому в кафке есть такое понятие как ретеншн. Например мы хотим хранить только последний миллион сообщений или гигабайт.</p>
  <p id="pK7e">Как только заполняется сегмент, он удаляется.</p>
  <figure id="ir5G" class="m_custom">
    <img src="https://lh4.googleusercontent.com/NDifw6D8dpxxzHYMqb7VrQzQLeODGPQCTA7lBpI3rXl8Zh_EEn80KAsBID792dBc65T-wOtIslUyJvXLajw00easW-EnPLOAo-zE9pxGRcII4Fm8-uewZUtgM9FZLqQKC1BQXWrPsYSOgoll8HFWGGgu9U7XsVsyScKNtZIGby1r-5wtjXVxLZVadaw" width="788" />
  </figure>
  <h2 id="ZDXN">Как это может выглядеть всё вмесчте</h2>
  <figure id="W5rk" class="m_custom">
    <img src="https://lh4.googleusercontent.com/qGmvzJyXgPCOnxinW8FrDthUDmzl_PPm1eOaR4YLM1108mX-hcouJcNb90zb_D5DnjMMpNaz81s8yE31mfOkNk3IVA5NPzCbQ24gAYvNjMx9D8J7A5fXSGWRBQtdZHZBCcLami5oRYNGT7f5pzUNtT9wIrGcwGMBgIycsjJN-iikUGR91taE81yp58A" width="725" />
  </figure>
  <h2 id="bBu9">Полезности</h2>
  <p id="MPv4"><a href="https://www.confluent.io/resources/kafka-the-definitive-guide-v2/" target="_blank">Полезная книжка</a></p>
  <figure id="Kgjm" class="m_custom">
    <img src="https://lh4.googleusercontent.com/sLr8iXNalQyeUqkN4-ttmzHBS6irAO-Ilb0e-OZWoswrVd-FvV6XhyOy5LaRjnpsS5I_v_f8CfQ2c0wdEY2hHAtFUYpZQw-1R3ztjUaviTwhxorpOtZWTpyFnY2gW9Mm3nae1GROsjH6Ar3goSZJUE0-JF307WEf-a6WMN8tzo5P7ODtDmG5oUgBTNU" width="381" />
  </figure>

]]></content:encoded></item><item><guid isPermaLink="true">https://blog.yangirov.ru/commits-convention</guid><link>https://blog.yangirov.ru/commits-convention?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=yangirov</link><comments>https://blog.yangirov.ru/commits-convention?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=yangirov#comments</comments><dc:creator>yangirov</dc:creator><title>Конвенция текста коммитов</title><pubDate>Mon, 22 Aug 2022 06:46:39 GMT</pubDate><description><![CDATA[<img src="https://img2.teletype.in/files/d9/50/d950ad51-9671-4750-8677-b86db83f3cbe.png"></img>Чтобы сохранить единообразие коммитов и не путаться при поиске по репозиторию, можно подключить к проекту линтер коммитов, который проверяет текст коммитов на соответствие правилам разработки. Проверка происходит на хуке commit-msg с помощью husky, simple-git-hooks или git-hooks.]]></description><content:encoded><![CDATA[
  <p id="NiiI">Чтобы сохранить единообразие коммитов и не путаться при поиске по репозиторию, можно подключить к проекту <a href="https://commitlint.js.org/" target="_blank">линтер коммитов</a>, который проверяет текст коммитов на соответствие правилам разработки. Проверка происходит на хуке commit-msg с помощью <a href="https://www.npmjs.com/package/husky" target="_blank">husky</a>, <a href="https://www.npmjs.com/package/simple-git-hooks" target="_blank">simple-git-hooks</a> или <a href="https://www.npmjs.com/package/git-hooks" target="_blank">git-hooks</a>.</p>
  <figure id="wHGo" class="m_original">
    <img src="https://img2.teletype.in/files/d9/50/d950ad51-9671-4750-8677-b86db83f3cbe.png" width="512" />
  </figure>
  <h2 id="id-СоглашениеокоммитахишаблонахкМР-Мотивация">Мотивация</h2>
  <ul id="ZM15">
    <li id="yie8"><strong>Единый стиль и понятность:</strong> Используя одинаковый формат коммитов, мы сделаем историю изменений более понятной. Каждый коммит будет иметь ясное обозначение типа изменения, области и краткое описание, что сразу даст представление о его смысле.</li>
    <li id="HOx9"><strong>Легкость поиска и навигации:</strong> Стандартизированные коммиты помогут быстрее находить связанные изменения и легче перемещаться по истории разработки. Проще отслеживать, что и когда менялось.</li>
    <li id="fUjJ"><strong>Поддержка сотрудничества:</strong> Благодаря четким коммитам команда будет лучше понимать, что делает каждый разработчик. Это улучшает коммуникацию и управление проектом.</li>
    <li id="RtOj"><strong>Упрощение автоматизации:</strong> Стандартизированные коммиты помогут автоматизировать процессы сборки, тестирования и развертывания. Меньше возможности для ошибок и быстрее выпускать новые версии.</li>
    <li id="iIDM"><strong>Автоматическая документация:</strong> Коммиты могут быть использованы для создания автоматической документации. Так пользователи и разработчики быстро узнают, что нового в каждой версии проекта. Можно использовать <a href="https://github.com/conventional-changelog/standard-version" target="_blank">standard-changelog</a>.</li>
  </ul>
  <p id="7PAr">Даже при условии сквоша коммитов в МР это полезно, потому что в истории МР будет структурированная история изменений, что упрощает код-ревью и отслеживание разработки фич. Также в Gitlab можно настроить <a href="https://docs.gitlab.com/ee/user/project/merge_requests/commit_templates.html" target="_blank">шаблон для тела коммита.</a></p>
  <p id="uASx"><strong>Примеры стандартов</strong></p>
  <ul id="cOvM">
    <li id="bmt6"><a href="https://www.conventionalcommits.org/en/v1.0.0/" target="_blank">Стандартная нотация</a></li>
    <li id="ARaA"><a href="https://www.conventionalcommits.org/en/v1.0.0-beta.4/" target="_blank">Angular нотация</a></li>
  </ul>
  <h3 id="4P4t">Предлагаемый формат коммитов</h3>
  <ul id="chqO">
    <li id="RxUJ">type(scope): subject</li>
  </ul>
  <p id="JLUi"><em>Где:</em></p>
  <ul id="BssV">
    <li id="VJtM">type — тип изменения, fix/feat/build/etc.</li>
    <li id="CuJc">scope — область, которую затронуло изменения, либо номер заявки. Если несколько, писать через запятую. Если вне заявок, пропустить.</li>
    <li id="Wgkc">subject — краткое описание проделанной работы. С заглавной буквы. Описание коммитов должно отвечать на вопрос: «Что делает коммит?».</li>
  </ul>
  <p id="gqh1"><em>Тип изменения:</em></p>
  <ul id="QKhc">
    <li id="3PP5">feat - используется при добавлении новой функциональности приложения</li>
    <li id="5SeM">fix - если исправили какую-то багу</li>
    <li id="osjj">refactor - рефакторинг кода приложения</li>
    <li id="bZpI">style - исправляем опечатки, исправляем форматирования</li>
    <li id="HiU3">chore - обычное обслуживание кода</li>
    <li id="1Q6f">revert - отмена изменений</li>
    <li id="9mUj">perf - оптимизация кода, улучшение производительности</li>
    <li id="XRTT">docs - всё, что касается документации</li>
    <li id="QbFy">test - всё, что связано с тестированием</li>
    <li id="D18f">build - всё, что связано с билдом</li>
    <li id="okyj">ci - всё, что связано с процессом деплоя</li>
    <li id="yQkX">any - не входящее ни в одну из категорий</li>
  </ul>
  <p id="uVyg">П<em>ример коммитов, которые пройдут проверку</em></p>
  <ul id="HDD1">
    <li id="OlJn">feat(front): Внедрение проверки коммитов TASK-####</li>
    <li id="VIsz">fix(back): Исправил дедлок в репозитории TASK-####</li>
  </ul>
  <p id="Slsd"><em>Примеры коммитов, которые не пройдут проверку:</em></p>
  <ul id="HVZd">
    <li id="JrNE">Зарефакторил компонент к заявке 35487</li>
    <li id="vPnu">Удаление изменений по модальному окну</li>
  </ul>
  <h3 id="Kene">Пример настройки</h3>
  <p id="UHk7">Создать файл package.json в корне проекта (рядом с папкой .git), установить менеджер гит-хуков (<a href="https://www.npmjs.com/package/husky" target="_blank">husky</a>, <a href="https://www.npmjs.com/package/simple-git-hooks" target="_blank">simple-git-hooks</a> или <a href="https://www.npmjs.com/package/git-hooks" target="_blank">git-hooks</a>).</p>
  <pre id="VBWU">git init
npm i @commitlint/cli @commitlint/config-conventional husky --save-dev
</pre>
  <p id="nGzm">Добавить в секцию с хуками хук <code>&quot;commit-msg&quot;: &quot;commitlint -E HUSKY_GIT_PARAMS&quot;</code></p>
  <p id="B4XQ">Пример package.json</p>
  <pre id="xOyE">{
  &quot;name&quot;: &quot;project-name&quot;,
  &quot;version&quot;: &quot;1.0.0&quot;,
  &quot;description&quot;: &quot;&quot;,
  &quot;husky&quot;: {
    &quot;hooks&quot;: {
      &quot;commit-msg&quot;: &quot;commitlint -E HUSKY_GIT_PARAMS&quot;
    }
  },
  &quot;devDependencies&quot;: {
    &quot;@commitlint/cli&quot;: &quot;^17.0.0&quot;,
    &quot;@commitlint/config-conventional&quot;: &quot;^17.0.0&quot;,
    &quot;husky&quot;: &quot;^8.0.0&quot;
  }
}
</pre>
  <p id="Z87b">Настроить формат коммитов в commitlint.config.js или оставить по умолчанию.</p>
  <pre id="w2qz">module.exports = {
	extends: [&#x27;@commitlint/config-conventional&#x27;],
	rules: {
		&#x27;body-leading-blank&#x27;: [1, &#x27;never&#x27;],

		&#x27;type-case&#x27;: [2, &#x27;always&#x27;, &#x27;lower-case&#x27;],
		&#x27;type-empty&#x27;: [2, &#x27;never&#x27;],
		&#x27;type-enum&#x27;: [
			2,
			&#x27;always&#x27;,
			[
				&#x27;build&#x27;,
				&#x27;chore&#x27;,
				&#x27;ci&#x27;,
        			&#x27;devops&#x27;,
				&#x27;docs&#x27;,
				&#x27;feat&#x27;,
				&#x27;fix&#x27;,
				&#x27;perf&#x27;,
				&#x27;refactor&#x27;,
				&#x27;revert&#x27;,
				&#x27;style&#x27;,
				&#x27;test&#x27;,
				&#x27;any&#x27;
			]
		],

		&#x27;scope-case&#x27;: [2, &#x27;always&#x27;, &#x27;lower-case&#x27;],

		&#x27;subject-case&#x27;: [
			2,
			&#x27;always&#x27;,
			[&#x27;sentence-case&#x27;]
		],
		&#x27;subject-empty&#x27;: [2, &#x27;never&#x27;]
	}
};</pre>
  <h1 id="id-СоглашениеокоммитахишаблонахкМР-ШаблоныMergeRequests">Шаблоны Merge Requests</h1>
  <p id="Bfgi">Также можно добавить шаблоны к Merge Requests.  Это упростит процесс ревью и убедит всех участников, что необходимые проверки и тесты были выполнены перед слиянием</p>
  <h3 id="id-СоглашениеокоммитахишаблонахкМР-Мотивация.1"><strong>Мотивация</strong></h3>
  <ul id="QfT9">
    <li id="2GPY"><strong>Стандартизация и единообразие:</strong> Шаблоны для МР позволяют установить общие стандарты и правила для всех МР в проекте. Это способствует единообразию в оформлении, структуре и требованиях к каждому МР, что облегчает их понимание и улучшает качество кода.</li>
    <li id="OKZG"><strong>Улучшение коммуникации:</strong> Хорошо структурированные шаблоны помогают разработчикам четко описывать суть изменений в МР. Это улучшает коммуникацию в команде и снижает возможность недопонимания.</li>
    <li id="S7zH"><strong>Облегчение код-ревью:</strong> Шаблоны позволяют уточнить, какой код и какой функционал должны быть протестированы перед отправкой МР на ревью. Это сокращает время, которое уходит на ревью кода, и помогает избежать пропуска критических проверок.</li>
    <li id="HL94"><strong>Повышение качества кода:</strong> Использование шаблонов позволяет включить в чеклист необходимые требования к коду, такие как правила форматирования, проверка наличия тестов и документации. Это способствует повышению качества кодовой базы.</li>
    <li id="8FDn"><strong>Улучшение прозрачности процесса:</strong> Шаблоны дают возможность ясно определить, какие шаги и требования должны быть выполнены перед слиянием МР. Это упрощает процесс слияния и делает его более прозрачным для всех участников.</li>
  </ul>
  <p id="id-СоглашениеокоммитахишаблонахкМР-ШаблонМР">Для Gitlab можно использовать <a href="https://docs.gitlab.com/ee/user/project/description_templates.html" target="_blank">шаблоны МР</a>. Пример файла <em>.gitlab/merge_request_templates/Default.md. </em>Также в шаблоне настроен автоматический выбор Assignee и создание МР в Draft.</p>
  <pre id="Oxf3">## Описание изменений

Опишите, что было сделано в этом МР.

## Чеклист

Пожалуйста, убедитесь, что все пункты ниже выполнены перед отправкой МР:
- [ ] Проставлены контексты ревью
- [ ] Добавлен Assignee
- [ ] На момент создания в МР подлит свежий develop или feature-ветка
- [ ] Все комментарии и документация актуальны и информативны
- [ ] Изменения протестированы на локальной среде разработки

Если какой-то пункт из чеклиста не выполняется, пожалуйста, исправьте это перед слиянием МР.

/assign me /draft</pre>

]]></content:encoded></item><item><guid isPermaLink="true">https://blog.yangirov.ru/BPMN-metadata</guid><link>https://blog.yangirov.ru/BPMN-metadata?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=yangirov</link><comments>https://blog.yangirov.ru/BPMN-metadata?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=yangirov#comments</comments><dc:creator>yangirov</dc:creator><title>Метаданные и BPMN: нас просят сделать космодром, а потом не превращать задачи в космолёт</title><pubDate>Mon, 07 Feb 2022 16:10:34 GMT</pubDate><description><![CDATA[<img src="https://camunda.com/wp-content/uploads/2020/06/cawemo-milestone-history-768x499.png"></img>Помните слова Германа Грефа о том что &quot;программисты не нужны&quot; и последующую статью о том как программистов пытались заменить на BPMN (Business Process Model and Notation)? Почитайте, интересная история.]]></description><content:encoded><![CDATA[
  <p id="fOlV">Помните слова Германа Грефа о том что &quot;программисты не нужны&quot; и последующую статью о том как программистов<a href="https://habr.com/ru/post/510588/" target="_blank"> пытались заменить</a> на BPMN <em>(Business Process Model and Notation</em>)? Почитайте, интересная история.</p>
  <p id="ioAf">Мой рассказ не такой красочный, но в нем тоже есть боль, страдания, принятие и  отторжение. Выводом может быть фраза  <strong>&quot;делай проще!&quot;</strong>. </p>
  <figure id="2zV6" class="m_original" data-caption-align="center">
    <img src="https://camunda.com/wp-content/uploads/2020/06/cawemo-milestone-history-768x499.png" width="768" />
    <figcaption>Пример BPMN-системы.</figcaption>
  </figure>
  <p id="BRXu">В компании в которой я работал, решили переложить часть разработки бизнес-логики с программистов на аналитиков. </p>
  <p id="RmVa">Сначала это были безобидные правки тарифов по ставкам. Потом решили сделать аля-BPMN, когда в визуальной среде стрелочками рисуется бизнес-логика, а потом из этого генерируется код на C# использующий под капотом процессную модель <a href="https://docs.microsoft.com/en-us/dotnet/framework/windows-workflow-foundation/" target="_blank">Windows Workflow Foundation</a>.  </p>
  <p id="3Ltm">И началось. </p>
  <ul id="6Uzt">
    <li id="5uO7">Постоянные конфликты JSON-конфигураций на базе которых генерировались визуальные схемы. </li>
    <li id="xov8">Усложнение обратной совместимости на  бекенде, потому что в кэше хранились процессы предыдущих версий. Формат контрактов так же ограничен особенностями схемы. </li>
    <li id="oGbg">Вместо понятного SQL или C# мы писали JSON-метаданые в кастомном формате, из которых потом генерировались Entity, DTO, ViewModel, DDL-скрипты. О релевантности такого опыта на рынке даже говорить не хочется. </li>
    <li id="x43g">Каждая новая фича давалась кровью и потом, а сроки исполнения задач росли в геометрической прогрессии. Чем естественно расстраивали менеджеров, ориентирующихся на потрясающие метрики вроде time to market, cycle time, etc.</li>
    <li id="0Tqy">И еще миллион проблем!</li>
  </ul>
  <p id="En3W">Всё получилось как в классическом примере из книги &quot;Чистый код&quot;, о том почему переусложненый продукт будет очень сложен в поддержке и сколько разработчиков не бери, всё равно всё будет плохо.</p>
  <figure id="KyuY" class="m_original" data-caption-align="center">
    <img src="https://img4.teletype.in/files/f7/c1/f7c10b99-a967-4453-a7f2-5a1810cbb137.jpeg" width="563" />
    <figcaption>Ссылка на <a href="https://books.google.ru/books?id=d6JSDwAAQBAJ&lpg=PA1&hl=ru&pg=PA27#v=onepage&q&f=false" target="_blank">легендарный пример</a></figcaption>
  </figure>
  <p id="y7BW">Также из-за того что весь проект был завязан на WWF была невозможна миграция на .NET Core (смотрели форки типа <a href="https://github.com/UiPath/CoreWF" target="_blank">CoreWF</a>, но не взлетело).</p>
  <p id="EUts">В итоге имеем сотрудников, которые работают на неактуальном стеком и изобретающими костыли для внедрения чего-либо нового где каждая задача превращается в ад.</p>
  <p id="UWG4">К примеру, я работал над одним багом три месяца и на каждом дейли говорил &quot;я в процессе, распутываю клубок&quot;. Баг был в том что при нажатии на ссылку после покупки инвалидировались данные в корзине и пользователь видел ошибку. Звучит просто? Три месяца, сынок.</p>
  <p id="7vOr">P.S. Некоторые проекты в компании отказались от использования &quot;ядра&quot; и начали делать простые круды с формочками на фронте. Стоит ли говорить что за несколько месяцев разработки их time-to-market уменьшился в несколько раз по сравнению с предыдущими годами?</p>
  <p id="MZ66">P.P.S. Мой друг из крупного китайского ритейлера написал что они отказываются от метаданных. Победа здравого смысла! </p>
  <figure id="FVUw" class="m_original">
    <img src="https://img4.teletype.in/files/bb/07/bb07b0c5-9132-44ac-8486-7ef892e8edc3.png" width="405" />
  </figure>

]]></content:encoded></item></channel></rss>