chore(ci): синхронизировать /opt/gendesign на остающемся хосте #3071

Merged
lekss361 merged 1 commit from chore/deploy-infra-host into main 2026-08-24 00:51:51 +00:00
Owner

Закрывает пункт «чем обновлять /opt/gendesign на Beget после смены DEPLOY_HOST» из #3059.

Проблема

deploy.yml ходит по SSH на secrets.DEPLOY_HOST и жёстко пересинхронизирует там рабочее дерево. Сегодня это Beget, поэтому и прод, и инфраструктура обновляются одним проходом.

После 30.08 DEPLOY_HOST станет указывать на Selectel — и /opt/gendesign на Beget перестанет обновляться совсем. Молча: ни ошибки, ни падения пайплайна, ни строчки в логе.

А из этого каталога на Beget продолжат работать:

Что Откуда запускается
ops/backup.sh, ops/backup-forgejo.sh, ops/check-backup-staleness.sh, ops/lib-backup.sh, ops/docker-prune.sh cron
docker-compose.prod.yml для Forgejo / GlitchTip / CouchDB docker
Caddyfile + caddy/sites/infra.caddy единственный публичный вход для git / errors / obsidian (#3062)

То есть любая будущая правка этих файлов легла бы в main и никогда не доехала до машины, которая их исполняет.

Это ровно класс #2887 — тот самый, из-за которого в paths: появился глоб ops/*.sh с комментарием «скрипт запускается на VM по cron из /opt/gendesign/ops/, куда попадает только через жёсткую пересинхронизацию шага деплоя. Без этой строки правка лежала бы в main, а cron месяцами исполнял бы старую версию — молча и без единого сигнала». Здесь то же самое, но не на уровне одного файла, а на уровне целого хоста.

Решение

Отдельный workflow deploy-infra.yml, инертный пока не задан INFRA_DEPLOY_HOST.

Почему отдельный, а не job в deploy.yml: разные адресаты и разные вердикты. «Выкатили продукт на Selectel» и «синхронизировали инфру на Beget» — независимые факты, и падение второго не должно читаться как неудавшийся деплой продукта. Триггеры тоже разные — инфра-хосту не нужны пересборки backend/** и frontend/**, поэтому в paths: только то, что там реально исполняется.

Почему гейт: сегодня Beget и есть DEPLOY_HOST. Второй проход по тому же хосту был бы лишним и мог бы состязаться с основным деплоем за докер-демон (#2950 — взаимное исключение докер-секций двух прод-деплоев). Включается одной настройкой в момент, когда хосты разъедутся.

Что намеренно НЕ делает

  • Прун образов — конкурирует за leases докер-демона (#2950), остаётся за еженедельным ops/docker-prune.sh.
  • Перезапуск Forgejo / GlitchTip / CouchDB — правка ops-скрипта не повод ронять git.
  • Caddy — reload, а не recreate. Конфиг примонтирован read-only, контейнер читает тот же файл, который только что обновил git. Невалидный конфиг откажет громко, а старый продолжит работать — то есть падение здесь не роняет git / errors / obsidian.

Test plan

  • YAML разбирается; триггеры (push + workflow_dispatch), paths и оба шага — те, что задуманы
  • Гейт прогнан обеими ветками: пустой INFRA_DEPLOY_HOSTenabled=false и job ничего не делает; заданный → enabled=true
  • Настоящий проход по SSH на разъехавшиеся хосты — невозможен до переезда, сейчас хост один

Что нужно от тебя в момент переезда

Задать в секретах Actions:

INFRA_DEPLOY_HOST=46.173.16.127     # Beget, остающийся хост

Плюс, если у остающегося хоста будут отдельные креды — INFRA_DEPLOY_USER / INFRA_DEPLOY_SSH_KEY / INFRA_DEPLOY_PORT. Если их не задать, workflow берёт те же DEPLOY_* через ||-фолбэк.

⚠️ Одно место, которое я не смог проверить: поддерживает ли Forgejo Actions (act_runner) выражение secrets.A || secrets.B в with:. В GitHub Actions это штатно, здесь — вероятно тоже, но без прогона утверждать не буду. Если фолбэк не сработает, лечится заданием всех четырёх INFRA_* явно.

Refs #3059, #3057, #3029

Закрывает пункт «чем обновлять `/opt/gendesign` на Beget после смены `DEPLOY_HOST`» из #3059. ## Проблема `deploy.yml` ходит по SSH на `secrets.DEPLOY_HOST` и жёстко пересинхронизирует там рабочее дерево. Сегодня это Beget, поэтому и прод, и инфраструктура обновляются одним проходом. **После 30.08 `DEPLOY_HOST` станет указывать на Selectel — и `/opt/gendesign` на Beget перестанет обновляться совсем.** Молча: ни ошибки, ни падения пайплайна, ни строчки в логе. А из этого каталога на Beget продолжат работать: | Что | Откуда запускается | |---|---| | `ops/backup.sh`, `ops/backup-forgejo.sh`, `ops/check-backup-staleness.sh`, `ops/lib-backup.sh`, `ops/docker-prune.sh` | cron | | `docker-compose.prod.yml` для Forgejo / GlitchTip / CouchDB | docker | | `Caddyfile` + `caddy/sites/infra.caddy` | **единственный публичный вход** для `git` / `errors` / `obsidian` (#3062) | То есть любая будущая правка этих файлов легла бы в `main` и никогда не доехала до машины, которая их исполняет. Это ровно класс **#2887** — тот самый, из-за которого в `paths:` появился глоб `ops/*.sh` с комментарием *«скрипт запускается на VM по cron из /opt/gendesign/ops/, куда попадает только через жёсткую пересинхронизацию шага деплоя. Без этой строки правка лежала бы в main, а cron месяцами исполнял бы старую версию — молча и без единого сигнала»*. Здесь то же самое, но не на уровне одного файла, а **на уровне целого хоста**. ## Решение Отдельный workflow `deploy-infra.yml`, **инертный пока не задан `INFRA_DEPLOY_HOST`**. Почему отдельный, а не job в `deploy.yml`: разные адресаты и разные вердикты. «Выкатили продукт на Selectel» и «синхронизировали инфру на Beget» — независимые факты, и падение второго не должно читаться как неудавшийся деплой продукта. Триггеры тоже разные — инфра-хосту не нужны пересборки `backend/**` и `frontend/**`, поэтому в `paths:` только то, что там реально исполняется. Почему гейт: сегодня Beget **и есть** `DEPLOY_HOST`. Второй проход по тому же хосту был бы лишним и мог бы состязаться с основным деплоем за докер-демон (#2950 — взаимное исключение докер-секций двух прод-деплоев). Включается одной настройкой в момент, когда хосты разъедутся. ### Что намеренно НЕ делает - **Прун образов** — конкурирует за leases докер-демона (#2950), остаётся за еженедельным `ops/docker-prune.sh`. - **Перезапуск Forgejo / GlitchTip / CouchDB** — правка ops-скрипта не повод ронять git. - **Caddy — `reload`, а не `recreate`.** Конфиг примонтирован read-only, контейнер читает тот же файл, который только что обновил git. Невалидный конфиг откажет **громко**, а старый продолжит работать — то есть падение здесь не роняет `git` / `errors` / `obsidian`. ## Test plan - [x] YAML разбирается; триггеры (`push` + `workflow_dispatch`), `paths` и оба шага — те, что задуманы - [x] **Гейт прогнан обеими ветками:** пустой `INFRA_DEPLOY_HOST` → `enabled=false` и job ничего не делает; заданный → `enabled=true` - [ ] Настоящий проход по SSH на разъехавшиеся хосты — **невозможен до переезда**, сейчас хост один ## Что нужно от тебя в момент переезда Задать в секретах Actions: ``` INFRA_DEPLOY_HOST=46.173.16.127 # Beget, остающийся хост ``` Плюс, если у остающегося хоста будут отдельные креды — `INFRA_DEPLOY_USER` / `INFRA_DEPLOY_SSH_KEY` / `INFRA_DEPLOY_PORT`. Если их не задать, workflow берёт те же `DEPLOY_*` через `||`-фолбэк. ⚠️ **Одно место, которое я не смог проверить:** поддерживает ли Forgejo Actions (`act_runner`) выражение `secrets.A || secrets.B` в `with:`. В GitHub Actions это штатно, здесь — вероятно тоже, но без прогона утверждать не буду. Если фолбэк не сработает, лечится заданием всех четырёх `INFRA_*` явно. Refs #3059, #3057, #3029
lekss361 added 1 commit 2026-08-24 00:49:17 +00:00
chore(ci): синхронизировать /opt/gendesign на остающемся хосте
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI / changes (pull_request) Successful in 9s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
33ef0f7330
После переезда 30.08 `secrets.DEPLOY_HOST` станет указывать на Selectel —
и рабочее дерево /opt/gendesign на Beget перестанет обновляться совсем.
Молча: ни ошибки, ни падения пайплайна.

А оттуда на Beget продолжат работать:
  - cron-скрипты бэкапов (backup.sh, backup-forgejo.sh,
    check-backup-staleness.sh, lib-backup.sh, docker-prune.sh)
  - docker-compose.prod.yml для Forgejo / GlitchTip / CouchDB
  - Caddyfile + caddy/sites/infra.caddy — единственный публичный вход
    для git / errors / obsidian (#3062)

Любая будущая правка этих файлов легла бы в main и никогда не доехала до
машины, которая их исполняет. Это класс #2887 («скрипт запускается по
cron из /opt/gendesign, куда попадает только через жёсткую
пересинхронизацию дерева на шаге деплоя»), но не на уровне одного файла,
а на уровне целого хоста.

Отдельный workflow, а не job в deploy.yml: разные адресаты и разные
вердикты — «выкатили продукт на Selectel» и «синхронизировали инфру на
Beget» независимы, и падение второго не должно читаться как неудавшийся
деплой продукта. Триггеры тоже разные: инфра-хосту не нужны пересборки
backend/frontend.

ИНЕРТЕН, пока не задан INFRA_DEPLOY_HOST. Сегодня Beget и есть
DEPLOY_HOST, второй проход по тому же хосту был бы лишним и мог бы
состязаться с основным деплоем за докер-демон (#2950). Включается одной
настройкой в момент, когда хосты разъедутся.

Намеренно НЕ делает: прун образов (конкурирует за leases докер-демона,
#2950) и перезапуск Forgejo/GlitchTip/CouchDB (правка ops-скрипта не
повод ронять git). Caddy — reload, а не recreate: невалидный конфиг
откажет громко, старый продолжит работать.

Проверено: YAML разбирается, триггеры и paths те, что задуманы, шагов 2;
гейт прогнан обеими ветками (пустой секрет -> enabled=false, заданный ->
enabled=true).

Refs #3059, #3057, #3029
lekss361 merged commit 01128e6331 into main 2026-08-24 00:51:51 +00:00
lekss361 deleted branch chore/deploy-infra-host 2026-08-24 00:51:51 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#3071
No description provided.