11 KiB
Автодеплой через Drone
Drone: https://drone.smartsoltech.kr, цель: trevor@192.168.40.112:/opt/new_lottery_bot, репозиторий trevor/new_lottery_bot, production-ветка master.
Подготовленный pipeline запускает деплой только для успешного push в master после проверок, PostgreSQL-тестов и сборки архива. Pull request запускает проверки без передачи deployment-секретов.
Секреты репозитория
| Имя в Drone | Значение |
|---|---|
lottery_deploy_user |
SSH-пользователь сервера с доступом к Docker и каталогу приложения |
lottery_deploy_path |
Отдельный абсолютный каталог, например /opt/new_lottery_bot |
lottery_deploy_ssh_key |
Закрытый SSH-ключ этого пользователя, пригодный для неинтерактивного входа |
lottery_deploy_known_hosts |
Проверенная запись ключа сервера для 192.168.40.112 |
lottery_env |
Полный актуальный production env-файл с BOT_TOKEN, DATABASE_URL, ADMIN_IDS и остальными настройками |
Настройка использует официальный API создания и обновления секретов. Скрипт передаёт pull_request=false, повторно проверяет наличие имён и не печатает значения. Учётной записи нужны права записи в репозиторий.
На Windows, из корня проекта, после заполнения файлов за пределами репозитория:
.\.venv\Scripts\python.exe scripts/configure_drone_secrets.py `
--server https://drone.smartsoltech.kr `
--repo trevor/new_lottery_bot `
--token-file C:\secure\drone-token.txt `
--ssh-key C:\secure\lottery-deploy-key `
--known-hosts C:\secure\lottery-known-hosts `
--env-file C:\secure\lottery-production.env `
--deploy-user trevor `
--deploy-path /opt/new_lottery_bot
Пути C:\secure\... — примеры файлов с ограниченными правами доступа. Токены не нужно вставлять в командную строку. Отпечаток host key сверяется через доверенный доступ к серверу; автоматическое принятие неизвестного ключа отключено. Для Drone используется отдельный ключ id_ed25519_lottery_deploy; пользователь trevor имеет доступ к Docker и каталогу приложения.
При подготовке deployment актуальные настройки взяты из работающего контейнера: PostgreSQL 16 расположен на 192.168.20.2, база lottery_bot. Локальный старый .env.prod не является источником production-настроек. Проверено совпадение эффективных BOT_TOKEN, DATABASE_URL, REDIS_URL, ADMIN_IDS и имён volumes с действующим Compose-проектом new_lottery_bot. Все пять секретов созданы в Drone с запретом передачи pull request.
Резервная копия рабочей БД восстановлена в изолированном PostgreSQL 16; обновление с 20260701_perf_indexes до 20260913_staff_concurrency и проверка схемы прошли. При обновлении PostgreSQL согласованно обновлять клиент резервного копирования: PostgreSQL не гарантирует восстановление дампа нового клиента в более старую major-версию сервера.
Перед первым деплоем
- Активировать репозиторий в Drone. Runner должен получать Git-репозиторий и обращаться по SSH к
192.168.40.112; сервер должен иметь доступ к registry/PyPI для сборки. - На сервере нужны Docker Engine, Compose v2 с поддержкой
--wait,flock,tar,install. Пользователь должен иметь доступ к Docker и выделенному каталогу. Подготовить ключ и проверить обычный неинтерактивный SSH-вход. - Если уже существует контейнер
lottery_bot, проверить его labelcom.docker.compose.project. Скрипт ожидаетnew_lottery_botи остановится при другом проекте, чтобы не подменить чужой стек. Существующие volumes, каталог и внешний PostgreSQL необходимо сопоставить до переноса. Не запускатьdown -v. - В
.env.prodиспользовать реальные настройки из.env.prod.example. Для внешней БД оставитьCOMPOSE_PROFILESпустым и указать доступный из контейнера PostgreSQL вDATABASE_URL; POSTGRES_PASSWORD не требуется. Для БД в этом Compose задатьCOMPOSE_PROFILES=local-db, непустой POSTGRES_PASSWORD, согласованные POSTGRES_* и адресpostgresв URL. Спецсимволы пароля внутри URL должны быть URL-encoded. Клиент резервного копирования и PostgreSQL в Compose/CI используют major-версию 16, соответствующую рабочей БД. - При использовании переменных со знаком
$учитывать интерполяцию Compose env-файла; заключать соответствующее значение в одинарные кавычки. Проверять конфигурацию командойdocker compose --project-name new_lottery_bot --env-file .env.prod config --quiet, чтобы значения секретов не попадали в вывод. - Проверить доступ к целевой БД и возможность
pg_dump. БД должна уже существовать. Пользователю миграций нужны права изменения принадлежащих приложению объектов. Исторические дубликаты миграция сообщает без удаления данных. - Загрузить пять секретов указанным скриптом, опубликовать изменения в
masterи дождаться завершения всего pipeline, включаяdeploy.
Последовательность deployment-скрипта
- Получает архив и env-файл по SSH с обязательной проверкой host key.
- Берёт файловую блокировку деплоя и отклоняет устаревший номер сборки.
- Создаёт каталог
releases/COMMIT-BUILD, собирает образ с тегом commit и поднимает Redis/необходимую локальную БД. - Делает PostgreSQL backup в
backups/COMMIT-BUILD-UTC_TIMESTAMP.dumpс ограниченными правами. Дальнейшие действия прекращаются, если backup не получен. - Останавливает старого polling-бота, выполняет
alembic upgrade headи проверку схемы. - Запускает новый образ, ожидает healthcheck, затем ещё 120 секунд проверяет heartbeat и отсутствие перезапусков. Только после этого переключает
currentи записываетlast-build. - При ошибке после остановки пытается вернуть прежний образ. Это откат приложения: схема БД автоматически не откатывается; используется env текущего deployment. Восстановление БД из backup требует отдельного решения. При первом запуске предыдущего образа может не быть.
Heartbeat обновляется после проверки БД в работающем event loop; до запуска бот проверяет Redis, схему и Telegram getMe. Отдельный watchdog-поток завершает процесс при устаревшем heartbeat, даже если завис драйвер или event loop; после этого действует Docker restart policy. На рабочем сетевом маршруте длительное повторное использование соединений зависало: в lottery_env установлен DB_POOL_RECYCLE=15, сохраняющий ограниченный пул с коротким сроком жизни соединения. Один только начальный Docker healthcheck не является проверкой длительной работы или доставки всех сообщений.
Проверка результата
После успешного шага deploy проверить /start, админку, /cashier со второго Telegram-аккаунта, добавление участника и тестовый розыгрыш. В логах должны отсутствовать ошибки миграций, Conflict: terminated by other getUpdates request и повторяющиеся ошибки соединения с БД. Проверить сохранение FSM после штатного рестарта, содержимое backup и возможность восстановления на отдельной тестовой БД.
Локальные команды CI:
.\.venv\Scripts\python.exe -m pip install -r requirements-dev.txt
.\.venv\Scripts\python.exe -m ruff check src main.py scripts tests migrations
.\.venv\Scripts\python.exe -m pytest -q
.\.venv\Scripts\python.exe -m pip_audit -r requirements.txt
.\.venv\Scripts\python.exe scripts/check_secrets.py
.\.venv\Scripts\python.exe scripts/build_release.py
Для PostgreSQL-тестов задаётся TEST_DATABASE_URL только отдельной одноразовой тестовой БД: тесты удаляют и создают в ней таблицы. Пользователю тестов также требуется CREATEDB для проверки миграций. Рабочий DATABASE_URL тестами не используется: tests/conftest.py подставляет временную SQLite БД, если TEST_DATABASE_URL не указан.