Главная/Проекты/Проект

Проект 4. Production pipeline

Выполнять после: раздела 16
Опирается на разделы: 11, 12, 14, 15, 16
Ориентировочное время: 12 часов
Оценивание: rubric, проходной результат 70


Задача

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

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

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


Требования

Обязательные

ТребованиеПроверяется
1Логика в скриптах, а не в шагах YAMLChecklist 1
2Порядок этапов выведен, а не назначенChecklist 2
3Три состояния этапа: пройдено, провалено, не провереноChecklist 3
4Сканирование образа с отдельным кодом «не проверено»Checklist 3
5SBOM; частичный состав помечен как частичныйChecklist 4
6Проверки применяются к собранному образуChecklist 5
7Тег неизменяемый: SHA коммита, признак грязного дереваChecklist 6
8Кэш сборки переносится между запускамиChecklist 7
9Развёртывание по digest; развёртывание по тегу запрещеноChecklist 8
10План отката — команда, а не пожеланиеChecklist 8
11Скрипты конвейера покрыты тестамиChecklist 9

Требования, невыполнение которых снимает работу

  • отсутствие сканера даёт зелёный конвейер;
  • публикация происходит при непройденных проверках;
  • образ развёртывается по перезаписываемому тегу;
  • «план отката» не содержит выполнимой команды.

Архитектура

Три состояния вместо двух

КодЗначениеЧто делать
0Проверено, чистоПубликовать
1Проверено, есть находкиИсправлять
3Не провереноРазобраться, почему инструмента нет

Без третьего кода сканер, который не установился, неотличим от сканера, не нашедшего проблем (урок 16.4). Хуже того: конвейер становится зелёным именно в тот момент, когда перестал проверять.

Требование 3 распространяется на конвейер целиком: итоговая сводка обязана различать три исхода, а публикация — требовать код 0.

Логика в скриптах

text
.github/workflows/pipeline.yaml   ← только вызовы и окружение
ci/lib.sh                         ← общие определения, коды возврата, теги
ci/lint.sh  ci/test.sh  ci/build.sh
ci/verify-image.sh  ci/scan.sh  ci/sbom.sh
ci/pipeline.sh                    ← порядок и сводка
ci/deploy.sh  ci/rollback.sh

Следствий три, и каждое проверяемо:

СледствиеКак проверить
Конвейер отлаживается локальноci/pipeline.sh работает без CI
Перенос на другую платформу механическийШаги YAML — только run: ci/*.sh
Те же скрипты проверяют образ в тестахci/verify-image.sh вызывается и оттуда

Порядок этапов

Сортировка по время / вероятность отказа: вперёд то, что падает часто и стоит секунды.

text
линтер          → секунды,  падает часто
тесты           → минуты,   падает часто
сборка          → минуты,   падает редко
проверка образа → секунды,  падает редко
сканирование    → минуты,   находки бывают
состав (SBOM)   → секунды,  не падает

Сканирование стоит после сборки не по времени, а по смыслу: проверяется образ, а не исходники. Между ними Dockerfile, и его ошибки исходниками не ловятся.

Теги и развёртывание

ЧтоПравило
Тегg<sha12> плюс -dirty, если дерево не чисто
ПубликацияТолько при коде 0
РазвёртываниеТолько по digest
ОткатЗаписанный предыдущий digest

«Развернуть предыдущую версию» — не план отката, а пожелание. Планом он становится, когда предыдущий digest записан и команда выполнима без раздумий.


Пошаговый план

Шаг 1. Общие определения

ci/lib.sh: три кода возврата, функции журналирования, вычисление тега.

Тонкость, о которую легко споткнуться: git diff не видит неотслеживаемых файлов, а они входят в контекст сборки.

Шаг 2. Этапы

Отдельный скрипт на этап. Каждый обязан различать «инструмента нет» и «проверка не прошла».

Опора: урок 16.1.

Шаг 3. Сводка

Итог по всем этапам с тремя состояниями и кодом возврата.

Шаг 4. Образ

Базовый образ по digest, метки прослеживаемости, числовой пользователь.

Опора: урок 11.6, урок 12.7.

Шаг 5. Развёртывание и откат

Отказ при развёртывании по тегу. Запись предыдущего digest.

Опора: урок 14.4.

Шаг 6. Тесты конвейера

Скрипты — код, и проверяются как код. Иначе об ошибке в них сообщит только сломанная выкатка.


Критерии завершения

  1. ci/pipeline.sh выполняется локально без CI.
  2. Убрать сканер из PATH — итог 3, не 0.
  3. Сломать один тест — итог 1.
  4. Все проверки проходят — итог 0.
  5. ci/deploy.sh образ:тег отвергается; образ@sha256:… принимается.
  6. ci/rollback.sh без записанного digest отказывается работать.
  7. Добавить неотслеживаемый файл — тег получает -dirty.
  8. Шаги в YAML не содержат логики: только run: ci/*.sh и окружение.
  9. Тесты конвейера проходят при грязном рабочем дереве.

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


Дополнительные задания

ЗаданиеЧто добавляет
1Подпись образа и проверка подписиУрок 12.7
2Проверка воспроизводимости: две сборки — один digestУрок 5.9
3Развёртывание в два окружения с разными порогамиРазные требования к одному образу
4Автоматический откат при провале проб после выкаткиСвязь конвейера и эксплуатации
5Измерить, сколько даёт кэш между запускамиЧисло вместо предположения

Ни одно не реализовано в эталонном решении — причины названы в его конце.


Навигация

Список проверок →
Эталонное решение → — открывать после собственной попытки
← Предыдущий проект: Multi-service stack
Вернуться к проектам
Главное оглавление

Markdown на GitHub ↗