Лаборатория: какие свидетельства подтверждают релиз
Оглавление · CI/CD · Готовность · Откат и восстановление
Задача: по разрозненным результатам установить, что проверено, что применено и чего пока нельзя утверждать. Упражнения вымышленные и не выполняют deploy.
Нельзя свести релиз к одному зелёному флагу
Состояние представим как (C,A,E,D,O): C — проверенный commit, A — выбранные артефакты, E — конфигурация среды, D — данные, O — наблюдения. Связи между ними требуют свидетельств. Например, O с HTTP 200 без идентичности A подтверждает ответ endpoint, но не то, что ответил новый релиз.
Исходник схемы
flowchart TD Commit["Commit и точный run"] --> Check["Результат проверок"] Commit --> Images["Digest опубликованных образов"] Images --> Applied["Образы работающих контейнеров"] Config["Конфигурация и данные"] --> Applied Applied --> Probe["Наблюдение: endpoint или сценарий"] Probe --> Report["Утверждение с границей проверки"]
| Свидетельство | Допустимый вывод | Следующий пробел |
|---|---|---|
| Локальные тесты в worktree | Проверено локальное состояние | Commit, удалённый CI, publication |
| check success для выбранного SHA | Эти проверки прошли для run | Результат images/deploy |
| Digest получен после push | Этот image опубликован | Использует ли его VPS? |
| Контейнер запущен с image reference | Применён выбранный артефакт | Готовность нужной операции |
| HTTPS health 200 | Проверенный endpoint отвечает | Идентичность релиза, CMS/media, UI |
| Ручной editor workflow | Этот сценарий выполнен | Остальные сценарии и долговременная доступность |
Список не требует выполнять все проверки после любой опечатки в Markdown. Проверки выбирают под изменение; формулировка результата должна соответствовать реально собранным свидетельствам.
Локальный опыт: имя артефакта и хеш байтов
Следующий пример использует только Node 24 и память. Это модель content addressing, а не сборка Docker image или проверка подписи. tag — условное изменяемое имя; хеш вычисляется по конкретным байтам.
node --input-type=module <<'JS'
import assert from "node:assert/strict";
import { createHash } from "node:crypto";
const digest = (bytes) => createHash("sha256").update(bytes).digest("hex");
const first = Buffer.from("<h1>Учебник: версия 1</h1>");
const second = Buffer.from("<h1>Учебник: версия 2</h1>");
const checkedDigest = digest(first);
const registry = new Map([["lesson:current", first]]);
registry.set("lesson:current", second);
assert.equal(digest(first), checkedDigest);
assert.notEqual(digest(registry.get("lesson:current")), checkedDigest);
console.log("Имя то же; байты изменились; хеш обнаружил расхождение");
JS
Одинаковое имя не означает одинаковые байты. Для реального image digest относится к объекту manifest/index registry; это не просто sha256 tar-каталога исходников. Идентификатор помогает выбрать артефакт, но не подтверждает источник доверия или полноту его проверок. Image digest Docker.
Опыт 1: зелёный run, старый frontend
Вымышленные свидетельства:
- main/commit A: check success, images success, deploy success.
- release.sh сообщил: CMS prepared, CONTENT_READY is false.
- current указывает на релиз P; cms-current и prepared — на A.
- /api/health отвечает 200.
Сначала напишите свой вывод, затем сравните: новые образы опубликованы и CMS подготовлена, но frontend не переключён. Успех deploy job соответствует предусмотренной ветке подготовки. Нельзя утверждать, что новый web работает, только по health. Следующий шаг в настоящей процедуре зависит от явного импорта и проверки содержимого; в рамках упражнения ничего не импортируем.
Опыт 2: красный run после публикации
Вымышленные свидетельства:
- images опубликовал web и Strapi; deploy запустил CMS.
- Применение web завершилось, но HTTPS content-health получил 503.
- Скрипт попытался вернуть прежние web/Caddy; SSH затем оборвался.
Ответ: образы опубликованы, среда могла измениться, успешный rollback не подтверждён. Нужно установить фактические версии компонентов и состояние сервисов. Красный job не доказывает отсутствие изменений, а сообщение о попытке rollback — его успех. Возврат web/Caddy не возвращает БД и Strapi; сначала нужна совместимость.
Исходник схемы
flowchart LR Failure["Run завершился ошибкой"] --> Inspect["Установить фактическое состояние"] Inspect --> Compatible["Оценить совместимость кода и данных"] Compatible --> Choice["Продолжить релиз / вернуть код / восстановить данные"] Choice --> Verify["Проверить выбранный результат"]
Опыт 3: поменялся контент, commit тот же
Вымышленные свидетельства: rerun main/A успешен, редактор изменил новость между попытками; CMS_BUILD_ID всё ещё A. Образ использует build cache.
Ответ: commit не изменился, но внешний вход изменился. Нельзя по успеху rerun утверждать, что новое содержимое попало в статический слой образа. Проверяют, был ли выполнен соответствующий RUN, какой артефакт получен и что обслуживает страница после runtime-ревалидации. ISR может обновить страницу без нового image; поэтому её текст тоже не идентифицирует image. См. рендеринг.
Опыт 4: новое staging и выпущенный релиз
Вымышленные свидетельства: production успешно применил staging generation G1, но release-ветка уже получила новый commit и staging G2. Controller повторяет poll.
Ответ: production остаётся на проверенных digest G1. Охлаждать можно только совпавшую generation G1; новый staging G2 этим выпуском останавливать нельзя. Успех публикации образа G2 не означает новый production release.
Чтение настоящего pipeline без запуска
Откройте .sourcecraft/ci.yaml, environments.py и production.py. Отметьте event/ref guard, needs, границу IAM, SHA/digest capsule, общий lock, критерий успеха и recovery. YAML описывает предусмотренное поведение; состояние живого VPS из него не следует.
В деплое есть команды чтения run. Связывайте запуск с commit и проверяйте требуемые tasks, включая skipped. Не запускайте workflow и не изменяйте credentials ради упражнения.
Составьте отчёт
Для каждого опыта напишите три предложения: что подтверждено; что осталось неизвестным; какое следующее наблюдение уменьшит неопределённость. Пример: «Image опубликован под digest D. Применение на VPS не подтверждено. Нужно сверить образ работающего контейнера и выполнить выбранный сценарий». Не заменяйте неизвестное предположением ради короткого слова «готово».