Техническая документация

Описание

Система автоматического обновления MmoWeb Client реализует механизм безопасного развёртывания новых версий приложения через GitHub Releases API. Система поддерживает автоматическое резервное копирование, поэтапное применение изменений и отслеживание прогресса обновления в реальном времени.


Архитектура системы

Основные компоненты

  1. UpdateService (Class/Services/UpdateService.php)

    • Центральный сервис управления обновлениями

    • Отвечает за скачивание, распаковку и применение релизов

  2. Repository (Class/GitHub/Repository.php)

    • Абстракция работы с GitHub API

    • Обработка запросов к репозиторию и релизам

  3. ApiController (Controllers/ApiController.php)

    • HTTP endpoints для удалённого управления обновлениями

    • Методы: updater_check_connection, install_update, get_version, get_updater_process_progress

  4. Cache система

    • Хранилище состояния процесса обновления

    • Кеширование прогресса выполнения


Процесс обновления

1. Инициализация

Вызов API endpoint

Валидация

  • Проверка версии PHP (только 7.4.33)

  • Проверка соединения с GitHub API

  • Проверка конфигурации версии

  • Проверка отсутствия активного процесса обновления

Генерация процесса

  • Создаётся уникальный process_key (SHA256 хеш)

  • Устанавливается статус CREATED

  • Возвращается process_key клиенту

Файл: UpdateService.php:82-104


2. Создание директории процесса

Расположение: Files/update/{process_key}/

Структура директории:

Файл: UpdateService.php:106-127


3. Создание резервной копии

Параметры бекапа

  • Путь: Files/update/{process_key}/backup.zip

  • Метод: Рекурсивная архивация через ZipArchive

  • Исключения:

    • Директория Files/update/ (любые процессы обновления)

    • Архивы: .zip, .rar, .7z, .tar, .gz, .bz2, .xz, .tgz

    • Символические ссылки

    • Нечитаемые файлы

Алгоритм

  1. Сканирование всех файлов от ROOT_DIR

  2. Фильтрация по критериям исключения

  3. Добавление файлов и директорий в ZIP с сохранением структуры

  4. Проверка целостности (размер > 0 байт)

Время выполнения: зависит от размера проекта (обычно 5-30 секунд)

Файл: UpdateService.php:233-312


4. Загрузка релиза

Источник

  • URL: {release.zipball_url} из GitHub API

  • Таймаут: 2100 секунд (35 минут)

Механизм загрузки

Путь сохранения

Files/update/{process_key}/{tag}.zip

Файл: UpdateService.php:129-179


5. Анализ изменений коммита

Получение списка файлов

Система запрашивает все файлы из коммита релиза через GitHub API:

Пагинация

  • Обрабатываются все страницы (max 50)

  • Паузы между запросами: 250ms (usleep(250000))

Типы изменений файлов

  • added - новый файл

  • modified - изменённый файл

  • renamed - переименованный файл (обрабатывается как копирование)

  • removed - удалённый файл (логируется, но НЕ удаляется локально)

Файл: UpdateService.php:345-390


6. Применение изменений

Процесс обработки файлов

Метод извлечения файла

Атомарная операция:

  1. Создание временного файла {targetPath}.tmp

  2. Копирование потока из ZIP в временный файл

  3. Установка прав 0644

  4. Атомарная замена через rename()

Безопасность:

  • Автоматическое создание директорий с правами 0755

  • Откат при ошибке (удаление .tmp)

Файл: UpdateService.php:604-631


7. Завершение процесса

При успешном обновлении

  1. Статус устанавливается в COMPLETED

  2. Обновляется конфигурация version.json:

  3. Очистка кеша (если DEBUG = false):

    • update_progress_{process_key}

    • update

Файл: UpdateService.php:548-563

При ошибке

  1. Статус устанавливается в FAILED

  2. Запись в лог с полным трейсом ошибки

  3. Отправка ошибки в Global API

  4. Бекап остаётся нетронутым в Files/update/{process_key}/backup.zip

Файл: UpdateService.php:565-574


Логирование

Расположение логов

Директория: Files/logs/

Формат имени:

Пример:

Содержимое логов

Стандартная информация

  • Начало установки релиза

  • Создание директории процесса

  • Загрузка ZIP файла

  • SHA коммита релиза

  • Создание бекапа

  • Обработка каждого файла (статус и путь)

  • Прогресс обновления (% выполнения)

  • Окончание процесса

Debug информация (если DEBUG = true)

Системная информация:

Файл: UpdateService.php:633-639, 314-343

Критические ошибки

Обработчик Shutdown

Регистрируется на старте обновления и отлавливает фатальные ошибки:

  • E_ERROR

  • E_PARSE

  • E_CORE_ERROR

  • E_COMPILE_ERROR

  • E_USER_ERROR

При фатальной ошибке:

  1. Пишется в лог с префиксом FATAL ERROR:

  2. Кеш устанавливается в FAILED

  3. Уведомление отправляется в Global API

Файл: UpdateService.php:182-231


Управление состоянием

Кеширование статуса

Ключ кеша: update

Структура:

TTL: 1800 секунд (30 минут)

Файл: UpdateService.php:92-104


Кеширование прогресса

Ключ кеша: update_progress_{process_key}

Значение: Float (0.00 - 100.00)

TTL: 600 секунд (10 минут)

Обновление: При обработке каждого файла

Пример файла: cache/update_progress_{hash}.txt

Файл: UpdateService.php:532-533


API Endpoints

1. Проверка соединения

Endpoint: POST /api/updater_check_connection

Проверки:

  • Валидность конфигурации версии

  • PHP = 7.4.33

  • Соединение с GitHub API

Ответы:

Файл: ApiController.php:432-475


2. Установка обновления

Endpoint: POST /api/install_update

Параметры:

  • tag (required) - тег релиза (например, v1.2.3)

  • process_key (optional) - ключ процесса при продолжении

Двухэтапный процесс:

Этап 1: Создание процесса

Ответ:

Этап 2: Выполнение обновления

Ответ при успехе:

Ответ при ошибке:

Файл: ApiController.php:477-572


3. Получить текущую версию

Endpoint: POST /api/get_version

Ответ:

Файл: ApiController.php:574-590


4. Получить прогресс обновления

Endpoint: GET /api/get_updater_process_progress?process_key={key}

Ответ:

Файл: ApiController.php:592-630


Обработка ошибок и recovery

Типовые ошибки

1. Обновление уже запущено

Статус: 423 Locked

Решение: Дождаться завершения текущего процесса или проверить статус в кеше


2. Тег уже установлен

Exception: The specified tag is already installed.

Решение: Проверить текущую версию через /api/get_version


3. Проблемы с GitHub API

Возможные причины:

  • Неверный токен авторизации

  • Rate limiting

  • Таймаут соединения

  • Несуществующий релиз/тег

Диагностика:

  • Проверить логи Debug/github.log

  • Проверить конфигурацию Library/configs/github.json

  • Тест соединения: /api/updater_check_connection

Файл: Repository.php:53-115


4. Ошибка создания бекапа

Возможные причины:

  • Недостаточно места на диске

  • Нет прав на запись в Files/update/

  • Исчерпана память PHP (memory_limit)

Решение:

  1. Проверить свободное место: df -h

  2. Проверить права: ls -la Files/

  3. Увеличить memory_limit в php.ini (по умолчанию устанавливается 256M)

Файл: UpdateService.php:233-312


5. Битый ZIP файл

Exception: Failed to open ZIP file... The file may be corrupted.

Решение:

  1. Проверить файл вручную: unzip -t Files/update/{process_key}/{tag}.zip

  2. Удалить процесс и повторить обновление

  3. Проверить стабильность сетевого соединения

Файл: UpdateService.php:449-451


6. ZIP Slip атака

Exception: ZIP Slip detected: invalid path: ...

Причина: Попытка записи файла за пределы ROOT_DIR

Защита: Проверка на наличие .. или абсолютных путей в именах файлов

Файл: UpdateService.php:492-497


Восстановление из бекапа

Автоматическое восстановление

При ошибке процесс останавливается, но откат не производится автоматически.

Ручное восстановление

  1. Найти директорию последнего обновления:

  2. Проверить наличие бекапа:

  3. Распаковать бекап:

  4. Проверить права доступа:

  5. Очистить кеш обновления:


Безопасность

Аутентификация API (клиентская часть)

Все API endpoints используют HMAC-SHA256 подпись:

Константа: API_KEY из Config.php

Файл: ApiController.php:14-44


Защита от атак

1. ZIP Slip Protection

Проверка всех путей файлов на наличие:

  • .. (выход за пределы директории)

  • Абсолютных путей (/, \, C:)

2. Игнорирование пользовательского прерывания

3. Ограничения выполнения

  • Таймаут: 1800 секунд (30 минут)

  • Память: 256MB

  • Umask: 0022 (права по умолчанию)

Файл: UpdateService.php:395-400


Конфигурация GitHub

Файл: Library/configs/github.json

Файл: Repository.php:21-36


Производительность

Таймауты

Операция
Таймаут
Конфигурация

Процесс обновления

1800 сек (30 мин)

PROCESS_EXECUTE_TIMEOUT

Загрузка ZIP с GitHub

2100 сек (35 мин)

CURLOPT_TIMEOUT

GitHub API запрос

15 сек

Repository->timeout

Пауза между запросами коммитов

250 мс

usleep(250000)


Оптимизация

1. Прогресс-репортинг с дебаунсом

Отправка прогресса в Global API происходит не чаще 1 раза в 3 секунды:

Файл: UpdateService.php:536-539


2. Потоковая обработка файлов

Использование stream_copy_to_stream() вместо загрузки в память:

Файл: UpdateService.php:607-617


Мониторинг

Проверка статуса обновления


Проверка логов


Конфигурационные файлы

version.json

Расположение: Library/configs/version.json


github.json

Расположение: Library/configs/github.json


Troubleshooting

Проблема: Обновление зависло

Диагностика:

  1. Проверить статус процесса:

  2. Проверить PHP процессы:

  3. Проверить последний лог:

Решение:

  • Если процесс завис > 30 минут - очистить кеш вручную

  • Проверить доступность GitHub API

  • Повторить обновление


Проблема: Недостаточно прав доступа

Симптомы:

Решение:


Проблема: GitHub API rate limit

Симптомы:

Решение:

  • Authenticated requests: 5000 req/hour

  • Unauthenticated: 60 req/hour


Рекомендации для специалистов

Pre-deployment checklist


Post-deployment checklist

Last updated