
Недавно у нас на работе стихийно возник спор о том, стоит ли вводить непрерывную доставку. Не имея в виду сразу переделывать все наши процессы под непрерывную доставку, я, однако, отстаивал целесообразность такого подхода в общем. К сожалению, после начала спора я за приемлемые 510 минут так и не нашел в интернете подходящего текста, доходчиво объясняющего, зачем нужна непрерывная доставка, чтобы хорошенько подкрепить свою точку зрения. Материалов о том, как наладить непрерывную доставку, очень много, а вот статей (на русском языке) о том, зачем же это нужно, недостает.
Давайте исходить из того, что цель жизни нормального человека это написать побольше интересного кода и закинуть его на прод. С такой точки зрения, думаю, важность непрерывной доставки очевидна. Увы, оказалось, что есть и совершенно другие люди (вы можете узнать их по таким странными выражениям, как качество продукта, ресурсы, скорость исправления ошибок, трудозатраты), которым нормальные ценности чужды. Чтобы легче было достучаться до них и чтобы под рукой всегда была краткая памятка по отстаиванию единственно правильной точки зрения, я и написал этот текст.
Ладно, в некоторых довольно редких, надо сказать, ситуациях организовать непрерывную доставку действительно почти невозможно. Думаю, вы и сами поймете это, когда окажетесь в подобной ситуации. На всякий случай ближе к концу этого материала описаны случаи, в которых выгоды непрерывной доставки явно не окупят расходов на ее организацию.
Определения
В данном материале будем пользоваться следующими тремя определениями М. Фаулера.
Непрерывная интеграция (Continuous Integration) когда продукт регулярно (несколько раз в день) собирается из исходного кода и для него запускается существенная часть автоматических тестов, например все модульные тесты. Если автоматические тесты работают долго, то их можно запускать реже, например раз в сутки. Стандартный подход для организации непрерывной интеграции это запустить TeamCity или Jenkins, которые будут загружать исходный код из системы контроля версий, собирать его и запускать тесты. Другие известные решения: Travis CI, GitLab, Space, GitHub, BitBucket.
Непрерывная доставка (Continuous Delivery) продукт всегда находится в собранном состоянии и готов к передаче в промышленную эксплуатацию, даже с учетом последних изменений, внесённых разработчиками в код. Скорее всего, непрерывная доставка будет реализована на основе тех же технологий, что и непрерывная интеграция. В этой статье на Хабре приводятся еще несколько подходящих открытых инструментов. В другой работе подробно рассматривается разница между реализацией конвейера сборки в облаке и на земле.
Непрерывное развертывание (Continuous Deployment) когда обновления продукта регулярно (например, после каждого изменения, внесенного разработчиками) вводятся в промышленную эксплуатацию, и при этом все процессы предметной области продолжают работать без сбоя. В некотором роде непрерывное развертывание это хорошо автоматизированная и часто выполняющаяся непрерывная доставка.
Чтобы лучше осознать эти понятия, можно посмотреть на картинку, где приведена более-менее универсальная схема современного процесса разработки и доставки программного продукта. В каких-то компаниях используются дополнительные компоненты, а некоторые из указанных не используются.

Мне кажется, что в профессиональной среде чаще пользуются обобщающим все вышеперечисленное термином CI/CD с необходимыми уточнениями, чтобы не задумываться о том, какой из трех терминов включает регулярное автоматическое развертывание продукта в средах для разработки и тестирования.
Две деревни
Чтобы разобраться в произношении названий, предлагаю заинтересованным почитать Ответы Mail.ru, а я далее буду пользоваться латиницей. О чем это я? Конечно, о двух захолустных деревнях Villarriba и Villabajo: обе деревни живут типичным сельским трудом производят программное обеспечение. Жители первой деревни вводят обновления своего продукта в промышленную эксплуатацию каждый день, ну, может быть, кроме пятниц (то есть практикуют непрерывную доставку или развертывание), а жители второй каждые две недели. На их примере предлагаю рассмотреть несколько параметров стандартного процесса изготовления и сопровождения программных продуктов. Это поможет лучше понять, в чем заключаются рассматриваемые подходы.
Скорость устранения ошибок
Жители Villabajo выкатывают изменения раз в две недели. За две недели они делают много новой функциональности, поэтому, когда они ошибаются в одной из новинок, им приходится либо 1) откатывать сразу все изменения и, если надо, выковыривать из версии дефектное изменение, собирать версию заново и ставить ее (впопыхах, естественно), либо 2) ковыряться сразу во всех изменениях, которые они выкатили, пытаться понять, какое из этих изменений привело к ошибкам, и отлаживать это в бою.
Жители Villarriba готовы выкатывать изменения хоть несколько раз в день. Чем чаще они выкатывают обновления, тем меньше изменений у них накапливается. Чем меньше изменений одновременно вводится в промышленную эксплуатацию, тем легче откатить ошибочные изменения или, при возможности, исправить их прямо в работающем продукте, потому что изменения изолируются друг от друга и, значит, меньше друг на друга влияют.
Казалось бы, жители Villarriba ошибаются не реже жителей Villabajo, поэтому количество дефектов в промышленно эксплуатируемом продукте одинаковое! Однако жители Villarriba в среднем исправляют каждый дефект быстрее, чем жители Villabajo, потому что им легче разобраться в причинах ошибки, легче откатить ошибочные изменения и легче накатить исправленную версию.
Но и здесь не все так просто: жители Villabajo не хотят ставить обновления часто не потому, что они такие злые, а потому, что у них плохо автоматизирован процесс публикации своего продукта. В результате они, в отличие от жителей Villarriba, страдают еще и от ошибок в продукте, порожденных неправильной установкой версии. На эту тему есть интересное исследование (стр. 53).
Затраты на установку новой версии
Жители Villabajo выкатывают изменения раз в две недели. В отличие от серьезных b2b-контор из столицы 6-й экономики мира, у жителей Villabajo действительно четко запланирован объем каждого спринта, а еще они научились проверять, все ли нужное вошло в версию (и не попал ли туда мусор), в полуавтоматическом режиме.
Тем не менее каждый житель Villabajo регулярно тратит по несколько часов, чтобы:
1) проверить версию на полноту включенных изменений (да, в полуавтоматическом режиме), включить в версию то, что забыли, и выкинуть то, что попало по ошибке, договориться с остальными жителями деревни и с заказчиком о том, что пришло время ставить обновление;
2) выполнить то, что нужно сделать до установки версии, например, запустить скрипты, отладить и починить их, потому что они не были полностью готовы к запуску в бою;
3) выполнить то, что нужно сделать во время установки версии, например, запустить скрипты, отладить и починить их, потому что они опять не были полностью готовы к запуску в бою;
4) выполнить то, что нужно сделать после установки версии, например, запустить скрипты, отладить и починить их, потому что они в третий раз не были полностью готовы к запуску в бою.
Жители Villarriba готовы выкатывать изменения раз в день. Им приходится почти все время держать продукт готовым к введению в промышленную эксплуатацию с учетом самых последних обновлений. У них нет скриптов для выполнения перед установкой новой версии, во время и после нее. Они ведут разработку таким образом, чтобы можно было вводить новую функциональность постепенно, по одному небольшому контролируемому блоку за версию. Жителям Villabajo нет смысла так делать: у них же версии раз в две недели.
Что в итоге? Жители Villabajo каждые две недели тратят первую половину рабочего дня на то, чтобы установить версию, а вторую половину на просмотр YouTube (в лучшем случае чтение Хабра), потому что после стресса они не могут продуктивно работать (серьезно, см., например, вот эту публикацию, стр. 53). А жители Villarriba работают в обычном режиме, только иногда отвлекаются на то, чтобы откатить последние изменения с боевого сервера.
Рассматриваемый эффект уменьшение затрат на установку версии вполне очевиден и подтверждается реальными случаями. Например, непрерывная доставка помогла одной из команд Hewlett-Packard снизить общие затраты на разработку на 40%.
В одном исследовании (стр. 53) показывается, как непрерывная доставка избавила инженеров компании от необходимости тратить несколько дней (разумеется, в каждой компании это значение свое) на подготовку и установку версии. В этот же эффект, очевидно, включается и отмеченное там же уменьшение затрат на исправление ошибок именно в самом процессе подготовки и установки версии.
В другом исследовании (стр. 67) некоторые из опрошенных компаний в качестве существенного преимущества непрерывных подходов отметили уменьшение количества ручного труда, необходимого для управления всем циклом разработки и доставки.
Включение и отключение новой функциональности
Жители Villabajo выкатывают изменения раз в две недели. Если их заказчик хочет какую-то функциональность, то он вместе с жителями Villabajo согласует дату, когда он увидит эту функциональность, и жители Villabajo готовят ее точно к сроку. Более того, в некотором смысле заказчик не может отказаться от запланированной функциональности: сначала этой функциональности нет на боевом сервере, потом есть день установки версии, а потом эта функциональность отлита в граните.
Чтобы откатить эту функциональность (либо из-за того, что жители Villabajo ошиблись, либо из-за того, что сам заказчик или другие взаимодействующие с продуктом Villabajo системы не готовы), надо установить предыдущую версию, удалить из новой версии оказавшуюся ненужной функциональность и установить эту исправленную новую версию. Особенно жители Villabajo унывают в таких случаях, когда новая версия успела создать данные, которые не могут быть обработаны старой версией: приходится чистить или переформатировать эти данные.
Жители Villarriba готовы выкатывать изменения раз в день. Если их заказчик хочет какую-то функциональность, то, после того как она готова к публикации, он может в любой момент включить ее. Еще жители Villarriba сделали так, чтобы заказчик мог вернуться к предыдущей версии, пока полностью не убедится в том, что его устраивает новая функциональность. Такой подход выглядит наиболее естественным в случае, когда основная ветка исходного кода должна быть готова к публикации в любой момент.
В отличие от жителей Villabajo, жители Villarriba тратятся на поддержание кода в адекватном состоянии и, возможно, на переключатели функциональности, но 1) им не приходится тратиться на откатывание оказавшихся ненужными изменений и на докатывание исправленных версий; 2) их заказчикам не нужно согласовывать миг, в который новая функциональность становится неотъемлемой частью системы.
Заказчики жителей Villarriba довольны. Это и неудивительно: положительное влияние такого подхода на отношения между заказчиком и исполнителем подтверждают научные исследования (стр. 67).
Продолжительность цикла разработка публикация корректировка
Жители Villabajo выкатывают изменения раз в две недели. В большинстве случаев они не имеют возможности проверить, как поведет себя новая функциональность на боевом сервере. В отличие от серьезных b2b-контор из столицы 6-й экономики мира у них есть много сред развертывания, и одна из них по своим параметрам почти совпадает с боевой.
Но все же различия между боевой и почти боевой средой не позволяют жителям Villabajo точно предсказывать последствия публикации новой версии. Можно выкатывать новую функциональность по чуть-чуть, но кто же будет ждать, пока этих двухнедельных чуть-чуть наберется на заказанную функциональность? Тут и заказчик забудет, зачем она ему нужна, и разработчики будут каждые две недели после установки версии заново вспоминать, чем же они таким занимались и что там в готовящейся функциональности надо корректировать.
Жители Villarriba могут позволить себе выдавать новую функциональность небольшими порциями, попадающими в боевую среду каждый день. После публикации версии (а они даже и не особенно следят за этим, для них публикация версии это просто обычный рабочий день) жители Villarriba смотрят, как их небольшие изменения отразились на системе и ее пользователях, и в зависимости от этого корректируют готовящуюся функциональность, по необходимости информируя своего заказчика об изменениях.
Как видно, жители Villarriba наслаждаются коротким циклом разработка публикация корректировка, благодаря чему у них не бывает, как у жителей Villabajo, проблем с отгрузкой буквально не той функциональности, что было нужно.
Пример: положительное влияние быстрой обратной связи отмечено в исследовании (стр. 65); там же сказано, что сами разработчики при этом лучше понимают, что они делают, и больше вовлечены в рассмотрение процессов предметной области. В другом исследовании (стр. 21) указывают на прямую корреляцию между тем, 1) насколько полно компании учитывают обратную связь от клиентов для исправления своих продуктов, 2) насколько просто заинтересованные сотрудники могут увидеть и осознать жизненный цикл продукта, 3) насколько сотрудники удовлетворены работой в компании и 4) насколько сильно сотрудники ассоциируют себя с компанией.
Функциональное и регрессионное тестирование
А это немного особенный пункт, в котором рассматривается основная боль отдела обеспечения качества: функциональное и регрессионное тестирование вручную. Сначала посмотрим, зачем это нужно.
-
Очевидно, во время функционального тестирования проверяется, соответствует ли выполненная работа описанной и согласованной с клиентом постановке. В случае чего вносятся исправления.
-
В это время также может готовиться и приемочный сценарий для клиента.
-
Выявляются ошибки в тех местах, которые не покрыты автоматическими тестами.
-
Во время регрессионного тестирования проверяется функциональность, которая находится сбоку и напрямую не затрагивалась при разработке. Здесь же можно упомянуть и проверку того, как изменения, сделанные в рамках отдельных задач, дружат между собой: не появляется ли при соединении этих изменений неожиданных и нежелательных эффектов.
-
Возможно, требуется и проведение нагрузочного тестирования.
В компаниях, выпускающих новую версию раз в 23 недели, часто практикуется продолжительное ручное тестирование, к началу которого должны быть готовы все задачи, планирующиеся в предстоящую версию. После тестирования и разворачивания новой версии в боевой среде начинается новый цикл проработки технического задания, реализации и тестирования. Таким образом, если разработчики будут вливать готовые изменения в основную кодовую базу слишком часто, у отдела обеспечения качества не будет достаточного временного промежутка, когда набор внесенных изменений достаточно заморожен для того, чтобы можно было провести регрессионное тестирование.
Эту проблему решают переключатели функциональности. С их помощью можно держать внесенные изменения в спячке в тестовой среде (можно и в боевой, просто сейчас речь идет именно о тестовой среде) и включать их разом в тот момент, когда отдел собирается приступить к регрессионному тестированию. Во время тестирования разработчики вносят изменения, касающиеся других задач, например, для следующей версии. Эти изменения по умолчанию также пребывают в спячке и ждут, когда начнется тестирование следующей версии. Понятно, что переключатели функциональности помогают также и в приемочном тестировании.
Если вернуться к сюжету о двух деревнях, то скажем так: жители Villabajo заранее объединяют в одной тестовой среде все те и только те изменения, которые нужно протестировать за точно заданный временной промежуток, а жители Villarriba могут гибко менять объем тестируемых изменений и время проведения тестирования. Такое удобство досталось жителям Villarriba не бесплатно (они должны были по крайней мере внедрить переключатели функциональности), но ясно, что у нас тут вряд ли стоит искать преимущества, дающиеся без затрат.
Обобщение
Теперь давайте немного структурируем рассмотренную информацию. В следующем далее списке первыми идут те преимущества, которые дает непрерывная доставка, затем те, которые появляются и при внедрении непрерывной доставки, и при внедрении непрерывного развертывания (каждый раз новые), затем те, которые дает только непрерывное развертывание. То же и с затратами. В конце этого раздела основные идеи подытожены в виде технологического дерева компании, производящей программное обеспечение.
Преимущества
-
Установка обновлений почти полностью автоматизирована, поэтому перестают появляться ошибки из-за неправильной установки обновления.
-
Установка обновлений почти полностью автоматизирована, поэтому вы ничего не тратите на установку новой версии.
-
Изменения быстрее интегрируются и проверяются на фоне в общем стабильной системы. Заинтересованные сотрудники быстрее получают обратную связь и лучше понимают свою роль и задачи в контексте продукта в целом (как системы). Поэтому становится меньше проблем на стыке зон ответственности; исчезают симптомы вида об этом должен позаботиться кто-то другой. Качество рождается на местах, а не обеспечивается отдельным процессом (подробнее об этом здесь, на стр. 22).
-
Установка обновлений почти полностью автоматизирована, поэтому сотрудники не выгорают во время установки новой версии.
-
Установка обновлений почти полностью автоматизирована, а изменения устанавливаются небольшими порциями, поэтому вы быстрее устраняете ошибки и восстанавливаете штатную работу продукта.
-
Установка обновлений почти полностью автоматизирована, а изменения устанавливаются небольшими порциями, поэтому ошибки, которые вы допускаете, реже становятся катастрофическими.
-
Установка обновлений почти полностью автоматизирована (как и весь цикл разработки), поэтому от идеи до появления ее реализации в промышленной эксплуатации проходит очень мало времени. Благодаря этому, заказчик и исполнитель могут легко проверять свои гипотезы о новой функциональности на практике, быстрее реализовывать полезную и удалять невостребованную функциональность.
-
Обновления устанавливаются автоматически и непрерывно, поэтому вы меньше тратите на согласование установки новой версии и момента включения новой функциональности. При желании заказчик может делать это самостоятельно.
-
Обновления устанавливаются автоматически, непрерывно и небольшими порциями, поэтому вы с заказчиком начинаете лучше понимать друг друга; исчезают проблемы вида сделали не то, что хотели.
-
Обновления устанавливаются автоматически и непрерывно. Заинтересованные сотрудники быстрее получают обратную связь и лучше понимают свою роль и задачи в контексте находящегося в промышленной эксплуатации продукта. Поэтому сотрудники больше вовлечены в предприятие (и в процесс создания продукта, и в его предметную область). Они сильнее ассоциируют себя как с продуктом, так и вообще с компанией.
Затраты
-
Чтобы наладить полуавтоматическую публикацию, вы должны купить и настроить соответствующее программное обеспечение. Если у вас уже есть непрерывная интеграция, то вы наверняка сможете переиспользовать ее инфраструктуру.
-
Чтобы наладить полуавтоматическую публикацию, вы должны провести организационные изменения. Например, если единственная команда владеет доступом к нужному серверу, нужно сделать так, чтобы к серверу имели доступ все заинтересованные сотрудники. Подробности в этой статье (стр. 53).
-
Чтобы держать основную ветку исходного кода в собранном состоянии, вы не должны включать в нее потенциально разрушающие изменения. Например, если для работы новой функциональности требуется хранить данные в новом формате, то ваш продукт должен продолжительное время иметь возможность работать с данными как в старом, так и в новом формате.
-
Если вы или заказчик вручную проводите регрессионное тестирование совокупности изменений в целом, то вам нужно будет настроить переключатели функциональности. Благодаря этому, вы сможете держать в боевой среде множество изменений в скрытом виде и включать их только после того, как проверите все в тестовой среде.
-
Чтобы вводить рассмотренные изменения, вам надо будет сломать консервативную корпоративную культуру у себя и у заказчика. Это, очевидно, означает, что между вами и заказчиком должно установиться доверие достаточно высокого уровня.
-
Чтобы иметь возможность публиковать обновления продукта несколько раз в день, вы должны поменять процессы таким образом, чтобы 1) установка новой версии не требовала отдельного согласования с заказчиком или чтобы 2) заказчик мог сам управлять включением и выключением новой функциональности.
Препятствия
Есть случаи, когда внедрить непрерывные доставку или развертывание почти невозможно.
-
Некоторые предметные области плохо поддерживают непрерывное развертывание (см. стр. 69 этого исследования), например, телекоммуникационное программное обеспечение и встраиваемое медицинское оборудование.
-
Еще проблемы могут возникнуть, когда речь идет о продукте большого объема, который не покрыт автоматическими тестами или который тяжело интегрируется с остальными системами.

Как у нас?
В CUSTIS есть разные команды, так что и ситуация во всех них немного отличается. Есть команды, где налажено непрерывное развертывание, есть команды, где обновления ставятся вручную раз в несколько недель. Как было отмечено в самом начале, в моей команде как раз пока нет сильной спешки с переходом на непрерывную доставку.
Заключение
Один из проповедников непрерывной доставки отмечал в 2014 году, что многие руководители не убеждены в преимуществах такого подхода. Надеюсь, что сегодня уменьшилось хотя бы относительное число таких руководителей и что данный материал поможет аргументированно и конструктивно убедить оставшихся. Кроме этого, не забывайте и о более общих методах работы с людьми.
Если будете вести свою зловещую пропаганду, можете ссылаться на отчет State of DevOps (стр. 13). В отчете утверждается, что в 2016 году успешные компании публиковали обновления намного чаще, чем остальные (экстремальные значения показали Amazon и Netflix несколько тысяч раз в день), и у них изменения быстрее проваливались по конвейеру от включения в исходный код до введения в промышленную эксплуатацию. Но только в таком случае лучше сразу сознаться, что прямой причинно-следственной связи здесь установить нельзя. Вероятнее всего, что непрерывное развертывание это только одно из свойств успешной компании.
Источники
-
1cloud.ru. Справочная: что такое Continuous Delivery (2019)
-
Martin Fowler. ContinuousDelivery (2013)
-
Jez Humble. The Case for Continuous Delivery (2014)
-
B. Alanna, N. Forsgren, J. Humble et al. State of DevOps Report (2016)
-
Chen, Lianping. Continuous Delivery: Huge Benefits, but Challenges Too (2015)
-
Leppnen, M.; Mkinen, S.; Pagels, M.; Eloranta, V. P.; Itkonen, J.; Mntyl, M. V.; Mnnist, T. The Highways and Country Roads to Continuous Deployment (2015)
-
A. Hkli, D. Taibi, K. Syst. Towards Cloud Native Continuous Delivery: An Industrial Experience Report (2018)
-
Г. А. Минашин. Переключатели функциональности (feature toggles): виды, преимущества и работа с ними в .NET (2019)