Перейти к основному содержимому

Сторож деплойных блокировок (Deploy Locks)

Если видишь Refusing S3 deploy: при попытке деплоя — ты здесь.

Какие сторожа входят

СторожЧто охраняет
Host Deploy Lock (FD8)Только один деплой на хосте одновременно
Codebase Deploy Lock (FD9)Деплой запущен через официальную обёртку
Hidden Git Index CheckНа checkout нет skip-worktree / assume-unchanged
Busy-Process ScanНи один процесс не запущен из заменяемого checkout
ProductSpec Registry CountКоличество ProductSpec-файлов совпадает с реестром

Host Deploy Lock (FD8)

Где

scripts/deploy/verify_inherited_host_deploy_lock.py

Что охраняет

Файл /run/lock/gwptd-next-deploy.lock (EXCLUSIVE). Гарантирует что только ОДИН деплой на всём хосте. Защита от случайного параллельного запуска двух деплой-обёрток.

Как работает

  1. Обёртка gwptd-next-deploy открывает /run/lock/gwptd-next-deploy.lock на FD8 с EXCLUSIVE lock
  2. Экспортирует GWPTD_NEXT_DEPLOY_HOST_LOCK_PROTOCOL, GWPTD_NEXT_DEPLOY_HOST_LOCK_FD=8, GWPTD_NEXT_DEPLOY_HOST_LOCK_PATH
  3. Внутренний deploy запускает verify_inherited_host_deploy_lock.py
  4. Python проверяет:
    • Протокол верный
    • FD = 8
    • Путь фиксированный
    • Inode совпадает
    • Блокировка удерживается (независимый probe + перезахват)

Как отказывает

Refusing S3 deploy: host deploy lock protocol is absent or incompatible
Refusing S3 deploy: host deploy lock descriptor must be FD8
Refusing S3 deploy: host deploy lock path is not the fixed /run inode
Refusing S3 deploy: host deploy descriptor does not reference the fixed lock inode
Refusing S3 deploy: host deploy lock parent must be a real directory

Codebase Deploy Lock (FD9)

Где

scripts/deploy/verify_inherited_deploy_lock.py

Что охраняет

Файл /opt/mcp-gwptd/logs/codebase-reindex.lock на FD9 (EXCLUSIVE). Доказывает что деплой запущен через gwptd-next-deploy, а не через ручной bash deploy-s3-next.sh.

Как работает

  1. gwptd-next-deploy открывает codebase-reindex.lock на FD9 с EX
  2. Экспортирует GWPTD_NEXT_DEPLOY_LOCK_PROTOCOL, GWPTD_NEXT_DEPLOY_LOCK_FD=9
  3. Python проверяет:
    • Иерархию путей (MCP root root:root 0755, logs root:gwptd 1770, lock root:gwptd 0660)
    • Inode совпадает
    • Блокировка УЖЕ удерживается (probe сначала)
    • После перезахвата — всё ещё удерживается (probe после)

Обрати внимание: проверка делает TRIPLE probe. Это защита от гонки:

  • Probe 1: блокировка уже есть (никто не передал разблокированный FD)
  • Re-lock FD9: доказывает что именно FD9 владеет блокировкой
  • Probe 3: блокировка всё ещё есть (re-lock не сломал)

Как отказывает

Refusing S3 deploy: inherited an unsupported lock protocol
Refusing S3 deploy: inherited an invalid lock descriptor
Refusing S3 deploy: inherited an unexpected lock descriptor
Refusing S3 deploy: inherited the wrong codebase lock inode
Refusing S3 deploy: lock was not held exclusive before inner execution
Refusing S3 deploy: inherited descriptor does not own the exclusive lock

Hidden Git Index Check

Где

ops/bin/gwptd-next-deploy

Что охраняет

На S3 checkout нет файлов, помеченных git update-index --skip-worktree или --assume-unchanged. Эти флаги скрывают изменения от git status и могут привести к деплою с непреднамеренными локальными правками.

Как отказывает

Refusing deploy: hidden Git index flags on S3 checkout:
<список файлов>

Exit code 9.

Что делать

  1. Посмотреть список файлов в сообщении
  2. Снять флаги:
    git update-index --no-skip-worktree <file>
    git update-index --no-assume-unchanged <file>
  3. Проверить что git status --porcelain чист

Busy-Process Scan

Где

deploy/s3/gwptd-deploy-app

Что охраняет

При деплое только app/API (без cron quarantine) проверяется что ни один процесс не запущен из checkout, который заменяется. Ищет по /proc/*/cwd и /proc/*/exe.

Как отказывает

Отказ: из этого checkout работает процесс $pid ($cwd) — подмена кода его сломает

Exit code 10.

ProductSpec Registry Count

Где

scripts/deploy/deploy-s3-next.sh (внутренний deploy)

Что охраняет

Количество YAML-файлов ProductSpec совпадает с количеством записей в реестре. Защита от: добавили spec, забыли реестр → endpoint молча не собирается.

Как отказывает

Refusing deploy: ProductSpec file/registry counts differ

Exit code 8.