Главная/Материалы/Материал

Конвейер доставки

От коммита до развёрнутого образа. Схема соответствует проекту 4.

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

text
   коммит
     │
     ▼
┌─────────────┐  секунды    падает часто
│   линтер    │─────────────────────────────► падение здесь дешевле всего
└─────┬───────┘
      ▼
┌─────────────┐  минуты     падает часто
│   тесты     │
└─────┬───────┘
      ▼
┌─────────────┐  минуты     падает редко
│   сборка    │◄──── кэш из registry
└─────┬───────┘
      ▼
┌─────────────────┐  секунды
│ проверка образа │  ← проверяется ОБРАЗ, не исходники
└─────┬───────────┘
      ▼
┌─────────────┐  минуты
│сканирование │
└─────┬───────┘
      ▼
┌─────────────┐  секунды
│    SBOM     │
└─────┬───────┘
      ▼
   ┌──────────────┐
   │  все = 0 ?   │── нет ──► НЕ публиковать
   └──────┬───────┘
          │ да
          ▼
      публикация

Как читать

Порядок не назначен, а выведен: сортировка по отношению «время выполнения / вероятность отказа» ставит вперёд то, что падает часто и стоит секунды.

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

Три состояния этапа

text
   ┌─────────────────────────────────────────────────┐
   │  0   проверено, чисто        ──► публиковать    │
   │  1   проверено, есть находки ──► исправлять     │
   │  3   НЕ ПРОВЕРЕНО            ──► разобраться,   │
   │                                  почему нет     │
   │                                  инструмента    │
   └─────────────────────────────────────────────────┘

Без третьего кода:

text
   сканер не установился
            │
            ▼
   этап вернул 0
            │
            ▼
   конвейер зелёный
            │
            ▼
   зелёный цвет означает «мы перестали проверять»,
   и узнать об этом неоткуда

Сводка обязана различать три исхода, а публикация — требовать кода 0, а не «не провалено».

Где живёт логика

text
.github/workflows/pipeline.yaml     ← только вызовы и окружение
        │
        │  run: ci/lint.sh
        │  run: ci/test.sh
        │  run: ci/build.sh
        ▼
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       развёртывание по digest
ci/rollback.sh     откат

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

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

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

text
   коммит a1b2c3d4e5f6
        │
        ▼
   тег: ga1b2c3d4e5f6            ← неизменяемый
        │                          (+ «-dirty», если дерево не чисто)
        ▼
   публикация ──► registry
        │
        ▼
   digest: sha256:9f8e7d6c…      ← вычислен из содержимого
        │
        ▼
   развёртывание ПО DIGEST       ← не по тегу

Почему не по тегу:

text
   собрали ──── время ────► запустили
      │                        │
      │  за это время тег      │
      │  мог указать на другое │
      ▼                        ▼
   образ A                  образ B

Три места расхождения: pull без пересоздания container'а; тег перезаписан между pull и запуском; опубликовано не то, что собрано.

Откат

text
   artifacts/deployed-production.txt   ← что развёрнуто сейчас
   artifacts/previous-production.txt   ← на что откатиться
                    │
                    ▼
            ci/rollback.sh production

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

Два разных кэша

text
   кэш СЛОЁВ                     cache mount
   ──────────                    ───────────
   --cache-to type=registry      RUN --mount=type=cache
   переносится между запусками   живёт на машине сборки
   нужен mode=max                НЕ переносится в CI

Их путают чаще всего. mode=min — значение по умолчанию — экспортирует только последнюю стадию, и слой с зависимостями в кэш не попадает.

Что проверить в своём конвейере

ПроверкаКак
Падает быстро на частой ошибкеСломать линтер, замерить время
Отсутствие сканера даёт 3Убрать сканер из PATH
Провал перевешивает непроверенноеПодать оба состояния в сводку
Публикация требует кода 0Условие в шаге публикации
Тег меняется при грязном деревеСоздать неотслеживаемый файл
Развёртывание по тегу отвергаетсяПередать тег вместо digest
Откат без записи отказываетУдалить файл с предыдущим digest

Подробнее

Урок 16.1. Проектирование конвейера
Урок 16.3. Кэш в CI
Урок 16.4. Сканирование и SBOM
Проект 4. Production pipeline


Навигация

Раздел 16. CI/CD
Диаграмма стека Compose
Главное оглавление

Markdown на GitHub ↗