fix(ci): deploy-tradein paths-filter base = last deployed SHA (накопленный diff, fail-safe build-all) #1839

Merged
lekss361 merged 1 commit from fix/deploy-tradein-cumulative-base into main 2026-06-20 14:13:54 +00:00
Owner

Чинит class-баг деплоя: при быстрых мержах build-джобы пропускались → код в main, образа нет (сегодня ударило по #1825 и #1829).

Корень

changes-джоба (dorny/paths-filter) диффала per-merge-commit против родителя. Frontend-only мерж #1830 не видел backend-изменений #1829 (они в предыдущем коммите) → build-backend/build-browser skipped, хотя дерево их содержит. Выживший ран собирает только дельту СВОЕГО коммита, а ран #1829 (который собрал бы backend/browser) отменён concurrency-гонкой.

Решение (вариант B — инкрементально, без «всегда 3 образа»)

paths-filter base = последний успешно задеплоенный SHA → накопленный diff deployed..HEAD. Frontend-мерж сразу после backend-мержа теперь диффает от last-DEPLOYED → видит И backend И frontend → собирает оба.

Трекинг — host-file (/opt/gendesign/.tradein-deployed-sha): deploy-джоба пишет $GITHUB_SHA ПОСЛЕДНИМ в SSH-скрипте (под set -euo pipefail → только на полном успехе). Выбран вместо git-ref т.к. ни один workflow не использует токен с contents:write — переиспользуем существующие DEPLOY_* секреты, ноль новых зависимостей/attack-surface.

changes-джоба: fetch-depth:0; шаг resolve-base SSH-читает marker, валидирует (40-hex + merge-base --is-ancestor); если SHA есть → paths-filter с base=; если нет → шаг set-all эмитит все outputs=true.

Fail-safe (критично)

ЛЮБАЯ неопределённость → build-all, никогда build-none: первый ран (marker нет), VPS недоступен, битый/не-предок SHA, force-push. Лишняя сборка безопаснее пропуска.

Сценарии (проверены логикой, CI локально не гоняется)

  • (a) первый ран после мержа этого PR: marker ещё нет → build-all → деплоит весь backlog, включая pending #1829 backend+browser (отдельный dispatch не нужен).
  • (b) backend-only мерж: diff видит только backend → build-backend.
  • (c) пачка backend+frontend: выживший ран диффает от last-deployed → собирает оба. ✓ (фикс)
  • (d) deploy упал: marker не сдвинут → следующий ран пересоберёт ту же дельту.

Не трогали

concurrency: cancel-in-progress: false (true рискует оборвать прод-деплой mid-SSH); workflow_dispatch форс-билд.

YAML валиден (yaml.safe_load + pre-commit check-yaml). Файл один: .forgejo/workflows/deploy-tradein.yml.

Чинит class-баг деплоя: при быстрых мержах build-джобы пропускались → код в main, образа нет (сегодня ударило по #1825 и #1829). ## Корень `changes`-джоба (dorny/paths-filter) диффала **per-merge-commit** против родителя. Frontend-only мерж #1830 не видел backend-изменений #1829 (они в предыдущем коммите) → `build-backend`/`build-browser` skipped, хотя дерево их содержит. Выживший ран собирает только дельту СВОЕГО коммита, а ран #1829 (который собрал бы backend/browser) отменён concurrency-гонкой. ## Решение (вариант B — инкрементально, без «всегда 3 образа») paths-filter `base` = **последний успешно задеплоенный SHA** → накопленный diff `deployed..HEAD`. Frontend-мерж сразу после backend-мержа теперь диффает от last-DEPLOYED → видит И backend И frontend → собирает оба. **Трекинг — host-file** (`/opt/gendesign/.tradein-deployed-sha`): deploy-джоба пишет `$GITHUB_SHA` ПОСЛЕДНИМ в SSH-скрипте (под `set -euo pipefail` → только на полном успехе). Выбран вместо git-ref т.к. ни один workflow не использует токен с `contents:write` — переиспользуем существующие DEPLOY_* секреты, ноль новых зависимостей/attack-surface. **changes-джоба**: `fetch-depth:0`; шаг `resolve-base` SSH-читает marker, валидирует (40-hex + `merge-base --is-ancestor`); если SHA есть → paths-filter с `base=`; если нет → шаг `set-all` эмитит все outputs=`true`. ## Fail-safe (критично) ЛЮБАЯ неопределённость → **build-all**, никогда build-none: первый ран (marker нет), VPS недоступен, битый/не-предок SHA, force-push. Лишняя сборка безопаснее пропуска. ## Сценарии (проверены логикой, CI локально не гоняется) - (a) первый ран после мержа этого PR: marker ещё нет → build-all → **деплоит весь backlog, включая pending #1829 backend+browser** (отдельный dispatch не нужен). - (b) backend-only мерж: diff видит только backend → build-backend. - (c) пачка backend+frontend: выживший ран диффает от last-deployed → собирает оба. ✓ (фикс) - (d) deploy упал: marker не сдвинут → следующий ран пересоберёт ту же дельту. ## Не трогали `concurrency: cancel-in-progress: false` (true рискует оборвать прод-деплой mid-SSH); `workflow_dispatch` форс-билд. YAML валиден (`yaml.safe_load` + pre-commit check-yaml). Файл один: `.forgejo/workflows/deploy-tradein.yml`.
lekss361 added 1 commit 2026-06-20 13:07:11 +00:00
fix(ci): deploy-tradein paths-filter base = last deployed SHA (накопленный diff, fail-safe build-all)
All checks were successful
CI / changes (pull_request) Successful in 5s
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
febc88d37b
При быстрых мержах dorny/paths-filter без explicit base диффает per-merge-commit
(parent of merge), а не накопленно от последнего деплоя. Итог: backend-мерж #1829
не попадает в diff frontend-мержа #1830 → build-backend skipped, образа нет.

Решение (host-file mechanism):
- deploy-джоба пишет `echo "$GITHUB_SHA" > /opt/gendesign/.tradein-deployed-sha`
  в самом конце SSH-скрипта — только после успешного up+миграций.
- changes-джоба читает файл по SSH (те же DEPLOY_* секреты), валидирует SHA как
  40-char hex + git merge-base --is-ancestor HEAD, передаёт в `base:` paths-filter.
- Если файл отсутствует / SHA не предок HEAD / SSH недоступен → FAIL-SAFE:
  step `set-all` эмитит все outputs=true, paths-filter пропускается,
  все образы собираются (better safe than sorry).

Почему host-file, не git-ref: в workflows не используется `gitea.token` /
`GITHUB_TOKEN` с contents:write — добавлять новое разрешение ради ref push
ненужный риск. DEPLOY_* секреты уже есть, SSH уже есть.

Не изменено: concurrency.cancel-in-progress=false, workflow_dispatch форс,
логика build/deploy/migrations.
lekss361 merged commit 261f3a33e6 into main 2026-06-20 14:13:54 +00:00
lekss361 deleted branch fix/deploy-tradein-cumulative-base 2026-06-20 14:13:54 +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#1839
No description provided.