vpnbot-xray-patches/docs/2026-08-07-release-telegram-alert-plan.md
loop-uh 01627be8fc
All checks were successful
Follow official Xray dev releases / candidate (push) Successful in 9s
Test and build VPnBot Xray patches / test-and-build (push) Successful in 2m49s
Исправить сторож выпуска Xray после переноса репозитория
2026-08-09 13:36:53 +03:00

10 KiB
Raw Permalink Blame History

Telegram-уведомления о безопасно остановившемся выпуске Xray

Задача

Автоматический выпуск уже безопасно останавливается до появления proven, если патчи не накладываются, сборка или тесты падают, candidate слишком долго не проходит пилот либо canary не подтверждает активный отзыв доступа. Сейчас это состояние видно в Forgejo Actions, systemd и root-only JSON промоутера, но оператор должен сам регулярно проверять все три места.

Нужен отдельный наблюдатель, который быстро сообщает в Telegram только о состояниях, требующих реакции:

  1. workflow автоматического candidate-выпуска завершился ошибкой или был отменён;
  2. опубликованный candidate не получил соответствующий proven дольше допустимого времени;
  3. production-canary завершился ошибкой, включая отдельную повышенную критичность, если не удался и возврат на предыдущий proven.

Сам наблюдатель не должен изменять релизы, canary, конфигурацию Xray или парк узлов. Его единственная запись во внешнюю систему — операторское сообщение в Telegram.

Источники истины

  • Структурированное состояние Forgejo Actions владеет результатом candidate.yml. Сначала наблюдатель читает публичный Actions API. Если Forgejo показывает запуски в web-интерфейсе, но API возвращает пустой workflow_runs, используется ограниченный read-only fallback: страница именно candidate.yml выбирает последний запуск main, а detail-страница отдаёт встроенный JSON state.run. Иконки и локализованный HTML-текст не считаются доказательством результата. Успешный запуск закрывает ранее зарегистрированный сбой; незавершённый запуск считается pending только до общего stall-порога, после чего становится проблемой runner.
  • Forgejo Releases API и манифест candidate владеют связью candidate -> proven. Задержка считается от published_at, а не от времени локального опроса. Уже опубликованный proven немедленно снимает задержку.
  • /var/lib/vpnbot-xray-release-promoter/*.json владеет результатом живого пилота. Фазы failed_rolled_back и failed_rollback_failed являются canary-инцидентами. Фазы повторной установки, проверки и продвижения — переходные: во время них прежнее уведомление ещё нельзя объявлять восстановленным.
  • /var/lib/vpnbot-xray-release-alert/state.json владеет только жизненным циклом операторских уведомлений: что уже отправлялось, когда была последняя попытка и когда состояние действительно восстановилось. Он не становится источником истины для самого выпуска.

Архитектура

Один root-only systemd timer раз в пять минут запускает один oneshot-процесс. Процесс берёт неблокирующую файловую блокировку, получает общий снимок Forgejo, читает локальные состояния промоутера и вычисляет три независимых условия:

  • patch_pipeline;
  • candidate_stalled;
  • canary_failed.

Для каждого условия возможны три результата:

  • problem — подтверждён новый или продолжающийся инцидент;
  • healthy — источник истины подтверждает восстановление;
  • pending — идёт новый workflow или повторный пилот, поэтому прежний инцидент пока нельзя закрывать.

waiting, queued или другой переходный статус не может оставаться безмолвным бесконечно. После общего stall-порога наблюдатель публикует операторскую проблему с идентификатором запуска и предлагает проверить регистрацию runner, его состояние online и обязательную метку linux.

У каждого инцидента есть детерминированная сигнатура: идентификатор Actions- запуска либо набор candidate-тегов и стадий. Новая сигнатура создаёт обновление аварии, та же сигнатура не порождает повторное сообщение при каждом опросе.

Доставка и дедупликация

Перед сетевой попыткой наблюдатель атомарно сохраняет её время. После подтверждённого ответа Telegram Bot API он сохраняет message_id и время успешной доставки. Это даёт следующие правила:

  • первое сообщение отправляется один раз при переходе в проблему;
  • после неоднозначной сетевой ошибки немедленного шторма повторов нет: новая попытка разрешается только после отдельного интервала повторной доставки;
  • для долгого неустранённого инцидента допускается редкое напоминание;
  • сообщение о восстановлении отправляется только после подтверждённого healthy и само повторяется безопасно, пока Telegram не подтвердит доставку;
  • смена одной неуспешной попытки выпуска другой не создаёт ложную пару «восстановлено -> снова сломано», а обновляет действующий класс инцидента.

Telegram Bot API не предоставляет ключ идемпотентности для sendMessage, поэтому абсолютно исключить дубль при редком сценарии «Telegram принял сообщение, но ответ потерялся» невозможно. Долговечное время попытки и большой интервал повтора ограничивают этот случай одним редким повтором, а обычные systemd-запуски полностью дедуплицируются.

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

  • Токен бота не копируется в новый файл. Наблюдатель читает только VPNBOT_BOT_TOKEN из существующего root-only runtime-env VPnBot.
  • Chat ID, URL API, интервалы и пути лежат в отдельном root-only /etc/vpnbot-xray-release-alert.env.
  • Состояние и lock имеют режим 0600, каталог состояния — 0700.
  • Forgejo-релизы и Actions публичного patch-репозитория читаются без write-токена промоутера.
  • systemd запрещает повышение привилегий, запись в систему и запись в домашние каталоги; разрешён только каталог состояния наблюдателя.
  • Некорректный JSON, небезопасный путь, неизвестная структура API или ошибка чтения не переводятся в «всё исправилось». Процесс завершается ошибкой, а предыдущее активное состояние остаётся сохранённым.

Проверка и выпуск

  1. Unit-тестами проверить классификацию Actions, пустой публичный API при существующем структурированном web-run, зависший runner, задержку candidate, canary-фазы, незакрытие инцидента во время retry, дедупликацию, напоминание и восстановление.
  2. Прогнать полную существующую проверку репозитория патчей и сборку поверх официального Xray.
  3. Опубликовать один commit в Forgejo и дождаться успешных ci.yml и candidate.yml.
  4. Установить service/timer на production, создать только конфигурационный env без секретов и отправить явно помеченное тестовое сообщение оператору.
  5. Запустить обычную проверку в текущем здоровом состоянии: новых аварийных сообщений быть не должно, unit должен завершиться успешно, состояние должно зафиксировать три здоровых условия.
  6. Обновить проектный навык сопровождения Xray: зафиксировать новые unit, runtime-пути, значения состояний и команды проверки.