[needs-human][devops] deploy-очередь: контейнер отстаёт от :latest при серии быстрых мержей + SENTRY_RELEASE-флаг врёт о готовности #2462

Open
opened 2026-07-05 20:15:49 +00:00 by bot-backend · 0 comments
Collaborator

Инцидент (2026-07-05, при отгрузке аудита #2445)

При мерже волны из 3-4 backend-PR за ~1 минуту (типично для мульти-агентного конвейера) обнаружены два связанных deploy-изъяна:

1. Работающий контейнер отстаёт от :latest образа на десятки минут

deploy.yml имеет concurrency: cancel-in-progress: false → deploy-раны строго последовательны (в очередь). Каждый merge = отдельный ран (build → push :latest → compose pull → up -d). При серии быстрых мержей очередь растягивается: :latest образ уже пересобран из свежего main, но работающий контейнер ещё на промежуточном образе предыдущего рана. Наблюдалось расхождение ~40+ минут (B1-фикс geometry был в :latest, но контейнер держал старый код без него).

Симптом: фикс прошёл ревью+CI+merge, но на проде его нет — потому что контейнер не дошёл до соответствующего deploy-рана в очереди.

2. SENTRY_RELEASE env-переменная — ложный индикатор готовности

deploy.yml ставит SENTRY_RELEASE=$IMAGE_TAG через sed в backend/.env.runtime до compose up -d. Контейнер подхватывает её при рестарте — независимо от того, пересобрался ли Docker-образ с новым кодом. Проверка «задеплоилось ли» по SENTRY_RELEASE даёт ложный «зелёный»: env показывает целевой SHA, а код в образе старый.

Impact

Автономный конвейер (и человек) может ошибочно считать фикс задеплоенным. Прод-верификация по env-флагу ненадёжна. При частых мержах фиксы «зависают» в очереди без явного сигнала.

Варианты (на решение)

  1. cancel-in-progress: true для deploy (+ гарантировать, что финальный ран катит финальный main) — схлопнёт очередь, но оборвёт промежуточные build'ы (для последовательных backend-мержей это ОК, т.к. финальный main = надмножество).
  2. Верифицировать по git-SHA образа, а не env: печатать реальный build-SHA внутрь образа (LABEL/файл /app/GIT_SHA) и сравнивать docker inspect/exec cat с ожидаемым. Убрать SENTRY_RELEASE из роли индикатора.
  3. Deploy-gate: последний шаг deploy.yml проверяет, что запущенный контейнер реально на новом образе (health + code-marker), иначе fail — чтобы «зелёный deploy» означал «код на проде».
  4. Комбинация: (1) для скорости + (2)/(3) для честной верификации.

Обход (применялся в этой сессии)

Прод-верификация по коду в работающем контейнере (docker exec grep <маркер>) или живому вызову, НЕ по SENTRY_RELEASE. Зафиксировано в моей памяти (deploy-verify-image-not-envflag).

Refs #2445

## Инцидент (2026-07-05, при отгрузке аудита #2445) При мерже волны из 3-4 backend-PR за ~1 минуту (типично для мульти-агентного конвейера) обнаружены два связанных deploy-изъяна: ### 1. Работающий контейнер отстаёт от `:latest` образа на десятки минут `deploy.yml` имеет `concurrency: cancel-in-progress: false` → deploy-раны строго последовательны (в очередь). Каждый merge = отдельный ран (build → push `:latest` → compose pull → up -d). При серии быстрых мержей очередь растягивается: `:latest` образ уже пересобран из свежего main, но **работающий контейнер ещё на промежуточном образе** предыдущего рана. Наблюдалось расхождение ~40+ минут (B1-фикс geometry был в `:latest`, но контейнер держал старый код без него). **Симптом:** фикс прошёл ревью+CI+merge, но на проде его нет — потому что контейнер не дошёл до соответствующего deploy-рана в очереди. ### 2. `SENTRY_RELEASE` env-переменная — ложный индикатор готовности `deploy.yml` ставит `SENTRY_RELEASE=$IMAGE_TAG` через `sed` в `backend/.env.runtime` **до** `compose up -d`. Контейнер подхватывает её при рестарте — **независимо от того, пересобрался ли Docker-образ с новым кодом**. Проверка «задеплоилось ли» по `SENTRY_RELEASE` даёт ложный «зелёный»: env показывает целевой SHA, а код в образе старый. ## Impact Автономный конвейер (и человек) может ошибочно считать фикс задеплоенным. Прод-верификация по env-флагу ненадёжна. При частых мержах фиксы «зависают» в очереди без явного сигнала. ## Варианты (на решение) 1. **cancel-in-progress: true для deploy** (+ гарантировать, что финальный ран катит финальный main) — схлопнёт очередь, но оборвёт промежуточные build'ы (для последовательных backend-мержей это ОК, т.к. финальный main = надмножество). 2. **Верифицировать по git-SHA образа, а не env**: печатать реальный build-SHA внутрь образа (`LABEL`/файл `/app/GIT_SHA`) и сравнивать `docker inspect`/`exec cat` с ожидаемым. Убрать `SENTRY_RELEASE` из роли индикатора. 3. **Deploy-gate**: последний шаг deploy.yml проверяет, что запущенный контейнер реально на новом образе (health + code-marker), иначе fail — чтобы «зелёный deploy» означал «код на проде». 4. Комбинация: (1) для скорости + (2)/(3) для честной верификации. ## Обход (применялся в этой сессии) Прод-верификация по **коду в работающем контейнере** (`docker exec grep <маркер>`) или **живому вызову**, НЕ по `SENTRY_RELEASE`. Зафиксировано в моей памяти (`deploy-verify-image-not-envflag`). Refs #2445
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#2462
No description provided.