fix(ops): бэкап без выгрузки в S3 падает, а не рапортует успех #3086
Merged
lekss361
merged 1 commit from 2026-08-24 17:50:19 +00:00
fix/3085-backups-fail-loud into main
1 commit
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
1cb14c6a35 |
fix(ops): бэкап без выгрузки в S3 падает, а не рапортует успех
All checks were successful
CI Trade-In / changes (pull_request) Successful in 7s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / changes (pull_request) Successful in 8s
CI / frontend-tests (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
Проверка хостов за шесть дней до переезда показала, что на Poincare пустой crontab: ни бэкапов, ни сторожей, ни конфигов. Сегодня это неважно — базы ещё на Beget, где всё работает. Тридцатого августа они переезжают, и бэкапы там просто не начнутся. Хуже, что отказ был бы тихим. Выгрузка в S3 была опциональной: без четырёх переменных скрипт писал "backup stays local only" и выходил с кодом ноль. Не ошибка, не алерт — успешный прогон. Сторож свежести на новом хосте тоже не установлен, так что промолчали бы оба. Теперь отсутствие любой из S3_ENDPOINT / S3_BUCKET / S3_ACCESS_KEY / S3_SECRET_KEY роняет прогон с ненулевым кодом — до снятия дампа, потому что незачем тратить время и место на дамп, которому некуда уехать. Образец поведения взят из backup-forgejo.sh, где так было с самого начала. BACKUP_ALLOW_LOCAL_ONLY=1 оставляет прежний путь для машины без ключей. Ревью показало, что первая версия этой форточки возвращала ровно ту дыру, которую чинит PR: локальный прогон всё равно писал сентинел и выходил нулём, поэтому сторож свежести оставался зелёным, а единственным следом был WARNING в логе, который никто не читает. Достаточно было раскомментировать одну строку в /etc/default — и «настроено» выглядело бы неотличимо от рабочего. Теперь такой прогон сентинел НЕ пишет и сразу зовёт notify(). Попутно найден живой баг: в lib-backup.sh внутри блока после || литеральное `\n` разбиралось шеллом как команда `n`, поэтому запасной канал оповещения по почте не срабатывал никогда. То есть при недоступности Telegram мы теряли уведомления молча — тот же класс тишины. restore-drill.sh поставлен в расписание Poincare: он существовал, но не запускался нигде, и восстановимость дампов автоматически не проверялась ни разу. gzip -t и трейлер pg_dump говорят «файл не битый», а это не то же самое, что «база поднимается». У самой дрели своего сторожа нет и MAILTO в cron не задан, поэтому её падение теперь тоже уходит в notify(). Заодно docker rm -f получил -v: регулярный запуск иначе оставлял бы dangling-том размером с базу до воскресной чистки. Имя бакета в примере исправлено на gendsgn-backups — на хостах настроен именно он, forgejo пишет туда же под префиксом forgejo/. Две находки ревью намеренно не закрыты. Фолбэк на общий конфиг в tradein-скрипте остался elif: если появится /etc/default/tradein-backup без S3-переменных, прогон упадёт вместо чтения общего файла — под новой политикой это и есть желаемое поведение. Дрель проверяет только серию gendesign: restore-drill.sh не умеет батч, а расширять его в этом PR значит смешивать задачи. Хостовая часть — установка crontab и конфига на Poincare — в PR не входит. Конфиг уже положен вручную и выгрузка с Poincare проверена живым объектом; crontab ставится в окно переезда, потому что продуктового postgres там пока нет и ночные прогоны падали бы впустую. Refs #3085, #3008 |