ζ༼Ɵ͆ل͜Ɵ͆༽ᶘ

Основы CI/CD

2 комментов
14.05.2022
6 мин чтения

Основная цель любого программного проекта — зарабатывать деньги за счет автоматизации бизнес-процессов. Чем быстрее вы сможете выпустить новые версии для клиентов, тем лучше для вашей компании. Но как реализовать процесс релиза быстро? Ну можно и вручную. Например, можно подключиться к удаленному серверу по SSH. Затем вы можете клонировать репозиторий с новым кодом, собрать его и запустить с помощью командной строки. Хотя это и работает, это неэффективный подход. Итак, сегодня мы обсуждаем автоматизацию выпуска продукта и самого процесса разработки.

CI и CD — это две аббревиатуры, обозначающие непрерывную интеграцию(Continuous Integration) и непрерывную доставку(Continuous Delivery).

CI

Непрерывная интеграция описывает процесс потоков изменений в репозиторий. Давайте рассмотрим простую схему, которая дает пример развития команды.

Группа людей может работать одновременно. Но все изменения со временем переносятся в master ветку. В любом случае, даже такая простая модель вызывает пару вопросов.

  1. Как мы можем знать, что код, который идет в master ветку, компилируется?
  2. Мы хотим, чтобы разработчики писали тесты для кода. Как мы можем убедиться, что тестовое покрытие не уменьшается?
  3. Все члены команды должны форматировать код в соответствии с указанным стилем кода. Как мы можем проверить возможные нарушения?

Конечно, все описанные требования можно проверить вручную. Хотя такой подход весьма неорганизованный. Более того, когда команда растет, становится все труднее поддерживать ее.

CI был доведен до автоматизации заявленных предложений.

Начнем с первого пункта. Как мы можем проверить, что предстоящие изменения не испортят сборку? Для этого нам нужен еще один блок в нашей схеме.

Большинство процессов CI можно описать по этому алгоритму.

  1. При каждом открытии запроса на извлечение (а также при отправке новых изменений) сервер Git отправляет уведомление на сервер CI.
  2. Сервер CI клонирует репозиторий, извлекает исходную ветку (например, bugfix/wrong-sorting) и объединяется с master веткой.
  3. Затем запускается скрипт сборки. Например, ./gradlew build
  4. Если команда возвращает код 0, сборка выполнена успешно. В противном случае он считается неудачным.
  5. CI-сервер отправляет запрос с результатом сборки на Git-сервер.
  6. Если сборка прошла успешно, запрос на слияние разрешается объединить. В противном случае слияние блокируется.

Этот процесс гарантирует, что любой код, попадающий в master ветку, не нарушит дальнейшие сборки.

Проверка покрытия тестами

Усложним задачу. Предположим, что мы хотим установить минимальную планку покрытия тестами. Таким образом, в любой момент охват основной ветки не должен быть ниже 50%. Плагин Jacoco может легко решить эту проблему. Вам просто нужно настроить его так, чтобы build провалился, если значение тестового покрытия меньше допустимого.

Реализация подхода - кусок пирога. Но есть оговорка. Это может работать только в том случае, если плагин был настроен с момента запуска проекта.

Представьте, что вы работаете над продуктом, которому пять лет. С момента первого коммита проверка тестового покрытия не проводилась. Разработчики добавляли тесты случайным образом без какой-либо дисциплины. Но однажды вы решили увеличить количество тестов. Вы настраиваете плагин Jacoco так, чтобы минимальная полоса равнялась 60%. Через некоторое время разработчик открывает новый запрос на слияние. Потом вдруг понимают, что покрытие тестами всего 30%. Итак, для успешного закрытия задачи необходимо покрыть не менее 30% кода продукта. Как вы можете догадаться, для проекта пятилетней давности это почти неразрешимая проблема.

Что, если бы мы проверяли только предстоящие изменения кода, а не весь продукт? Если разработчик изменил 200 строк в запросе на слияние, ему нужно будет покрыть как минимум 120 из них (если планка покрытия тестами равна 60%). Но нет необходимости проходить через тонны модулей, которые не являются частью задачи. Это может решить проблему. Как мы можем применить это к проекту? К счастью, есть решение.

Отчет Jacoco отправляется на сервер тестового покрытия.

SonarCloud — одно из самых популярных решений.

Сервер хранит статистику предыдущих расчетов. Это полезный момент для расчета покрытия тестами предстоящих изменений, а также всего кода. Затем результат анализа отправляется на сервер CI, который отправляет его обратно на сервер Git.

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

Говоря о стиле кода, различий не так много. Вы можете попробовать плагин Checkstyle. Он автоматически отклоняет сборку, которая нарушает какое-либо из заявленных требований. Например, в коде может быть неиспользуемый импорт. Кроме того, вы можете посмотреть на облачные сервисы, которые запускают анализ кода и показывают результат в виде набора диаграмм (SonarCloud тоже может это делать).

CD

непрерывная доставка описывает процесс автоматического развертывания новой версии продукта.

Давайте внесем некоторые изменения в схему CI. Вот так может выглядеть процесс CI/CD в реальном проекте.

Во-первых, сервер CI теперь называется сервером CI/CD. Дело в том, что зачастую и CI, и CD задания выполняются одним и тем же диспетчером задач. Итак, мы рассматриваем этот подход.

Хотя это не правило. Например, можно делегировать задания CI GitLab CI, а задания CD — Jenkins.

Правая часть схемы представляет CI. Мы обсуждали это ранее. На левой картинке изображен CD. Задача CD заключается в создании проекта и развертыванием его на конечном сервере.

Стоит отметить, что сервер в нашем случае является абстракцией. Например, развертывание может перейти в кластер Kubernetes. Итак, серверов может быть несколько.

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

В любом случае, есть важный вопрос. Когда мы должны запускать задания CD? Триггеры могут быть разными.

  1. Развертывайте после каждого слияния запросов на слияние.
  2. Развертывание по расписанию.
  3. Развертывайте после того, как каждый запрос на слияние сливается с конкретной веткой.
  4. Комбинированный вариант.

Первый пункт устанавливает процесс таким образом, чтобы задания CI и CD всегда выполнялись последовательно. Этот подход довольно популярен в open-source разработке. Библиотека Semantic Release помогает настроить проект для прозрачной интеграции этого процесса.

Важно знать определение развертывания (deploy). Это не обязательно означает, что что-то где-то запускается. Если разрабатывать библиотеку, то запуска нет. Вместо этого процесс развертывания означает выпуск новой версии библиотеки.

Второй момент не зависит от процесса CI. Потому что проект разворачивается по какому-то заранее определенному расписанию. Например, каждый день в 01:00.

Третий пункт аналогичен первому. Хотя есть отличия. Предположим, что у нас есть две первичные ветки в нашем репозитории. Ветвь разработки и основная. Разработка содержит наиболее актуальные изменения. А у второго только релизы. Если нам нужно развернуть только основную ветку, нет необходимости запускать задание CD при слиянии с разработкой.

Последний пункт представляет собой совокупность всех подходов. Например, ветка разработки может быть развернута по расписанию в среде разработки. И мастер развертывается в рабочей среде при каждом слиянии запроса на слияние.

Инструменты

Рынок предлагает десятки решений для автоматизации процессов CI/CD. Давайте посмотрим на некоторые из них.

  1. Jenkins. Один из самых востребованных инструментов CI/CD в мире. Он стал настолько популярным из-за своей политики открытого исходного кода. Таким образом, вам не нужно ничего платить. Jenkins позволяет императивно описывать конвейеры сборки с помощью Groovy. С одной стороны, это обеспечивает большую гибкость. Но с другой стороны, это требует более высокого уровня компетентности.
  2. GitHub Actions. Инструмент CI/CD включен в GitHub и GitHub Enterprise. В отличие от Jenkins, GitHub Actions предоставляет декларативные сборки с конфигурацией YAML. Кроме того, решение имеет множество интеграций с различными системами обеспечения качества (например, SonarCube). Итак, сборку можно описать всего в нескольких строчках текста.
  3. GitLab CI. Это очень похоже на GitHub Actions. Тем не менее, у него есть особенности. Например, GitLab CI может указывать на конкретные тесты, в которых сборка не удалась.
  4. Travis CI. Облачный сервис CI/CD. Он предлагает множество возможностей, не требующих сложной настройки. Например, шифрование данных, которые должны быть скрыты в общедоступном хранилище. Кроме того, приятным бонусом является то, что Travis CI можно применять к публичным проектам с открытым исходным кодом GitHub, GitLab и BitBucket абсолютно бесплатно.
7
Сегодня
День улёта