Деплой ПТИЦЫ проверяет только backend /health — мёртвый frontend или crash-loop worker/beat уезжают зелёным деплоем #3324

Closed
opened 2026-09-02 06:57:51 +00:00 by bot-backend · 2 comments
Collaborator

Армейский аудит 01-02.09, линза devops; подтверждено скептиком сличением двух workflow.

Факт

deploy.yml:1027-1038 — единственный гейт: curl backend /health. При этом:

  • у worker/beat нет compose-healthcheck вовсе — crash-loop уезжает зелёным;
  • у frontend только TCP-проба, которую деплой не читает;
  • ни одного up -d --wait.

Для контраста: deploy-tradein.yml:1246-1392 проверяет backend, browser и сверяет образы — рассинхрон дисциплин в одном репозитории. Правильный образец лежит в соседнем файле (паттерн «правильный образец рядом с дефектом»).

Лечение

Перенести из деплоя МЕРЫ: healthcheck-и worker/beat (celery inspect ping), чтение фронтовой пробы, сверка образа scraper-паттерном.

Приёмка

  • Убитый вручную worker до деплоя → деплой красный (проверка на слом, не на зелёное)
  • Мёртвый frontend → красный
  • Обычный деплой не замедлился больше чем на ~1 мин

Периметр (low, сюда же)

Три подтверждённых мелочи одной темы «что видит аноним»:

  1. JS-чанки закрытого контура скачиваются с meraocenka.ru (webpack-карта публикует lazy-чанки GuardedRoute/useMe/support; dynamic() мешает загрузке, не раздаче) — disclosure имён ручек, apps.caddy:466;
  2. 401-оракул: мусорный путь /trade-in/api/public/* → 401 c текстом rbac, остальное 404 — выключенная ручка отличима от несуществующей (rbac.py exact-match _PUBLIC_PATHS);
  3. gendsgn.ru: Caddy инжектит TRADEIN_INTERNAL_AUTH_SECRET в каждый анонимный /trade-in/api/* (apps.caddy:189), где он мёртвый груз — блок meraocenka тот же секрет сознательно не ставит. Убрать инжект из анонимного пути.
Армейский аудит 01-02.09, линза devops; подтверждено скептиком сличением двух workflow. ## Факт `deploy.yml:1027-1038` — единственный гейт: `curl backend /health`. При этом: - у worker/beat нет compose-healthcheck вовсе — crash-loop уезжает зелёным; - у frontend только TCP-проба, которую деплой не читает; - ни одного `up -d --wait`. Для контраста: `deploy-tradein.yml:1246-1392` проверяет backend, browser и сверяет образы — рассинхрон дисциплин в одном репозитории. Правильный образец лежит в соседнем файле (паттерн «правильный образец рядом с дефектом»). ## Лечение Перенести из деплоя МЕРЫ: healthcheck-и worker/beat (celery inspect ping), чтение фронтовой пробы, сверка образа scraper-паттерном. ## Приёмка - [ ] Убитый вручную worker до деплоя → деплой красный (проверка на слом, не на зелёное) - [ ] Мёртвый frontend → красный - [ ] Обычный деплой не замедлился больше чем на ~1 мин ## Периметр (low, сюда же) Три подтверждённых мелочи одной темы «что видит аноним»: 1. JS-чанки закрытого контура скачиваются с meraocenka.ru (webpack-карта публикует lazy-чанки GuardedRoute/useMe/support; dynamic() мешает загрузке, не раздаче) — disclosure имён ручек, apps.caddy:466; 2. 401-оракул: мусорный путь `/trade-in/api/public/*` → 401 c текстом rbac, остальное 404 — выключенная ручка отличима от несуществующей (rbac.py exact-match _PUBLIC_PATHS); 3. gendsgn.ru: Caddy инжектит TRADEIN_INTERNAL_AUTH_SECRET в каждый анонимный `/trade-in/api/*` (apps.caddy:189), где он мёртвый груз — блок meraocenka тот же секрет сознательно не ставит. Убрать инжект из анонимного пути.
Author
Collaborator

Часть «гейт деплоя» готова и прод-верифицирована в обе стороны (PR #3334, merged 02.09):

Зелёная сторона — деплой самого PR прошёл через новый гейт (run 9861, job deploy): backend/worker/beat/frontend healthy, frontend отвечает HTTP 200, все четыре сверки «образ→контейнер» на свежих sha, финальная строка Гейт деплоя (#3324): health_rc=0 frontend_rc=0 image_rc=0 → rc=0.

Красная сторона — контролируемый слом детектора на проде (полный красный деплой невозможен без реально сломанного кода: dispatch-деплой пересоздаёт контейнеры и лечит любую предварительную диверсию — гейт по построению проверяет пост-деплойное состояние): mv celery → celery.bak в живом worker → ровно после 5 провалов (FailingStreak: 5, как настроено retries) контейнер unhealthy, в Health.Log настоящий диагноз /bin/sh: 1: celery: not found (stderr виден — 2>&1 снят по ревью). Гейт читает ровно этот inspect. Восстановление mv обратно → healthy streak=0 через один интервал. Активных задач в момент эксперимента не было (проверено inspect active = 0).

До мержа все три пробы прогнаны на живом проде: worker pong rc=0, beat rc=0 (файл расписания в /tmp, свежий), фронт HTTP 200, /usr/bin/hostname в контейнере есть.

Issue остаётся открытым — периметр-трио (JS-чанки закрытого контура на meraocenka, 401-оракул /trade-in/api/public/*, мёртвый TRADEIN_INTERNAL_AUTH_SECRET в анонимном пути Caddy) пойдёт отдельным заходом после мержа #3331, чтобы не конфликтовать в rbac.py.

Часть «гейт деплоя» готова и прод-верифицирована в обе стороны (PR #3334, merged 02.09): **Зелёная сторона** — деплой самого PR прошёл через новый гейт (run 9861, job deploy): `backend/worker/beat/frontend healthy`, `frontend отвечает HTTP 200`, все четыре сверки «образ→контейнер» на свежих sha, финальная строка `Гейт деплоя (#3324): health_rc=0 frontend_rc=0 image_rc=0 → rc=0`. **Красная сторона** — контролируемый слом детектора на проде (полный красный деплой невозможен без реально сломанного кода: dispatch-деплой пересоздаёт контейнеры и лечит любую предварительную диверсию — гейт по построению проверяет пост-деплойное состояние): `mv celery → celery.bak` в живом worker → ровно после 5 провалов (`FailingStreak: 5`, как настроено retries) контейнер `unhealthy`, в `Health.Log` настоящий диагноз `/bin/sh: 1: celery: not found` (stderr виден — `2>&1` снят по ревью). Гейт читает ровно этот inspect. Восстановление `mv` обратно → `healthy streak=0` через один интервал. Активных задач в момент эксперимента не было (проверено inspect active = 0). До мержа все три пробы прогнаны на живом проде: worker `pong` rc=0, beat rc=0 (файл расписания в /tmp, свежий), фронт HTTP 200, `/usr/bin/hostname` в контейнере есть. **Issue остаётся открытым** — периметр-трио (JS-чанки закрытого контура на meraocenka, 401-оракул `/trade-in/api/public/*`, мёртвый TRADEIN_INTERNAL_AUTH_SECRET в анонимном пути Caddy) пойдёт отдельным заходом после мержа #3331, чтобы не конфликтовать в rbac.py.
Author
Collaborator

Периметр-трио закрыто (05.09, прод-верифицировано):

  • п.1 JS-чанки — PR #3340: на meraocenka чанки закрытых маршрутов 404/0 (Caddy), на gendsgn тот же путь 404/9 (Next, B2B не задет); ограничение честное — убран код, не имена (webpack-карта нужна лендингу).
  • п.2 401-оракул — PR #3352, приёмка изнутри контейнера после деплоя e48b4a4: /api/public/zzz → 404, /api/v1/zzz → 404, /api/v1/me → 401, /api/v1/me/ → 404 (redirect_slashes выключен, 307-канал закрыт), /api/v1/admin/zzz → 404. Честная оговорка в докстринге: обменяли префиксный оракул на оракул существования маршрута; admin-префикс снаружи доходит до guard'а → #3360.
  • п.3 мёртвый секрет — PR #3340: caddy adapt | grep -c Internal-Auth-Secret → 0, лог бэкенда без новых «без валидного X-Internal-Auth-Secret».

Гейт деплоя ПТИЦЫ (PR #3334) принят ранее в обе стороны. Issue можно закрывать; остаток — #3360 (срез admin-префикса на периметре, security).

Периметр-трио закрыто (05.09, прод-верифицировано): - **п.1 JS-чанки** — PR #3340: на meraocenka чанки закрытых маршрутов `404/0` (Caddy), на gendsgn тот же путь `404/9` (Next, B2B не задет); ограничение честное — убран код, не имена (webpack-карта нужна лендингу). - **п.2 401-оракул** — PR #3352, приёмка изнутри контейнера после деплоя e48b4a4: `/api/public/zzz → 404`, `/api/v1/zzz → 404`, `/api/v1/me → 401`, `/api/v1/me/ → 404` (redirect_slashes выключен, 307-канал закрыт), `/api/v1/admin/zzz → 404`. Честная оговорка в докстринге: обменяли префиксный оракул на оракул существования маршрута; admin-префикс снаружи доходит до guard'а → #3360. - **п.3 мёртвый секрет** — PR #3340: `caddy adapt | grep -c Internal-Auth-Secret → 0`, лог бэкенда без новых «без валидного X-Internal-Auth-Secret». Гейт деплоя ПТИЦЫ (PR #3334) принят ранее в обе стороны. Issue можно закрывать; остаток — #3360 (срез admin-префикса на периметре, security).
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#3324
No description provided.