Merge pull request 'chore(ci): деплой на изменение ролей, ruff-гейт для МЕРЫ, удаление мёртвого workflow' (#2751) from chore/ci-config-cleanup-v2 into main
All checks were successful
Deploy / changes (push) Successful in 8s
Deploy Trade-In / changes (push) Successful in 11s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy / build-backend (push) Successful in 43s
Deploy / build-worker (push) Successful in 44s
Deploy / build-frontend (push) Successful in 45s
Deploy / deploy (push) Successful in 1m8s
Deploy / deploy-status (push) Successful in 1s
Deploy Trade-In / test (push) Successful in 3m45s
Deploy Trade-In / build-backend (push) Successful in 2m3s
Deploy Trade-In / deploy (push) Successful in 2m37s
Deploy Trade-In / deploy-status (push) Successful in 2s

This commit is contained in:
lekss361 2026-08-15 19:39:05 +00:00
commit 48e75534bb
5 changed files with 21 additions and 97 deletions

View file

@ -183,13 +183,22 @@ jobs:
restore-keys: |
uv-tradein-${{ runner.os }}-
- name: Sync deps (incl. dev group — pytest)
- name: Sync deps (incl. dev group — pytest, ruff)
# Workspace-лок tradein-mvp/uv.lock TRACKED (с воркспейса #2137; gitignored
# только старый backend/uv.lock) → --frozen детерминирован и зеркалит
# Dockerfile (uv sync --frozen --no-dev там). uv находит workspace root
# вверх от cwd.
run: uv sync --frozen
- name: Lint (ruff check)
# Правила выбраны в tradein-mvp/backend/pyproject.toml ([tool.ruff.lint]
# select = E F I B UP N RUF), но до этого шага их никто не гонял в CI —
# "дерево чистое" было непроверенным утверждением, а не гарантией.
# Версия ruff — та же, что в tradein-mvp/uv.lock (--frozen из шага выше),
# т.е. ровно то, что видит `uv sync --frozen` в Dockerfile.
# Blocking: любое нарушение → job RED (не декоративно).
run: uv run ruff check .
- name: Run pytest (tradein-mvp/backend)
# БЕЗ deselect'ов — сьют гоняется целиком (#2722).
#

View file

@ -20,6 +20,14 @@ on:
# деплоя ниже — без этого триггера правка bootstrap-файла молча не доезжала бы
# до прода до следующего чужого коммита в backend/.
- "ops/db-bootstrap/**"
# RBAC roles config (auth/roles.yaml, bind-mounted read-only ТОЛЬКО в backend —
# см. docker-compose.prod.yml; worker монтирует лишь ./data и ./reports).
# app.core.auth кэширует парсинг на весь lifetime процесса (@lru_cache) — без
# этого триггера правка ролей вступала бы в силу в случайный момент, только на
# следующий чужой деплой (`up -d --force-recreate --no-deps backend worker beat`
# ниже сбрасывает кэш перезапуском процесса; сам файл в образ не запекается,
# ребилда картинок для этого не нужно).
- "auth/**"
# То же самое, ровно тот же класс бага (#2887): скрипт запускается на VM
# по cron из /opt/gendesign/ops/, куда попадает только через `git reset --hard`
# шага деплоя. Без этой строки правка скрипта лежала бы в main, а cron месяцами

View file

@ -1,91 +0,0 @@
name: CI
on:
push:
branches:
- main
- 'feat/**'
- 'fix/**'
- 'refactor/**'
- 'chore/**'
- 'docs/**'
- 'perf/**'
- 'test/**'
- 'hotfix/**'
pull_request:
branches: [main]
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
backend:
runs-on: ubuntu-latest
services:
postgres:
image: postgis/postgis:16-3.4
env:
POSTGRES_DB: gendesign
POSTGRES_USER: gendesign
POSTGRES_PASSWORD: gendesign
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready -U gendesign"
--health-interval 5s
--health-timeout 5s
--health-retries 10
defaults:
run:
working-directory: backend
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v3
with:
enable-cache: true
- name: Set up Python
run: uv python install 3.12
- name: Install system deps for geo + WeasyPrint
run: |
sudo apt-get update
sudo apt-get install -y libpq-dev libgdal-dev libproj-dev libgeos-dev \
libcairo2 libpango-1.0-0 libpangoft2-1.0-0
- name: Install Python deps
run: uv sync
- name: Lint (ruff)
run: uv run ruff check .
- name: Type check (mypy strict on core)
run: |
uv run mypy \
app/services/generative \
app/services/site_finder/scorer.py
- name: Test (pytest)
run: uv run pytest -q
env:
DATABASE_URL: postgresql+psycopg://gendesign:gendesign@localhost:5432/gendesign
frontend:
runs-on: ubuntu-latest
defaults:
run:
working-directory: frontend
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
cache-dependency-path: frontend/package-lock.json
- run: npm ci || npm install
- run: npm run lint
- run: npm run type-check
- run: npm run build

View file

@ -85,12 +85,10 @@ docker-compose.prod.yml main стек (backend, frontend, postgres, redis, work
docker-compose.obsidian.yml obsidian-стек (CouchDB) — деплоится отдельно
docker-compose.uptime.yml Uptime Kuma мониторинг (status.gendsgn.ru) — отдельный стек, запуск вручную
.forgejo/workflows/ (Forgejo Actions — основной CI/CD после миграции 16.05.2026)
├── ci.yml lint (ruff) + mypy + pytest на PR
├── ci.yml lint (ruff) + pytest на PR
├── deploy.yml main → пересборка backend/frontend образов + auto-apply data/sql/*.sql + SSH deploy
├── deploy-tradein.yml tradein-mvp стек (отдельный пайплайн + свой _schema_migrations)
└── stale-claims.yml авто-снятие протухших claim-меток в bot-пайплайне
.github/workflows/ (остаточные — только obsidian-стек на GitHub)
└── deploy-obsidian.yml obsidian-стек (CouchDB compose changes + bootstrap)
```
---
@ -158,7 +156,7 @@ docker-compose.uptime.yml Uptime Kuma мониторинг (status.gendsgn.ru
**Forgejo Actions deploys** (self-hosted `git.gendsgn.ru`, мигрировано с GitHub Actions 16.05.2026):
- [`.forgejo/workflows/ci.yml`](.forgejo/workflows/ci.yml) — на PR: ruff lint + mypy (selective strict) + pytest. Блокирует merge при провале.
- [`.forgejo/workflows/ci.yml`](.forgejo/workflows/ci.yml) — на PR: ruff lint + pytest (coverage gate ≥65%). mypy strict в гейте не гоняется (доступен вручную — `uv run mypy app/services/generative app/services/site_finder/scorer.py`). Блокирует merge при провале.
- [`.forgejo/workflows/deploy.yml`](.forgejo/workflows/deploy.yml) — main: триггер на `backend/**`, `frontend/**`, `Caddyfile`, `docker-compose.prod.yml`, `data/sql/**`. Build backend lean + worker-with-chromium + frontend → push в приватный GHCR → SSH `git reset --hard`, **auto-apply pending `data/sql/NN_*.sql` через `_schema_migrations`** (idempotent, см. ниже про миграции), sed `SENTRY_RELEASE=$IMAGE_TAG` в `backend/.env.runtime`, `compose pull && up -d`, `caddy reload`, `curl /health`.
- [`.forgejo/workflows/deploy-tradein.yml`](.forgejo/workflows/deploy-tradein.yml) — tradein-mvp стек (отдельный пайплайн).
- [`.forgejo/workflows/deploy-obsidian.yml`](.forgejo/workflows/deploy-obsidian.yml) — obsidian: триггер на `docker-compose.obsidian.yml`, `scripts/setup-couchdb.sh`, `docs/obsidian-livesync.md`. Без сборки образов (couchdb:3 с DockerHub), SSH `compose up -d` + idempotent bootstrap (CORS, DB, лимиты). *(до 2026-07-05 ошибочно лежал в `.github/workflows/` — там ни разу не исполнился, см. issue #2416; контейнер держался вручную.)*

View file

@ -378,7 +378,7 @@ def test_corridor_clamp_above_corridor_tier_c_clamps() -> None:
def test_corridor_clamp_inside_corridor_is_noop() -> None:
# Эконом/комфорт: headline в коридоре (с учётом slack) → ничего не меняется.
new_ppm2, new_price, new_low, new_high, clamped = _clamp(
new_ppm2, _, _, _, clamped = _clamp(
median_ppm2=140_000, corridor_high=130_000, count=20, tier="C"
)
assert clamped is False