3.5 KiB
Design: Инкрементальный SFTP-деплой
Подход
Модифицируем единственный файл tools/deploy_sftp.py:
-
Сравнение файлов (size + mtime):
- Для каждого локального файла вызываем
sftp.stat(remote_path). - Если stat успешен И
(st_size, int(st_mtime))совпадает с локальным(os.stat(lpath).st_size, int(os.stat(lpath).st_mtime))— пропускаем (не льём). - Если stat бросает IOError (нет файла) или не совпадает — заливаем.
- Метрику печатаем:
= пропущено, + залито.
- Для каждого локального файла вызываем
-
Таймауты против зависания:
paramiko.Transportсоздаём сbanner_timeout=30,timeout=30.- Для каждого
putиспользуемparamikoокно: оборачиваем вsocket.setdefaulttimeout(120)(SFTP-канал унаследует) — если операция длится дольше 2 мин, канал падает с ошибкой, скрипт падает с понятным сообщением вместо бесконечного висения. - Удаление тоже не должно висеть: те же таймауты.
-
Что НЕ меняется:
- Mirror-логика (всё, чего нет локально, удаляется) — сохранена.
- Рекурсивное создание каталогов — сохранено.
- Интерфейс:
tools/deploy_sftp.py [--dry-run], переменные DEDINIT_* / SSHPASS. - Вызов из
.gitea/workflows/deploy.ymlне меняется.
Риски
-
mtime на сервере (Jino) может отличаться от локального (часовой пояс, точность). SFTP stat возвращает mtime в секундах; локально
int(st_mtime)— тоже секунды. Допуск: считаем «не изменился», если|remote_mtime - local_mtime| <= 120И размеры равны. (Больше 2 мин расхождения не бывает при честном сравнении; зато гарантируем, что файл, записанный «только что» локально и залитый минуту назад, не перельётся без нужды.) Решение: допуск на mtime = 300 сек (5 мин) при равенстве размеров. -
Ложные пропуски: если сервер отдаёт mtime 0 (некоторые SFTP-сервера) — считаем файл изменённым (льём всегда). Проверка
if remote_mtime > 0. -
Большой дерево: rlist рекурсивно обходит всё дерево — оставляем как есть (работает, это доли секунды на 500 файлов).
Верификация
python3 tools/deploy_sftp.py --dry-runлокально: показывает список изменившихся (должно быть 0 после сборки в тот же public/... фактически покажет все «+», т.к. на сервере старый mtime — это ок, первый деплой льёт всё).- После первого инкрементального деплоя повторный
--dry-runпокажет «=» (пропуски).