Files
progcode/editorial/agent-rewrites/124.json
T
huncode 2d914b543f
Build and deploy / deploy (push) Failing after 15s
Publish rewritten technical article archive
2026-08-02 22:19:34 +03:00

8 lines
15 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"index": 124,
"slug": "editorial-2024-07-field-release-engineering",
"title": "Когда версия не доказывает релиз: проверка artifact, migration и rollback",
"excerpt": "Один номер релиза может скрывать разные commit, artifact и migration. Разбираем, где остановиться, какие связи проверить и почему возврат образа не отменяет изменения данных.",
"contentHtml": "<p>В заявке на выпуск стоит <code>2024.07.0</code>. Такой же номер виден у commit, container image, migration и rollout. После выкладки сервис отвечает кодом старой схемы: новый код ждёт поле, которого в базе нет. Команда повторяет deploy, потому что все карточки выглядят согласованными. Ошибка становится дороже с каждой попыткой: растёт окно недоступности, меняется состояние данных, а точку возврата уже трудно назвать.</p>\n<p>Проблема не в самом номере версии. Проблема в том, что номер заменил связи между объектами. Он не доказывает, что artifact собран из нужного commit, что migration рассчитана на этот contract и что rollout ссылается на тот же digest. Выпуск готов только тогда, когда эти связи можно проверить по точным значениям, а отрицательный результат останавливает действие.</p>\n<h2>Где рвётся цепочка</h2>\n<p>Commit описывает исходный revision. Artifact содержит собранное содержимое и immutable digest. Migration меняет схему или данные и должна назвать целевую версию и совместимость. Rollout intent говорит, какой digest команда собирается отправить. Return point хранит предыдущую версию и digest. Эти записи связаны, но не заменяют друг друга.</p>\n<p>У каждой связи есть проверяемое утверждение. Artifact должен ссылаться на exact commit id. Migration должна называть release version и совместимость с текущей схемой. Rollout должен содержать digest из artifact, а не только tag. Return point должен быть известен до approval. Если одно утверждение ложно или неизвестно, действие заканчивается на gate. Retry не исправляет неправильную запись.</p>\n<figure><img src=\"/assets/editorial/2024/release-engineering-2024-evidence-gate.svg\" alt=\"Схема проверки связей между commit, artifact, migration, rollout и точкой возврата\" loading=\"lazy\" /><figcaption>Учебная схема показывает порядок сверки. Она не является логом CI, registry, кластера или production rollout.</figcaption></figure>\n<h2>Минимальный пример</h2>\n<p>Ниже — ограниченный учебный пример. Значения вымышлены. Код не обращается к Git, registry, CI, Kubernetes API или базе данных. Он только сравнивает заранее заданные записи и возвращает решение для проверки человеком.</p>\n<pre><code>const release={version:'2024.07.0'},commit={id:'commit-7f4a0c1'},artifact={digest:'sha256:release-070-a1',sourceCommitId:'commit-7f4a0c1'},migration={targetReleaseVersion:'2024.07.0',compatibleWith:'2024.06.3'},rollout={requestedArtifactDigest:'sha256:release-070-a1',migrationVersion:'2024.07.0'}; const checks={source:artifact.sourceCommitId===commit.id,migration:migration.targetReleaseVersion===release.version,artifact:rollout.requestedArtifactDigest===artifact.digest,rollout:rollout.migrationVersion===migration.targetReleaseVersion}; const ready=Object.values(checks).every(Boolean); if(!ready) throw new Error('stop: reconcile release records');</code></pre>\n<p>При <code>ready === true</code> пример говорит только о согласованности пяти записей. Он не говорит, что образ существует, подпись действительна, migration выполнена или сервис здоров. Если заменить <code>sourceCommitId</code> на другой id, результат должен стать отрицательным. То же относится к digest и target version. Это и есть полезный отрицательный путь: система не угадывает, какую запись считать правильной.</p>\n<h2>Симптом → причина → проверка → действие</h2>\n<div class=\"table-scroll\"><table><caption>Диагностика расхождений до запуска</caption><thead><tr><th scope=\"col\">Симптом</th><th scope=\"col\">Причина</th><th scope=\"col\">Проверка</th><th scope=\"col\">Действие</th></tr></thead><tbody><tr><td>Номер версии совпадает, но artifact указывает на другой commit.</td><td>Tag используют вместо точной связи с исходным revision.</td><td>Сравнить <code>artifact.sourceCommitId</code> и commit id.</td><td>Остановить выпуск. Исправить запись или пересобрать artifact после решения владельца.</td></tr><tr><td>Код можно вернуть, но схема базы уже изменилась.</td><td>Rollback binary ошибочно считают rollback данных.</td><td>Проверить migration target, compatibility и обратную процедуру.</td><td>Вернуть только явно разрешённый artifact; вопрос данных передать отдельному владельцу.</td></tr><tr><td>Rollout прошёл с тем же tag, но другим digest.</td><td>Intent ссылается на mutable label, а не на immutable content.</td><td>Сравнить requested digest с digest artifact.</td><td>Не запускать rollout. Пересоздать intent после сверки.</td></tr><tr><td>После stop команда предлагает повторить deploy.</td><td>Retry используют как замену объяснению расхождения.</td><td>Найти первую ложную связь и назвать её источник.</td><td>Сначала reconcile records, затем повторить только проверку.</td></tr></tbody></table></div>\n<p>Таблица разделяет четыре разных вопроса. Mismatch commit относится к происхождению artifact. Mismatch migration относится к совместимости contract. Mismatch digest относится к содержимому, выбранному для rollout. Повторная попытка без такой классификации стирает причину и оставляет команду без доказуемого решения.</p>\n<h2>Порядок действий перед выпуском</h2>\n<ol><li><strong>Зафиксируйте границу проверки.</strong> Укажите release version, owner и источник каждой записи. Пометьте, что сейчас выполняется review, а не deploy.</li><li><strong>Сверьте commit и artifact.</strong> Проверьте exact source commit и digest. Название ветки, последний merge и короткий tag не заменяют id.</li><li><strong>Опишите migration отдельно.</strong> Назовите target version, совместимость с текущим contract и действие по данным. Не прячьте migration в комментарии к image.</li><li><strong>Сверьте rollout intent.</strong> Он должен повторять immutable digest artifact и migration version. Любое расхождение ведёт в stop.</li><li><strong>Назовите return point.</strong> Запишите предыдущую версию и digest. Отдельно укажите, что произойдёт с данными и кто проверит этот путь.</li><li><strong>Повторите проверки после исправления.</strong> Передайте человеку только записи без ложных связей. Положительный результат открывает review, но не выдаёт автоматическое разрешение на deploy.</li></ol>\n<h2>Почему rollback не возвращает всё</h2>\n<p>Rollback Deployment обычно возвращает предыдущую ревизию Pod template. Это полезно для кода и настроек, которые входят в template. Оно не отменяет произвольный SQL, удалённую запись, заполненное поле или изменение внешнего contract. Если migration уже прошла, старый image может не уметь читать новую схему.</p>\n<p>Return point должен содержать две границы. Первая — какую версию artifact можно запустить. Вторая — что разрешено делать с данными. Возможны обратная migration, совместимый промежуточный код, восстановление из резервной копии или запрет автоматического возврата. Пока путь не проверен, честная формулировка звучит так: «возврат artifact определён; откат данных не доказан».</p>\n<p>То же различие действует для provenance и attestations. Официальная документация SLSA описывает проверку provenance через сравнение с ожиданиями пакета. GitHub описывает artifact attestations как подписанные claims о происхождении и даёт команды для проверки. Ни один из этих механизмов сам по себе не утверждает, что migration совместима, rollout одобрен или production здоров.</p>\n<h2>Ограничения и отрицательный путь</h2>\n<p>Описанный подход ловит расхождения между названными записями. Он не доказывает, что значения правдивы. Он не проверяет историю Git, содержимое image, подпись, policy CI, права на кластер, runtime configuration, состояние базы, трафик, метрики или факт доставки. Для этих вопросов нужны разрешённые источники и отдельные проверки.</p>\n<p>Если commit неизвестен, digest отсутствует, migration не имеет compatibility statement или return point не назван, результат должен быть отрицательным. Не подставляйте «последний main», не ищите image по tag и не объявляйте data rollback по факту отката Pod template. Остановитесь на первой неизвестной границе. Такое поведение медленнее одной зелёной кнопки, но дешевле расследования после повреждения данных.</p>\n<h2>Проверяемый критерий готовности</h2>\n<p>Материал готов к передаче на human review, если второй инженер без устных пояснений может показать: exact commit id, artifact digest, связь artifact с commit, migration target и compatibility, rollout digest, migration version и return point. Для каждой строки есть источник, владелец и действие при mismatch. Проверка должна дать либо все утверждения <code>true</code>, либо конкретный stop с названием ложной связи. В первом случае разрешение на deploy всё ещё принимает авторизованный процесс. Во втором случае deploy не начинается.</p>\n<p>Учебные значения в примере не являются production-результатами. Их задача — показать форму проверки и сохранить отрицательный путь. Реальную оценку готовности нужно выполнять на доступных и разрешённых записях конкретного выпуска.</p>\n<h2>Проверяемые источники</h2>\n<ul><li><a href=\"https://slsa.dev/spec/v1.0/terminology\" target=\"_blank\" rel=\"noopener noreferrer\">SLSA v1.0: Terminology and verification model</a> — объясняет provenance verification и сравнение artifact с ожиданиями пакета.</li><li><a href=\"https://docs.github.com/en/actions/how-tos/secure-your-work/use-artifact-attestations/use-artifact-attestations\" target=\"_blank\" rel=\"noopener noreferrer\">GitHub Docs: Using artifact attestations to establish provenance for builds</a> — описывает проверку attestations для binary и container image.</li><li><a href=\"https://kubernetes.io/docs/concepts/workloads/controllers/deployment/\" target=\"_blank\" rel=\"noopener noreferrer\">Kubernetes Docs: Deployments</a> — описывает rollout history и rollback Deployment revision.</li></ul>"
}