fix(ci): стек CouchDB после переезда остаётся на своём хосте #3087

Merged
lekss361 merged 1 commit from fix/deploy-obsidian-infra-host into main 2026-08-24 17:58:57 +00:00
Owner

Зачем

Волт Obsidian живёт на Beget вместе с Forgejo и GlitchTip и там же остаётся. А deploy-obsidian.yml ходил на secrets.DEPLOY_HOST безусловно — тот самый секрет, который 30.08 будет переставлен на Selectel.

То есть в день переезда этот workflow молча сменил бы адресата: git reset на /opt/gendesign продуктового хоста и docker compose стека CouchDB там же, а волт на Beget тем временем перестал бы обновляться. Без единой ошибки — деплой зелёный, машина другая.

Файл сам это признавал в шапке: проблема была описана и намеренно оставлена, потому что прошлая правка (#3079) касалась подлинности хоста, а не маршрутизации. Закрываю.

Что меняется

Адресат берётся как INFRA_DEPLOY_HOST с фолбэком на DEPLOY_HOST. До разъезда это одна машина → сегодня не меняется ничего; после — workflow остаётся на инфраструктурном хосте без правки файла в горячий момент.

Схема и фолбэки user / key / port скопированы с deploy-infra.yml, чтобы два файла про один и тот же хост не расходились в поведении.

Отпечаток идёт в паре с адресатом

Соблазнительный вариант — ${{ secrets.INFRA_DEPLOY_SSH_FINGERPRINT || secrets.DEPLOY_SSH_FINGERPRINT }}ловушка: если инфра-хост задан, а его отпечаток нет, выражение свалится на отпечаток другой машины, и ssh откажет со сверкой ключа Beget'а против отпечатка Selectel'а. Перекрёстного фолбэка здесь нет и быть не должно — ровно как в deploy-infra.yml.

Поэтому выбор делает отдельный шаг с явным if, а вниз отдаётся готовое значение. Отпечаток — публичный хеш ключа хоста, через output его гонять можно; приватный ключ остался прямой ссылкой на секрет.

Инъекция через $GITHUB_OUTPUT

$GITHUB_OUTPUT — построчный формат ключ=значение, поэтому перевод строки внутри значения означает инъекцию произвольного output'а. Отпечаток однострочный по определению, но в поле секрета лишний \n попадает копипастой на раз — шапка файла предупреждает об этом отдельно.

Шаг падает с внятным текстом вместо тихой подмены. Молча вычищать нельзя: сверка побайтовая, и trim изменил бы результат проверки.

Test plan

  • YAML парсится (yaml.safe_load)
  • шаг извлечён из workflow и проходит bash -n
  • поведение прогнано на трёх значениях:
    • SHA256:abc123rc=0, «Подлинность хоста: сверяется по DEPLOY_SSH_FINGERPRINT»
    • пусто → rc=0, баннер-предупреждение, деплой не падает (сегодняшнее поведение)
    • значение с переводом строки → rc=1 с объяснением
  • при незаданном INFRA_DEPLOY_HOST host/user/key/port/fingerprint резолвятся ровно в те же секреты, что и до PR
  • после мержа: следующий прогон workflow идёт на тот же хост, что и раньше
  • в окно переезда: задать INFRA_DEPLOY_HOST и убедиться, что стек CouchDB поехал на Beget, а не следом за DEPLOY_HOST

Refs #3062, #3029, #3057

## Зачем Волт Obsidian живёт на Beget вместе с Forgejo и GlitchTip и там же остаётся. А `deploy-obsidian.yml` ходил на `secrets.DEPLOY_HOST` безусловно — тот самый секрет, который 30.08 будет переставлен на Selectel. То есть в день переезда этот workflow **молча сменил бы адресата**: `git reset` на `/opt/gendesign` продуктового хоста и `docker compose` стека CouchDB там же, а волт на Beget тем временем перестал бы обновляться. Без единой ошибки — деплой зелёный, машина другая. Файл сам это признавал в шапке: проблема была описана и намеренно оставлена, потому что прошлая правка (#3079) касалась подлинности хоста, а не маршрутизации. Закрываю. ## Что меняется Адресат берётся как `INFRA_DEPLOY_HOST` с фолбэком на `DEPLOY_HOST`. До разъезда это одна машина → **сегодня не меняется ничего**; после — workflow остаётся на инфраструктурном хосте без правки файла в горячий момент. Схема и фолбэки `user` / `key` / `port` скопированы с `deploy-infra.yml`, чтобы два файла про один и тот же хост не расходились в поведении. ## Отпечаток идёт в паре с адресатом Соблазнительный вариант — `${{ secrets.INFRA_DEPLOY_SSH_FINGERPRINT || secrets.DEPLOY_SSH_FINGERPRINT }}` — **ловушка**: если инфра-хост задан, а его отпечаток нет, выражение свалится на отпечаток *другой машины*, и ssh откажет со сверкой ключа Beget'а против отпечатка Selectel'а. Перекрёстного фолбэка здесь нет и быть не должно — ровно как в `deploy-infra.yml`. Поэтому выбор делает отдельный шаг с явным `if`, а вниз отдаётся готовое значение. Отпечаток — публичный хеш ключа хоста, через output его гонять можно; **приватный ключ остался прямой ссылкой на секрет**. ## Инъекция через $GITHUB_OUTPUT `$GITHUB_OUTPUT` — построчный формат `ключ=значение`, поэтому перевод строки внутри значения означает инъекцию произвольного output'а. Отпечаток однострочный по определению, но в поле секрета лишний `\n` попадает копипастой на раз — шапка файла предупреждает об этом отдельно. Шаг падает с внятным текстом вместо тихой подмены. Молча вычищать нельзя: сверка побайтовая, и `trim` изменил бы результат проверки. ## Test plan - [x] YAML парсится (`yaml.safe_load`) - [x] шаг извлечён из workflow и проходит `bash -n` - [x] поведение прогнано на трёх значениях: - `SHA256:abc123` → `rc=0`, «Подлинность хоста: сверяется по DEPLOY_SSH_FINGERPRINT» - пусто → `rc=0`, баннер-предупреждение, деплой не падает (сегодняшнее поведение) - значение с переводом строки → `rc=1` с объяснением - [x] при незаданном `INFRA_DEPLOY_HOST` host/user/key/port/fingerprint резолвятся ровно в те же секреты, что и до PR - [ ] после мержа: следующий прогон workflow идёт на тот же хост, что и раньше - [ ] в окно переезда: задать `INFRA_DEPLOY_HOST` и убедиться, что стек CouchDB поехал на Beget, а не следом за `DEPLOY_HOST` Refs #3062, #3029, #3057
lekss361 added 1 commit 2026-08-24 17:57:53 +00:00
fix(ci): стек CouchDB после переезда остаётся на своём хосте
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
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 / changes (pull_request) Successful in 8s
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
a77bfa5270
Волт Obsidian живёт на Beget вместе с Forgejo и GlitchTip и там же остаётся.
А deploy-obsidian.yml ходил на secrets.DEPLOY_HOST безусловно — тот самый
секрет, который 30.08 будет переставлен на Selectel.

Значит в день переезда этот workflow молча сменил бы адресата: git reset на
/opt/gendesign продуктового хоста и docker compose стека CouchDB там же, а
волт на Beget тем временем перестал бы обновляться. Без единой ошибки —
деплой зелёный, машина другая. Файл сам это признавал в шапке: проблема была
описана и намеренно оставлена, потому что прошлая правка касалась подлинности
хоста, а не маршрутизации.

Теперь адресат берётся как INFRA_DEPLOY_HOST с фолбэком на DEPLOY_HOST. До
разъезда это одна машина, поэтому сегодня не меняется ничего; после — workflow
остаётся на инфраструктурном хосте без правки файла в горячий момент. Схема
и фолбэки user/key/port скопированы с deploy-infra.yml, чтобы два файла про
один и тот же хост не расходились в поведении.

Отпечаток выбирается В ПАРЕ с адресатом, отдельным шагом с явным if. Соблазн
написать `secrets.INFRA_FP || secrets.DEPLOY_FP` — ловушка: если инфра-хост
задан, а его отпечаток нет, выражение свалится на отпечаток другой машины, и
ssh откажет со сверкой ключа Beget'а против отпечатка Selectel'а. Перекрёстного
фолбэка здесь нет и быть не должно — ровно как в deploy-infra.yml.

Отпечаток идёт вниз через output шага: это публичный хеш ключа хоста, не
секрет. Приватный ключ так передавать нельзя, он остался прямой ссылкой на
секрет.

$GITHUB_OUTPUT — построчный формат «ключ=значение», поэтому перевод строки
внутри значения означает инъекцию произвольного output'а. Отпечаток
однострочный по определению, но в поле секрета лишний перевод строки попадает
копипастой на раз — шапка файла об этом предупреждает отдельно. Проверка
падает с внятным текстом вместо тихой подмены: молча вычищать нельзя, сверка
побайтовая и trim изменил бы результат.

Проверено: YAML парсится, шаг проходит bash -n, поведение прогнано на трёх
значениях — нормальный отпечаток даёт rc=0 и строку про сверку, пустой даёт
предупреждение и не роняет деплой (как сегодня), значение с переводом строки
отбивается с rc=1.

Refs #3062, #3029, #3057
lekss361 merged commit de157b1024 into main 2026-08-24 17:58:57 +00:00
lekss361 deleted branch fix/deploy-obsidian-infra-host 2026-08-24 17:58:57 +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#3087
No description provided.