Лучшие практики CI/CD

Непрерывная интеграция, доставка и развертывание — технологии разработки, возникшие из движения DevOps. Они повышают эффективность процессов создания, тестирования и выпуска ПО и позволяют доставлять продукт в руки пользователей оперативнее, чем традиционные методы. Грамотно исполненный пайплайн сборки дает команде возможность быстро доставлять работающее ПО пользователю и своевременно получать обратную связь по внесенным изменениям.

Создание CI/CD-пайплайна — это не упражнение, которое делается один раз, после чего о нем можно забыть. Как и то ПО, которое вы разрабатываете, практики CI/CD требуют итеративного подхода: анализируя данные и следя за происходящим, вы сможете улучшить выстроенный вами CI/CD-процесс. В этой статье мы рассмотрим лучшие практики непрерывной интеграции и развертывания, которые рекомендуем применить к вашему пайплайну.

Делайте коммиты рано и часто

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

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

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

Чтобы получить максимум пользы от непрерывной интеграции, важно, чтобы все разработчики публиковали свои изменения в основную ветку (master) и обновляли свою рабочую версию, подгружая изменения остальных. Общее правило: старайтесь делать коммит в master минимум раз в день.

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

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

Долгосрочные ветки используются для хранения новой функциональности, которая пока не готова к релизу. Для этой цели можно также использовать флаги функций. Они позволяют контролировать видимость той или иной функциональности в разных окружениях. Вы сможете включать изменения в основную ветку и в сборки с тестами, при этом скрывая соответствующую функциональность от пользователя.

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

Собирая решение и запуская набор автоматизированных тестов для каждого коммита, CI/CD-пайплайн дает разработчикам быструю обратную связь по их изменениям.

Цель — постоянно держать код в состоянии, пригодном для релиза. Решать проблемы сразу по возникновении — это не только более эффективный подход, но он также позволит вам быстро выпускать изменения в случае, если возникнет проблема в продакшне.

Если сборка по какой-либо причине падает, команда должна сразу заняться решением проблемы. Возникает желание обвинить того, кто внес последнее изменение в код, и оставить этого человека разбираться с проблемой. Однако обвиняя таким образом коллег, вы вряд ли создадите в команде культуру созидания, при этом причины проблем могут так и оставаться невыясненными. Возлагая ответственность за исправление сборки и выяснение причин падения на всю команду, вы сможете улучшить CI/CD-процесс в целом. Конечно, на деле, когда испытывается высокое давление и напряжение, это может оказаться не так просто. Развитие DevOps-культуры — это упражнение, которое тоже требует постоянного совершенствования.

Представьте, что вы отвлекаетесь от своей работы, принимаетесь искать причину падения и в конце концов выясняете, что оно было вызвано чем-нибудь совсем тривиальным — синтаксической ошибкой или пропущенной зависимостью. Такое может раздражать. Чтобы таких ситуаций не возникало, можно поручить членам команды выполнять сборку и базовый набор тестов локально и только после этого публиковать свои изменения. В идеале, у всех должна быть возможность использовать в качестве CI/CD одни и те же скрипты — так никому не придется делать лишнюю работу. Кроме того, рассмотрите возможность использования CI/CD-инструмента в вашей организации.

Собирайте один раз

Типичной ошибкой является создание новой сборки для каждого шага CI/CD.

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

Чтобы реализовать это, нужно сделать сборки независимыми от системы. Любые переменные, параметры аутентификации, конфигурационные файлы и скрипты должны вызываться скриптом развертывания и не быть частью самой сборки. Это позволит делать развертывание одного и того же артефакта в каждом тестовом окружении. Тогда прохождение каждой стадии будет повышать уверенность команды в этом артефакте.

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

Оптимизируйте тесты

CI/CD в значительной мере опирается на автоматизированное тестирование — оно дает уверенность в качестве разрабатываемого ПО. Однако это не значит, что вам нужно стремиться протестировать каждый возможный сценарий.

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

Вначале запускайте те тесты, которые выполняются быстрее всего, чтобы как можно скорее получить первую порцию обратной связи. Более длительные тесты можно будет выполнить тогда, когда вы уже будете достаточно уверены в своей сборке. Что касается ручных тестов, учитывая то, что они выполняются долго и требуют привлечения коллег, лучше выполнять эту фазу тестирования после того, как у вас будут зеленые авто-тесты.

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

Также вы можете вложиться в создание более сложных автоматизированных тестов (например, тестов GUI, производительности или нагрузки). После этого можно заниматься ручным исследовательским и/или приемочным тестированием. Все эти виды тестов (будь они автоматизированными или ручными) более длительны. Чтобы достичь эффективности, вам нужно сосредоточиться на вещах, которые представляют наибольший риск для вашего продукта и пользователей.

Чистите ваши окружения

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

Когда среды работают слишком долго, отслеживать изменения конфигураций становится сложнее.

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

Для создания окружений и запуска в них тестов можно использовать контейнеры. Они позволяют с легкостью настраивать и сбрасывать окружения каждый раз, когда вам необходимо выполнить развертывание: для этого используется скрипт, фиксирующий все необходимые шаги (подход Infrastructure as Code). Создавая новый контейнер под каждое развертывание, вы будете соблюдать консистентность. Также с контейнерами легче масштабировать окружения, поэтому при необходимости вы сможете тестировать несколько сборок параллельно.

Не позволяйте делать развертывание обходными путями

Допустим, вы построили надежный, быстрый и безопасный CI/CD-пайплайн, который действительно позволяет вам быть уверенными в качестве сборок. Но ваша работа легко обесценится, если вы будете разрешать людям идти в обход процессу по каким бы то ни было причинам.

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

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

Вероятно, в какой-то момент вас попросят обойти эту процедуру («ну только в этот раз!»). Вы же в этот момент, скорей всего, будете, как пожарный, всех спасать. Однако в будущем полезно поднять этот вопрос на ретроспективе или на post-mortem и разобраться, почему так произошло. Слишком ли долгий процесс? Возможно, нужно поработать над улучшением производительности. Есть ли непонимание относительно того, когда использовать CI/CD? Убедив ваших коллег в преимуществах CI/CD-пайплайнов, вы уже не столкнетесь с такого рода просьбами, если снова случится форс-мажор.

Отслеживайте и анализируйте ваш пайплайн

Создавая CI/CD-пайплайн, вы скорей всего будете реализовывать способ мониторинга продакшн-окружения, чтобы иметь возможность как можно раньше отслеживать проблемы.

Вашему пайплайну сборки, как и вашему ПО, необходим цикл обратной связи.

Анализируя метрики, собранные вашим CI/CD-инструментом, вы сможете выявлять потенциальные проблемы и области, требующие улучшения.

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

Работайте всей командой

Создание эффективного CI/CD-пайплайна требует не только подходящих процессов и инструментов, но и командной и организационной культуры.

Непрерывная интеграция, доставка и развертывание — это DevOps-практики. Они устраняют традиционную разобщенность между разработкой, тестированием и операционной деятельностью и способствуют их коллаборации между специалистами.

Устранение разобщенности помогает командам лучше обозревать процесс, дает им возможность сотрудничать и объединять разные области знаний. Поддержкой пайплайна не должен заниматься один человек. Внедрение CI/CD-платформы также может помочь в совершенствовании вашей операционной практики.

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

Культура доверия, при которой члены команды могут экспериментировать и делиться идеями, поможет не только сотрудникам, но и всей организации, и окажет положительный эффект на ваш продукт. Если что-то идет не так, не нужно обвинять в этом членов вашей команды; вместо этого стремитесь извлекать уроки из произошедшего, разбираться в причинах проблем и в том, как их избежать в будущем.

Не упускайте возможность улучшить свои CI/CD-процессы, сделать их устойчивее и эффективнее. Позволяя членам команды экспериментировать и создавать новое, не опасаясь ничьих упреков, вы поощрите культуру созидания и непрерывного совершенствования.