3 проблемы фиксятся:
1. tradein-mvp/backend/Dockerfile копировал только COPY app — scripts/
слетал при каждом deploy, требовал manual docker cp.
2. docker-compose.prod.yml без env_file — .env.runtime не читался
контейнером, переменные приходили только через host env.
3. Env-var name mismatch: compose YANDEX_GEOCODER_KEY vs script
YANDEX_GEOCODER_API_KEY — script всегда видел None.
Изменения:
- backend/Dockerfile: COPY scripts ./scripts в builder + runner stage
- docker-compose.prod.yml:
* env_file: ./backend/.env.runtime (required: false) — pattern из
main backend (PR #585)
* убран дубль `YANDEX_GEOCODER_API_KEY: ${...}` из environment:
block — он бы overrideal env_file пустым значением. Reviewer nit
applied inline.
- pydantic Settings (app/core/config.py): rename yandex_geocoder_key
→ yandex_geocoder_api_key. Case-insensitive env binding автоматически
подхватывает `YANDEX_GEOCODER_API_KEY` (no Field alias нужен).
- All 5 call sites в app/services/geocoder.py обновлены.
- app/tasks/geocode_missing.py docstring + test mock обновлены.
- backend/scripts/README.md: canonical `docker exec` commands без
manual `docker cp` workflow.
- DEPLOY.md + .env.example обновлены с новым именем переменной.
Verified:
- pytest tests/test_backfill_house_coords.py + test_audit_address_mismatch.py
+ test_cadastral_reverse.py → 56 pass
- docker compose -f docker-compose.prod.yml config → valid syntax
- pydantic binding: YANDEX_GEOCODER_API_KEY=foo → settings.yandex_geocoder_api_key=='foo'
- code-reviewer LGTM (nit applied inline)
После merge — на VPS уже создан /opt/gendesign/tradein-mvp/backend/.env.runtime
с YANDEX_GEOCODER_API_KEY (см. PR #591 deploy). deploy.yml triggers
force-recreate из-за нового image hash → env_file pick up автоматически.
43 lines
2.2 KiB
Python
43 lines
2.2 KiB
Python
"""Минимальный settings для standalone trade-in MVP."""
|
||
|
||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||
|
||
|
||
class Settings(BaseSettings):
|
||
model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8", extra="ignore")
|
||
|
||
# required — задаётся через env DATABASE_URL. Нет дефолта: fail-fast при старте
|
||
# если переменная не задана (C-3 security audit).
|
||
database_url: str
|
||
cors_origins: list[str] = ["http://localhost", "http://localhost:3000", "http://localhost:8080"]
|
||
environment: str = "dev"
|
||
|
||
# Geocoder. Env var name `YANDEX_GEOCODER_API_KEY` — consistent с scripts/
|
||
# backfill_house_coords.py + audit_address_mismatch.py + main backend
|
||
# OpenRouteService_API_KEY pattern. Renamed from YANDEX_GEOCODER_KEY (PR F).
|
||
yandex_geocoder_api_key: str | None = None # 25K req/day free после регистрации
|
||
yandex_suggest_key: str | None = None # для frontend autocomplete (proxy через backend)
|
||
# для User-Agent в Nominatim (Nominatim Usage Policy)
|
||
contact_email: str = "erginrajpopxbe@outlook.com"
|
||
|
||
# Public URL — для QR-кода в PDF, shareable links, etc.
|
||
public_url: str = "http://127.0.0.1:8080"
|
||
|
||
# GlitchTip DSN — мониторинг ошибок (Sentry-совместимый). #396.
|
||
# Пусто = мониторинг выключен (dev). В prod — env GLITCHTIP_DSN из .env.runtime.
|
||
glitchtip_dsn: str | None = None
|
||
|
||
# Ключ шифрования для pgp_sym_encrypt (Cian session cookies).
|
||
# Задаётся через env COOKIE_ENCRYPTION_KEY. Пусто = шифрование не работает.
|
||
cookie_encryption_key: str = ""
|
||
|
||
# Redis URL для hot-cache (Phase 3.2). Задаётся через env REDIS_URL.
|
||
redis_url: str = "redis://localhost:6379/0"
|
||
|
||
# Password for tradein_fdw_reader role — used by backend startup to create/refresh
|
||
# USER MAPPING for postgres_fdw → gendesign DB (gendesign_remote server).
|
||
# Пусто = USER MAPPING не создаётся, gendesign_cad_buildings не работает (dev).
|
||
gendesign_fdw_password: str | None = None
|
||
|
||
|
||
settings = Settings()
|