Школа

← К программе

Зачем CI/CD: непрерывная интеграция, доставка и развёртывание

Урок курса «Курс подготовки DevOps-инженеров»

Хронометраж: занятие 60 минут — теория 30 минут, практика 30 минут. Домашняя работа: 1–2 часа.

Кратко о чём урок: Различие CI / CD (delivery) / CD (deployment), что даёт частая интеграция, требования к тестам и к архитектуре; связь с метриками DORA; типичный анти-паттерн «пайплайн есть, доверия нет».


1. Что изучаем

После урока вы сможете:

  • различать непрерывную интеграцию, непрерывную доставку и непрерывное развёртывание и по признакам определять, что из этого есть в конкретном проекте;
  • объяснять, почему «слито без конфликтов» и «работает» — разные утверждения, и показывать это опытом;
  • измерять время обратной связи и долю красных прогонов в реальном проекте, а не оценивать на глаз;
  • считать, во что превращается один нестабильный тест на большом наборе, и почему автоматический перезапуск задачи — не лечение;
  • называть требования, которые непрерывная доставка накладывает на тесты и на архитектуру приложения.

2. Зачем это нужно и где применяется

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

Типичная картина, в которую вы придёте: воркфлоу настроен, значок сборки в README зелёный, при этом изменение от коммита до продакшена идёт три дня, а красный прогон никого не останавливает, потому что «оно иногда падает». Формально CI/CD внедрён. Практически команда получает от него только счёт за минуты раннеров.

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

Дальше в блоке будут конкретные инструменты: модель воркфлоу GitHub Actions (09.02, 09.03), доступы без долгоживущих ключей (09.04), свои раннеры (09.05), сборка и публикация образов (09.06), проверки качества и безопасности (09.07, 09.08), доставка и стратегии выката (09.09, 09.10), релизы и откаты (09.11), перенос пайплайна в GitLab CI (09.12). Этот урок отвечает на вопрос, зачем всё это и как понять, что получилось.

3. Теория (30 минут)

3.1. Три разные вещи, которые называют одинаково

Аббревиатура CI/CD скрывает три практики. Они не взаимозаменяемы и внедряются по очереди.

Непрерывная интеграция (continuous integration, CI). Определение Мартина Фаулера: «Continuous Integration is a software development practice where each member of a team merges their changes into a codebase together with their colleagues changes at least daily. Each of these integrations is verified by an automated build (including test) to detect integration errors as quickly as possible». В переводе: каждый участник команды сливает свои изменения с изменениями коллег не реже раза в день, и каждое такое слияние проверяется автоматической сборкой с тестами.

Обратите внимание, чего в определении нет. В нём нет ни слова про сервис сборки, воркфлоу или значок в README. Ключевые слова — «не реже раза в день» и «слияние с изменениями коллег». Ветка, живущая неделю, с настроенным на неё воркфлоу — это не непрерывная интеграция, сколько бы проверок в ней ни запускалось. У Фаулера для этого есть отдельная врезка с названием «Semi-Integration (it isn't Continuous Integration)».

Непрерывная доставка (continuous delivery, CD). «Continuous Delivery then carries out any steps required to ensure that the product is releasable to production whenever anyone wishes». То есть любая сборка основной ветки пригодна к выпуску в любой момент, и выпуск — решение бизнеса, а не техническая задача. У Фаулера есть проверяемые признаки: программа развёртываема на всём протяжении жизненного цикла; команда считает сохранение развёртываемости приоритетнее новой функциональности; любой может получить быструю автоматическую обратную связь о готовности к продакшену; любую версию можно выкатить в любую среду по нажатию кнопки.

Непрерывное развёртывание (continuous deployment). «Continuous Deployment means the product is automatically released to production whenever it passes all the automated tests in the deployment pipeline». Прошло проверки — уехало в продакшен, человек в цепочке не участвует.

Различие между вторым и третьим — не техническое, а организационное: доставка даёт возможность выкатывать в любой момент, развёртывание делает это по умолчанию. Порядок внедрения при этом жёсткий: без непрерывной интеграции доставка не строится, потому что «пригодная к выпуску сборка» предполагает, что состояние основной ветки постоянно проверяется.

Слова «сборка», «релиз» и «развёртывание» мы разделили в уроке 01.03, и это разделение здесь нужно: релиз и развёртывание — разные события, поэтому непрерывное развёртывание не означает, что каждая функция сразу видна пользователю.

3.2. Интеграция — это прогон тестов, а не слияние

Ходовое объяснение пользы частой интеграции звучит так: «чем дольше ветка живёт, тем больше будет конфликтов». Проверим это измерением. В лабораторной режим diverge строит один и тот же эксперимент четыре раза: основная ветка всегда получает 12 коммитов, ветка всегда правит четыре функции, и меняется только одно — сколько функций правят обе стороны:

общих функций: 0 | коммитов в main: 12 | конфликтных блоков: 0
общих функций: 1 | коммитов в main: 12 | конфликтных блоков: 1
общих функций: 2 | коммитов в main: 12 | конфликтных блоков: 2
общих функций: 4 | коммитов в main: 12 | конфликтных блоков: 4

Число коммитов конфликты не создаёт вовсе. Их создаёт пересечение по строкам, и считается оно один к одному. Долгая ветка опасна не потому, что git тяжелее сливает, а потому что вероятность пересечения растёт со временем — но сам инструмент измеряет пересечение, а не давность.

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

тесты на main до слияния:   код 0
тесты в ветке до слияния:   код 0
git merge:                  код 0
конфликтных файлов:         0
тесты ПОСЛЕ слияния:        код 1
E       TypeError: validate() missing 1 required positional argument: 'strict'

Обе стороны зелёные. Слияние прошло без единого конфликта. Объединённое состояние не работает. Это и есть смысловой конфликт, и он объясняет, почему непрерывная интеграция определяется через автоматическую сборку с тестами, а не через git merge: проверить объединённое состояние может только прогон на нём. Отсюда же требование к порядку работы — проверять надо результат слияния, а не ветку саму по себе, иначе зелёный прогон в запросе на слияние ничего не гарантирует.

3.3. Цена редкой интеграции: поиск того, что сломалось

Вторая измеримая часть — стоимость поиска регрессии. Режим bisect берёт 200 изменений, из которых ровно одно ломает тест, и укладывает их двумя способами: по одному изменению в коммите и по десять. Дальше двоичный поиск git bisect run делает работу сам:

изменений в коммите: 1   коммитов в истории: 201  тест сейчас: код 1
  шагов bisect: 7   строк-кандидатов в найденном коммите: 1
изменений в коммите: 10  коммитов в истории: 21   тест сейчас: код 1
  шагов bisect: 3   строк-кандидатов в найденном коммите: 10

Крупные коммиты дали в два с лишним раза меньше шагов — и вдесятеро больше кандидатов в найденном коммите. Число шагов логарифмическое по числу коммитов, поэтому экономить на нём бессмысленно: семь прогонов тестов против трёх — это минуты. А вот разрешение поиска равно размеру коммита, и его выбирает автор, а не инструмент. Именно поэтому практика «маленькие частые коммиты в основную ветку» — не вопрос аккуратности, а вопрос стоимости разбирательства.

3.4. Что непрерывная интеграция требует от тестов

Требований два: тесты должны быть быстрыми и должны быть детерминированными. Оба измеримы.

Скорость. Ориентир, на который ссылается Фаулер, взят из XP: «the XP guideline of a ten minute build». Десять минут — не догма, а порог, после которого люди перестают ждать результат и начинают работать «поверх» непроверенного состояния. Насколько это выполняется на практике, легко посмотреть на живом проекте. Режим pipeline читает публичный API GitHub по репозиторию prometheus/prometheus:

ПО ВСЕМ ВОРКФЛОУ ВМЕСТЕ (так считать нельзя, смотрите таблицу ниже)
  медиана 0.5 мин, p95 16.8 мин

воркфлоу                          n   медиана  мин   макс  падений
CI                                21  16.1     11.6  33.1  29 %
govulncheck                       5   0.7      0.6   1.2   0 %
Scorecards supply-chain security  21  0.5      0.3   0.9   0 %
Check release notes               21  0.1      0.1   0.3   0 %

Числа сняты 2026-09-10 и со временем изменятся — смысл не в них, а в соотношении, которое получится и у вас. Здесь сразу две вещи. Первая: медиана «по всем воркфлоу вместе» равна 0,5 минуты, а медиана воркфлоу CI, который и есть проверка изменения, — 16,1 минуты. Разница в тридцать раз, и она целиком объясняется тем, что в репозитории десяток воркфлоу, из которых большинство — секундные служебные проверки. Одно число «среднее время пайплайна» не значит ничего: время обратной связи задаёт самый долгий обязательный воркфлоу. Вторая: 16 минут против ориентира в десять — то есть даже у образцового проекта порог не выполняется, и это нормальная отправная точка для разговора, а не повод считать проект плохим.

Детерминированность. Нестабильный тест — тот, что падает на неизменном коде. Кажется, что один такой тест — мелочь. Режим flaky показывает, что мелочь умножается. Каждый тест в наборе падает с вероятностью 5 %, набор прогоняется 50 раз:

тестов в наборе  красных прогонов  доля  ожидание 1-(1-p)^k
1                2 из 50           4 %   5 %
5                10 из 50          20 %  23 %
20               32 из 50          64 %  64 %

Измерение совпадает с арифметикой: доля красных прогонов набора равна 1 - (1 - p)^k. Двадцать тестов с пятипроцентной нестабильностью дают две трети красных прогонов на исправном коде. Таблица выше — один прогон по 50 попыток. Между прогонами числа гуляют: в трёх прогонах вышло 1–3 красных из 50 для одного теста, 9–11 для пяти и 32–34 для двадцати. Устойчиво здесь не само число, а совпадение с формулой — на это и надо смотреть. Никакой злой умысел не нужен: достаточно, чтобы каждый тест «иногда» зависел от времени, порядка или сети.

Стандартная реакция — включить автоматический перезапуск задачи. Тот же режим измеряет, что он даёт. В трёх прогонах по 50 попыток красными с первой попытки были 11, 12 и 14 наборов, а красными и после повтора — 1, 1 и 4. То есть перезапуск действительно прячет большинство падений: их становится в три-двенадцать раз меньше. Он же удваивает время обратной связи в этих случаях и убирает единственный сигнал о том, что с тестами что-то не так. Через месяц такой практики красный прогон перестают читать, и это уже не техническая проблема.

3.5. Что непрерывная доставка требует от приложения

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

  • артефакт собирается один раз и путешествует по средам неизменным — иначе «проверено» и «выкачено» относятся к разным сборкам (01.03, блок 09);
  • конфигурация приходит из среды, а не лежит в коде: один и тот же образ должен работать в тестовой среде и в продакшене (блок 07, уроки 07.02 и 07.03);
  • изменения схемы базы обратно совместимы: старая и новая версия приложения какое-то время работают одновременно, поэтому миграция не должна ломать старую (07.07);
  • приложение корректно завершается и сообщает о своей готовности — без этого автоматический выкат теряет запросы (07.05);
  • функциональность можно выключить без выката — флагами; тогда «выкатить» и «включить» становятся отдельными решениями (подробно в 09.10).

Каждый пункт — причина, по которой команда с настроенным пайплайном всё равно не может катить несколько раз в день.

3.6. Как понять, что стало лучше

Ощущения тут не годятся, и для измерения есть готовый набор — метрики программы DORA. Актуальный состав (пять метрик в двух группах), способы считать их на своих данных и типичные подтасовки разобраны в уроке 01.04; повторять это здесь не нужно. Важна только связь с текущим блоком: частота развёртываний и время от коммита до продакшена упираются в время обратной связи и в ручные шаги пайплайна, а доля неудачных изменений и время восстановления — в то, что именно пайплайн проверяет и умеет ли он откатывать.

Полезно добавить к ним две величины, которые снимаются прямо из пайплайна и хорошо описывают доверие к нему: медиана времени обязательного воркфлоу и доля красных прогонов. В измерении выше у prometheus/prometheus доля красных по всем воркфлоу — 8 % (6 из 75), а у обязательного CI — 29 %. Второе число и есть то, с чем живёт разработчик.

3.7. Анти-паттерн: пайплайн есть, доверия нет

Собирая всё вместе, получаем описание состояния, в которое приходит большинство проектов. Признаки такие:

  • красный прогон не останавливает работу: изменение всё равно сливают, потому что «падает не у нас»;
  • перезапуск задачи — обычное действие, а не событие;
  • обязательная проверка идёт дольше, чем человек готов ждать, поэтому её результат смотрят потом;
  • часть проверок ничего не блокирует: они существуют, но их падение никого не касается;
  • сборка не воспроизводится, и «попробуй ещё раз» иногда помогает.

Каждый признак поодиночке выглядит терпимым. Вместе они дают пайплайн, который тратит минуты раннеров и не даёт того единственного, за что его держат, — быстрого честного ответа на вопрос «можно ли это выкатывать». Заметить это состояние можно только числами, поэтому домашняя работа урока — не рассуждение, а два заполненных документа с измерениями.

3.8. Примеры и варианты реализации

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

Среда Как решается Что нужно иметь
Локальный стенд (Docker / VM / kind) прогон тестов и сборки в контейнере, хуки git до отправки Docker, репозиторий; общей основной ветки нет — непрерывной интеграции не получится
VPS / bare-metal свой раннер GitHub Actions или свой экземпляр GitLab сервер, доступ к репозиторию, содержание раннера (09.05)
Yandex Cloud Managed Service for GitLab плюс Container Registry для образов аккаунт, сеть, права; оплата по потреблению

Локальный стенд. На локальной машине воспроизводится вся техническая часть: те же команды сборки, тот же прогон тестов, тот же образ. Именно так проверены все числа этого урока — режимы лабораторной работают в контейнере course-ci:13 и никакого внешнего сервиса не требуют. Чего локальный стенд дать не может — самой непрерывной интеграции: для неё нужна общая основная ветка, в которую сливаются несколько человек. Поэтому локально отрабатывают содержание шагов, а не практику интеграции.

VPS / bare-metal. Здесь два варианта: подключить свой раннер к GitHub Actions (тогда сервис и логика остаются внешними, а вычисление вашим — разбираем в 09.05) или поднять свой GitLab целиком. Первое нужно, когда сборке требуется доступ во внутреннюю сеть или особое железо; второе — когда код не должен покидать вашу инфраструктуру. Оба варианта означают, что раннер становится сервисом, который надо обслуживать: обновлять, чистить кэш, следить за диском.

Yandex Cloud. Для случая «код внутри российской инфраструктуры» в Yandex Cloud есть Yandex Managed Service for GitLab — по описанию сервиса он «помогает разворачивать и поддерживать инстансы GitLab в инфраструктуре Yandex Cloud»; образы при этом складываются в Yandex Container Registry, «сервис для управления образами и контейнерами Docker». Практика с облаком идёт в блоке 11, а перенос пайплайна на GitLab CI — в уроке 09.12; здесь важно только то, что выбор сервиса не меняет ни одного вывода этого урока.

Что выбрать. Для учёбы и для большинства открытых проектов — GitHub Actions на раннерах сервиса: ничего не надо содержать, и блок 09 построен на этом варианте. Свой раннер добавляют, когда появляется причина: доступ во внутреннюю сеть, особое железо, требования к расположению данных. Свой GitLab — когда причина организационная, и тогда это отдельная служба со своей эксплуатацией, а не «просто CI».

4. Практика на занятии (30 минут)

Что делаем. Проверяем на опытах три утверждения урока и снимаем числа с реального проекта.

Курс проходят самостоятельно, поэтому каждый шаг говорит, что ввести, зачем, что должно получиться и что делать при неудаче. Все опыты идут в контейнере course-ci:13 и внешнего сервиса не требуют; для шага с реальным проектом нужен доступ к публичному API GitHub, ключ не требуется.

Файлы для работы: blocks/09-ci-cd/examples/09.01-ci-cd-concepts/

Шаги.

Шаг 1 (5 минут). Стенд.

  • Что ввести:
    cd blocks/09-ci-cd/examples/docker
    docker build -t course-ci:13 -f Dockerfile.ci .
    docker run --rm course-ci:13 sh -c 'git --version; pytest --version'
    
  • Зачем: собрать один образ, в котором проверены все числа блока, чтобы дальше запускать опыты в одинаковом окружении.
  • Ожидаемый результат: course-ci:13 появляется в docker images, в нём есть git, python3 и pytest — последняя команда печатает версии git и pytest.
  • Если не так: сборка упала — проверьте, что вы в каталоге examples/docker и что демон Docker запущен (docker ps); версии не печатаются — образ собрался не тот, пересоберите с явным -f Dockerfile.ci.

Шаг 2 (8 минут). Конфликты и смысловой конфликт.

  • Что ввести:
    cd ../09.01-ci-cd-concepts
    ./lab-cicd-concepts.sh diverge
    
  • Зачем: показать, что «слито без конфликтов» и «работает» — разные утверждения, и что число коммитов конфликтов не создаёт.
  • Ожидаемый результат: в первой части число конфликтных блоков равно числу общих функций (0, 1, 2, 4) при неизменных 12 коммитах; во второй — git merge даёт код 0 и ноль конфликтов, а тесты после слияния падают с TypeError.
  • Если не так: скрипт не находит lab-cicd-concepts.sh — вы не перешли в каталог 09.01-ci-cd-concepts (см. cd в команде); нет вывода про TypeError — режим прервался раньше, перезапустите после ./lab-cicd-concepts.sh clean.
  • Ответьте: какой шаг пайплайна поймал бы смысловой конфликт, а какой — нет.

Шаг 3 (7 минут). Нестабильные тесты.

  • Что ввести:
    ./lab-cicd-concepts.sh flaky
    
  • Зачем: увидеть, что один нестабильный тест на большом наборе даёт большинство красных прогонов, и что автоматический повтор прячет сигнал, а не чинит его.
  • Ожидаемый результат: три строки таблицы, где доля красных прогонов растёт с числом тестов и совпадает с расчётом 1 - (1 - p)^k, и ниже — эффект повтора задачи (около полутора минут).
  • Если не так: числа сильно отличаются от таблицы урока — это нормально, между прогонами они гуляют; смотреть надо на совпадение с формулой, а не на конкретное число.
  • Ответьте: попробуйте P=0.02 ./lab-cicd-concepts.sh flaky — как меняется картина при более «редкой» нестабильности?

Шаг 4 (8 минут). Реальный проект.

  • Что ввести:
    ./lab-cicd-concepts.sh pipeline
    REPO=grafana/loki ./lab-cicd-concepts.sh pipeline
    
  • Зачем: снять с живого проекта две разные медианы и долю красных прогонов и убедиться, что «среднее по всем воркфлоу» не отвечает на вопрос «сколько ждёт автор изменения».
  • Ожидаемый результат: таблица по воркфлоу, две разные медианы и доля красных прогонов. Инструмент можно запускать и напрямую: python3 pipeline-stats.py --limit 100 <владелец/репозиторий> (pipeline-stats.py).
  • Если не так: приходит ошибка о лимите запросов — без ключа GitHub разрешает 60 запросов в час на адрес; подождите или возьмите репозиторий поменьше. Скрипт lab-cicd-concepts.sh вызывает lab-cicd-concepts.sh в режиме pipeline.

Шаг 5 (2 минуты). Уборка.

  • Что ввести:
    ./lab-cicd-concepts.sh clean
    
  • Зачем: снять за собой контейнеры и временные каталоги, чтобы не копить мусор между уроками.
  • Ожидаемый результат: сняты контейнеры lab801-* и временные каталоги.
  • Если не так: остались контейнеры — проверьте docker ps -a и добейте их вручную по префиксу.

Проверка результата. Вы можете назвать по числам: сколько минут в этом проекте идёт обязательная проверка, какая доля её прогонов красная, и во сколько раз это отличается от «средней по всем воркфлоу». И вы можете объяснить на своём выводе режима diverge, почему зелёный прогон в ветке не означает, что после слияния всё работает.

5. Домашняя работа (1–2 часа)

Задание. Выберите один проект: либо публичный (годится любой активный репозиторий на GitHub с настроенными Actions), либо свой рабочий, если у вас есть к нему доступ. Разберите его пайплайн и заполните два документа.

  1. Карточка пайплайна — заготовка pipeline-card.md. Числа снимаются pipeline-stats.py, команда записывается в шапке. Нужно определить, какой воркфлоу обязателен для слияния, посчитать обе медианы и их отношение и по признакам решить, на какой ступени находится проект: непрерывная интеграция, доставка или развёртывание.

  2. Чек-лист доверия — заготовка trust-checklist.md. Десять признаков, у каждого — оценка и строка «чем подтверждается»; «не смог проверить» — законный ответ, если рядом написано, каких данных не хватило. Отдельно посчитайте по формуле 1 - (1 - p)^k, какую долю красных прогонов даёт нестабильность в вашем наборе тестов.

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

Критерии приёмки.

  • Заполнен pipeline-card.md: не меньше трёх воркфлоу с медианами, обе медианы и их отношение.
  • В карточке выбрана ступень (CI / delivery / deployment) и обоснована признаком, а не мнением.
  • В карточке названа причина, мешающая подняться на следующую ступень.
  • Заполнен trust-checklist.md: все десять строк, у каждой оценки есть подтверждение.
  • В чек-листе посчитана расчётная доля красных прогонов по формуле, рядом — наблюдаемая.
  • В чек-листе разобраны две проблемы: первый шаг и признак того, что помогло.
  • В обоих документах заполнены разделы про границы вывода: что осталось непроверенным и почему.
  • Все числа получены командой, а не оценкой на глаз; команды записаны.

6. Частые ошибки и подводные камни

«У нас есть CI, потому что настроен воркфлоу». Симптом: ветки живут неделями, зато на каждую запускается сборка. Причина: подмена практики инструментом. Непрерывная интеграция по определению требует слияния в основную ветку не реже раза в день; воркфлоу на долгоживущей ветке проверяет состояние, которого нет ни у кого, кроме её автора. Что делать: сначала укоротить ветки, потом улучшать пайплайн.

Считать «среднее время пайплайна» по всем воркфлоу. Симптом: в отчёте полторы минуты, а разработчики ждут двадцать. Причина: служебные секундные проверки сдвигают медиану вниз — в измерении выше это разница в тридцать раз. Что делать: считать по конкретному обязательному воркфлоу, как это делает pipeline-stats.py.

Включить перезапуск задачи вместо починки теста. Симптом: жёлтый значок «попытка 2 из 3» стал привычным. Причина: перезапуск прячет нестабильность — измерено, что из 12 красных прогонов после повтора остаётся 1. Что делать: считать нестабильные тесты дефектами, помечать их как известные и починить или удалить; ретрай допустим как временная мера с записанным сроком.

Верить зелёному прогону в ветке. Симптом: слили проверенную ветку — упала основная. Причина: проверялась ветка, а не результат слияния; смысловой конфликт при этом не даёт ни одного текстового конфликта. Что делать: проверять объединённое состояние — очередью слияния или обязательным обновлением ветки перед слиянием.

Стремиться к непрерывному развёртыванию раньше времени. Симптом: автоматический выкат на продакшен при пятнадцатипроцентной доле красных прогонов и необратимых миграциях. Причина: третья ступень внедряется без первых двух. Что делать: сначала честная интеграция и пригодная к выпуску основная ветка, потом автоматизация выката.

Проверять «наличие» пайплайна вместо его результата. Симптом: в отчёте написано «CI/CD внедрён». Причина: измеряется факт настройки, а не свойство процесса. Что делать: измерять время обратной связи, долю красных прогонов и частоту развёртываний — то есть заполнять карточку, а не галочку.

7. Проверка усвоения

  1. Чем непрерывная доставка отличается от непрерывного развёртывания? Приведите проект, который делает первое и сознательно не делает второе.
  2. Почему определение непрерывной интеграции содержит слова «не реже раза в день»? Что перестаёт работать, если этого нет, при полностью настроенном воркфлоу?
  3. В опыте diverge при 12 коммитах в основной ветке конфликтов не было вовсе. Почему тогда долгоживущие ветки считают проблемой?
  4. Обе стороны зелёные, слияние без конфликтов, после слияния тесты красные. Какой шаг пайплайна должен был это поймать и почему шаг «прогнать тесты в ветке» его не заменяет?
  5. В набор из 30 тестов попали два, падающих с вероятностью 5 %. Какую долю красных прогонов вы ожидаете на исправном коде? Что с этой долей сделает автоматический повтор задачи — и что он сделает со временем обратной связи?
  6. Медиана по всем воркфлоу репозитория — 0,5 минуты, медиана обязательного воркфлоу — 16 минут. Какое из чисел отвечает на вопрос «сколько ждёт автор изменения» и почему второе не является ошибкой измерения?
  7. git bisect нашёл виновный коммит за три шага вместо семи. Почему это не хорошая новость?
  8. Какие требования непрерывная доставка накладывает на миграции схемы базы данных и почему без них пригодной к выпуску основной ветки не бывает?

8. Материалы

Первоисточники:

  • Martin Fowler. Continuous Integration — статья, из которой взято определение и список практик («Everyone Pushes Commits To the Mainline Every Day», «Keep the Build Fast» и остальные). Читается за час, и это тот текст, на который ссылаются все остальные.
  • Martin Fowler. Continuous Delivery — короткая заметка с проверяемыми признаками непрерывной доставки. Полезна тем, что признаки сформулированы так, что по ним можно ответить «да» или «нет» про свой проект.
  • continuousdelivery.com — сайт Джеза Хамбла, автора книги «Continuous Delivery»: определение доставки как «способности доводить изменения любого типа до продакшена безопасно, быстро и в устойчивом режиме».
  • Метрики DORA — актуальный состав метрик и способ их считать. К этому уроку нужен только вывод, подробно — в 01.04.

Документация инструментов:

Книга (одна на выбор):

  • Джез Хамбл, Дэвид Фарли. «Continuous Delivery» — подробный разбор конвейера доставки; местами устарела в инструментах, но не в принципах.
  • Николь Форсгрен, Джез Хамбл, Джин Ким. «Accelerate» — исследовательская сторона: какие практики доставки статистически связаны с результатами компаний.

← Предыдущий: 08.11. Экосистема вокруг Docker: containerd, podman, buildah, nerdctl · Блок 09 · Следующий: 09.02. GitHub Actions: модель воркфлоу, события, джобы, шаги →

Материалы для практики

Скрипты, шпаргалки и заготовки к заданиям урока. Текст урока — на этой странице.