9.0 KiB
Раннбук: автосинк и деплой кабинета
Как устроено скрытие блока «Дополнительные опции» на странице Подписки и вся автоматика вокруг него: приватный форк, ежедневный синк с апстримом, сборка статики и выкладка на VPS.
Репозиторий: chillpadclub/bedolaga-cabinet (приватный форк
BEDOLAGA-DEV/bedolaga-cabinet).
Суть задачи
На странице Подписка нужно было скрыть блок «Дополнительные опции» (докупка
устройств, трафика, управление серверами), не потеряв возможность и дальше
получать обновления апстрима — проект активно развивается, жить на статичном
форке было бы риском самим по себе.
Решение: приватный форк со своим патчем поверх + GitHub Action, который каждый день сам подтягивает апстрим, накатывает патч и собирает готовую статику для VPS.
Патч: как спрятан блок
Файл — src/pages/Subscription.tsx. Условие рендера обёрнуто в false &&, но
не правкой существующей строки, а обёрткой снаружи — так, чтобы ни одна
оригинальная строка апстрима не менялась, только добавлены две строки до и две
после:
{/* Additional Options — disabled on purpose */}
{false && (
<>
{subscription && // ← строка апстрима не тронута
(subscription.is_active || subscription.is_limited) &&
...
<div>...</div>
)}
</>
)}
Благодаря этому будущий git merge с апстримом конфликтует, только если
апстрим правит саму первую или последнюю строку блока — а не любую строку
внутри (докупка устройств, трафика и т.д.), которую вы всё равно не
используете.
Компоненты DeviceTopupSheet, DeviceReductionSheet, TrafficTopupSheet,
ServerManagementSheet остаются в коде и в сборке — просто не рендерятся. Это
осознанный выбор в пользу простоты патча, а не баг.
Как работает автоматика
Один workflow — .github/workflows/sync-and-build.yml. Запускается по
расписанию (ежедневно, 06:00 UTC) и вручную кнопкой Run workflow.
- Merge апстрима —
git fetch+merge upstream/mainповерх форка. - Чистка CI — удаляет
dependabot.ymlи чужие workflow, если merge их принёс. - Push в форк — только если merge реально что-то изменил.
- Сборка —
npm ci+npm run build:docker(те же build-args, что и в официальном образе). - Релиз —
tar.gzстатики → GitHub Release с тегомvX.Y.Z. - Уведомление — сообщение в Telegram: готово или упало.
Если апстрим правит ровно ту же строку, что и патч, — шаг merge падает намеренно. Чужой код не должен домёрживаться в обход человека. Приходит сообщение в Telegram, конфликт разрешается руками локально, затем push — синк продолжается.
Сборка и релиз происходят, только если merge реально что-то поменял (или при ручном запуске) — вхолостую по расписанию ничего не собирается и не публикуется.
Файлы
| Путь | Назначение |
|---|---|
.github/workflows/sync-and-build.yml |
Весь пайплайн: синк, чистка, сборка, релиз, уведомления |
scripts/deploy-cabinet.sh |
Деплой на VPS: скачивает релиз, бэкапит текущую статику, раскатывает |
src/pages/Subscription.tsx |
Патч — скрытый блок «Дополнительные опции» |
docs/RUNBOOK.md |
Этот файл |
Удалено из форка сознательно (было в апстриме, плодило шум):
| Файл | Почему убран |
|---|---|
.github/dependabot.yml |
Открывал десятки PR на бамп версий — оставили только Dependabot alerts (без авто-PR) |
ci.yml, lint.yml |
Тесты/линт апстрима — код уже проверен в апстриме до мёржа |
codeql.yml, security-audit.yml |
Security-сканы апстрима, дублируют Dependabot alerts |
docker.yml |
Пуш официального образа в GHCR — не нужен, мы публикуем статику |
release-please.yml, release.yml |
Автобамп версии апстрима — версию читаем из package.json |
Секреты и токены
| Что | Где хранится | Права |
|---|---|---|
TG_BOT_TOKEN |
GitHub → Settings → Secrets and variables → Actions | Отправка сообщений ботом |
TG_CHAT_ID |
Там же | — |
| Fine-grained PAT | VPS: ~/.cabinet-deploy-token, права файла 600 |
Только Contents: Read-only на этот репозиторий |
Токен для VPS специально ограничен одним репозиторием и правом только на чтение — даже если файл утечёт, им нельзя ничего запушить или изменить.
Как выкатить на прод
На VPS:
./deploy-cabinet.sh # последний релиз
./deploy-cabinet.sh v1.63.0 # откат/установка конкретной версии
Скрипт сам:
- скачивает
cabinet-dist.tar.gzчерезgh release download; - бэкапит текущую статику в
cabinet-dist.bak; - раскатывает новую через
rsync -a --delete(чистит устаревшие хэшированные JS-чанки, не трогает50x.html).
Бэкап один, перезаписывается при каждом запуске. Откатиться на конкретную
версию надёжнее через ./deploy-cabinet.sh vX.Y.Z (GitHub хранит все
релизы), а не полагаться только на .bak.
Если что-то пошло не так
Пришло Telegram-сообщение «⚠️ упал» — почти всегда конфликт merge с апстримом. Локально:
git fetch upstream main && git merge upstream/main
# разрешить конфликт (скорее всего в месте патча Subscription.tsx)
git add -A && git commit && git push origin main
Следующий прогон workflow снова пойдёт сам.
Деплой на VPS выкатил битую сборку:
rsync -a --delete cabinet-dist.bak/ cabinet-dist/ # мгновенный откат
# либо
./deploy-cabinet.sh vX.Y.Z # конкретный рабочий релиз
Security-алерт в GitHub про уязвимость — это Dependabot alerts (без авто-PR). Апстрим обычно фиксит сам, фикс прилетит следующим синком. Если критично и срочно — можно поправить зависимость руками отдельным коммитом.
Что стоит проверять периодически
- Раз в 1–2 месяца — вкладка Actions. GitHub отключает scheduled-триггер
после ~60 дней без активности в репозитории. Один ручной
Run workflowвключает обратно. - Бэк и фронт бота обновлять вместе. Синк фронта и апдейт бэкенда бота — по-прежнему ручной процесс, специально не автоматизировали дальше деплоя.
- CHANGELOG апстрима перед выкаткой — на случай breaking changes в API между бэкендом и фронтом.