chore(scraper-kit): docker-context wiring + restore backend workspace dep (#2137)
All checks were successful
Deploy Trade-In / changes (push) Successful in 11s
Deploy Trade-In / build-frontend (push) Successful in 31s
Deploy Trade-In / build-browser (push) Successful in 30s
Deploy Trade-In / test (push) Successful in 1m29s
Deploy Trade-In / build-backend (push) Successful in 1m21s
Deploy Trade-In / deploy (push) Successful in 1m2s
All checks were successful
Deploy Trade-In / changes (push) Successful in 11s
Deploy Trade-In / build-frontend (push) Successful in 31s
Deploy Trade-In / build-browser (push) Successful in 30s
Deploy Trade-In / test (push) Successful in 1m29s
Deploy Trade-In / build-backend (push) Successful in 1m21s
Deploy Trade-In / deploy (push) Successful in 1m2s
This commit is contained in:
parent
ddf6cb7ce3
commit
8d7feabf9f
6 changed files with 97 additions and 16 deletions
|
|
@ -183,7 +183,10 @@ jobs:
|
||||||
- name: Build & push tradein-backend
|
- name: Build & push tradein-backend
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
context: ./tradein-mvp/backend
|
# Context = tradein-mvp/ (uv workspace root): образу нужен packages/scraper-kit
|
||||||
|
# для editable install (#2137). Dockerfile — в backend/.
|
||||||
|
context: ./tradein-mvp
|
||||||
|
file: ./tradein-mvp/backend/Dockerfile
|
||||||
push: true
|
push: true
|
||||||
cache-from: type=registry,ref=${{ env.IMAGE_BACKEND }}:buildcache
|
cache-from: type=registry,ref=${{ env.IMAGE_BACKEND }}:buildcache
|
||||||
cache-to: type=registry,ref=${{ env.IMAGE_BACKEND }}:buildcache,mode=max
|
cache-to: type=registry,ref=${{ env.IMAGE_BACKEND }}:buildcache,mode=max
|
||||||
|
|
|
||||||
49
tradein-mvp/.dockerignore
Normal file
49
tradein-mvp/.dockerignore
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
# Docker build context = tradein-mvp/ (uv workspace root) для backend/Dockerfile (#2137).
|
||||||
|
# Этот .dockerignore применяется только к backend-билду (context = tradein-mvp);
|
||||||
|
# frontend/browser собираются из своих под-контекстов (./frontend, ./browser).
|
||||||
|
#
|
||||||
|
# Держим context тонким: образу нужны лишь pyproject.toml, uv.lock, backend/,
|
||||||
|
# packages/. Всё остальное — исключаем.
|
||||||
|
|
||||||
|
# --- прочие подпроекты, не нужные backend-образу ---
|
||||||
|
frontend/
|
||||||
|
browser/
|
||||||
|
deploy/
|
||||||
|
docs/
|
||||||
|
ops/
|
||||||
|
scripts/
|
||||||
|
|
||||||
|
# --- backend: не нужны в образе (Dockerfile копирует только app/ + scripts/) ---
|
||||||
|
backend/tests/
|
||||||
|
backend/data/sql/
|
||||||
|
backend/.env
|
||||||
|
backend/.env.runtime
|
||||||
|
backend/.env.local
|
||||||
|
backend/Dockerfile
|
||||||
|
backend/.dockerignore
|
||||||
|
|
||||||
|
# --- инфра-манифесты (не нужны внутри образа) ---
|
||||||
|
docker-compose*.yml
|
||||||
|
Makefile
|
||||||
|
*.md
|
||||||
|
|
||||||
|
# --- Python / build junk ---
|
||||||
|
**/.venv/
|
||||||
|
**/__pycache__/
|
||||||
|
**/*.egg-info/
|
||||||
|
**/.pytest_cache/
|
||||||
|
**/.ruff_cache/
|
||||||
|
**/.mypy_cache/
|
||||||
|
**/*.pyc
|
||||||
|
|
||||||
|
# --- VCS / env / IDE / OS ---
|
||||||
|
.git/
|
||||||
|
.gitignore
|
||||||
|
**/.env
|
||||||
|
**/.env.local
|
||||||
|
**/.env.*.local
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
*.log
|
||||||
|
|
@ -1,5 +1,10 @@
|
||||||
# Trade-In MVP backend — lean image (FastAPI + WeasyPrint).
|
# Trade-In MVP backend — lean image (FastAPI + WeasyPrint).
|
||||||
# Не содержит Playwright/Chromium/Celery/Redis — только то что нужно для trade-in feature.
|
# Не содержит Playwright/Chromium/Celery/Redis — только то что нужно для trade-in feature.
|
||||||
|
#
|
||||||
|
# Build context = tradein-mvp/ (uv workspace root), НЕ ./backend (#2137): образу нужны
|
||||||
|
# workspace-манифест (pyproject.toml + uv.lock) и packages/scraper-kit для editable install.
|
||||||
|
# Собирается через `dockerfile: backend/Dockerfile` (см. docker-compose*.yml +
|
||||||
|
# .forgejo/workflows/deploy-tradein.yml build-backend).
|
||||||
|
|
||||||
# ---- builder ----
|
# ---- builder ----
|
||||||
FROM python:3.12-slim AS builder
|
FROM python:3.12-slim AS builder
|
||||||
|
|
@ -17,18 +22,28 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
|
||||||
|
|
||||||
RUN pip install --no-cache-dir uv
|
RUN pip install --no-cache-dir uv
|
||||||
|
|
||||||
|
# WORKDIR = uv workspace root. backend/ и packages/* — члены workspace.
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY pyproject.toml ./
|
# Манифесты workspace + members сначала (кэшируемый слой зависимостей).
|
||||||
# NB: команда содержит `import lxml`-assert — это И bust'ит build-cache этого слоя
|
# packages/ копируем ДО uv sync целиком: editable-install scraper-kit требует
|
||||||
# (защита от stale-кэша, который однажды задеплоил образ без lxml), И валидирует,
|
# src/ на этапе резолва (hatchling билдит editable-wheel по pyproject + src).
|
||||||
# что зависимость реально установлена (иначе сборка падает громко, а не в рантайме).
|
COPY pyproject.toml uv.lock ./
|
||||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
COPY backend/pyproject.toml backend/pyproject.toml
|
||||||
uv sync --no-dev \
|
COPY packages/ packages/
|
||||||
&& /app/.venv/bin/python -c "import lxml; print('lxml', lxml.__version__)"
|
|
||||||
|
|
||||||
COPY app ./app
|
# uv sync --frozen ставит зависимости backend ВКЛЮЧАЯ scraper-kit (editable member,
|
||||||
COPY scripts ./scripts
|
# .pth → /app/packages/scraper-kit/src). --no-dev: без pytest/ruff.
|
||||||
|
# NB: команда содержит import-assert'ы — они И bust'ят build-cache этого слоя
|
||||||
|
# (защита от stale-кэша без нужной deps), И валидируют что зависимость реально
|
||||||
|
# установлена (сборка падает громко, а не в рантайме).
|
||||||
|
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||||
|
uv sync --frozen --no-dev \
|
||||||
|
&& /app/.venv/bin/python -c "import lxml; print('lxml', lxml.__version__)" \
|
||||||
|
&& /app/.venv/bin/python -c "import scraper_kit; print('scraper_kit', scraper_kit.__file__)"
|
||||||
|
|
||||||
|
COPY backend/app backend/app
|
||||||
|
COPY backend/scripts backend/scripts
|
||||||
|
|
||||||
|
|
||||||
# ---- runner ----
|
# ---- runner ----
|
||||||
|
|
@ -51,9 +66,15 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Runtime-layout сохраняем прежним (app в /app/app, scripts в /app/scripts), чтобы
|
||||||
|
# bind-mount'ы compose не менялись: ./backend/app:/app/app (dev hot-reload) и
|
||||||
|
# ../auth/roles.yaml:/app/auth/roles.yaml (prod, app/core/auth.py читает /app/auth/roles.yaml).
|
||||||
|
# backend = virtual-пакет (НЕ в site-packages) → import app идёт из CWD=/app.
|
||||||
|
# packages/ ОБЯЗАТЕЛЕН в рантайме: editable .pth ссылается на /app/packages/scraper-kit/src.
|
||||||
COPY --from=builder --chown=app:app /app/.venv /app/.venv
|
COPY --from=builder --chown=app:app /app/.venv /app/.venv
|
||||||
COPY --from=builder --chown=app:app /app/app /app/app
|
COPY --from=builder --chown=app:app /app/packages /app/packages
|
||||||
COPY --from=builder --chown=app:app /app/scripts /app/scripts
|
COPY --from=builder --chown=app:app /app/backend/app /app/app
|
||||||
|
COPY --from=builder --chown=app:app /app/backend/scripts /app/scripts
|
||||||
|
|
||||||
USER app
|
USER app
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,10 +25,14 @@ dependencies = [
|
||||||
"redis>=5.0.0", # async hot cache для /api/v1/search (Phase 3.2)
|
"redis>=5.0.0", # async hot cache для /api/v1/search (Phase 3.2)
|
||||||
"pyyaml>=6.0.0", # RBAC roles.yaml loader (app/core/auth.py)
|
"pyyaml>=6.0.0", # RBAC roles.yaml loader (app/core/auth.py)
|
||||||
"playwright>=1.45", # Playwright client для connect к tradein-browser (#905)
|
"playwright>=1.45", # Playwright client для connect к tradein-browser (#905)
|
||||||
# scraper-kit — internal package; подключается в шаге C (перенос core + docker-wiring #2137),
|
"scraper-kit", # internal workspace-package (#2137) — общие утилиты скрапперов;
|
||||||
# чтобы standalone backend docker-context (COPY pyproject.toml + uv sync) не ломался на build.
|
# резолвится из workspace (см. [tool.uv.sources]), не с PyPI.
|
||||||
|
# Docker-context = tradein-mvp root, uv sync ставит editable.
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[tool.uv.sources]
|
||||||
|
scraper-kit = { workspace = true }
|
||||||
|
|
||||||
[dependency-groups]
|
[dependency-groups]
|
||||||
dev = [
|
dev = [
|
||||||
"pytest>=8.0.0",
|
"pytest>=8.0.0",
|
||||||
|
|
|
||||||
|
|
@ -36,8 +36,10 @@ services:
|
||||||
|
|
||||||
backend:
|
backend:
|
||||||
build:
|
build:
|
||||||
context: ./backend
|
# Context = tradein-mvp root (uv workspace): образу нужен packages/scraper-kit
|
||||||
dockerfile: Dockerfile
|
# для editable install (#2137). Dockerfile лежит в backend/.
|
||||||
|
context: .
|
||||||
|
dockerfile: backend/Dockerfile
|
||||||
container_name: tradein-backend
|
container_name: tradein-backend
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
|
|
|
||||||
2
tradein-mvp/uv.lock
generated
2
tradein-mvp/uv.lock
generated
|
|
@ -1295,6 +1295,7 @@ dependencies = [
|
||||||
{ name = "python-multipart" },
|
{ name = "python-multipart" },
|
||||||
{ name = "pyyaml" },
|
{ name = "pyyaml" },
|
||||||
{ name = "redis" },
|
{ name = "redis" },
|
||||||
|
{ name = "scraper-kit" },
|
||||||
{ name = "segno" },
|
{ name = "segno" },
|
||||||
{ name = "selectolax" },
|
{ name = "selectolax" },
|
||||||
{ name = "sentry-sdk" },
|
{ name = "sentry-sdk" },
|
||||||
|
|
@ -1327,6 +1328,7 @@ requires-dist = [
|
||||||
{ name = "python-multipart", specifier = ">=0.0.9" },
|
{ name = "python-multipart", specifier = ">=0.0.9" },
|
||||||
{ name = "pyyaml", specifier = ">=6.0.0" },
|
{ name = "pyyaml", specifier = ">=6.0.0" },
|
||||||
{ name = "redis", specifier = ">=5.0.0" },
|
{ name = "redis", specifier = ">=5.0.0" },
|
||||||
|
{ name = "scraper-kit", editable = "packages/scraper-kit" },
|
||||||
{ name = "segno", specifier = ">=1.6.0" },
|
{ name = "segno", specifier = ">=1.6.0" },
|
||||||
{ name = "selectolax", specifier = ">=0.3.0" },
|
{ name = "selectolax", specifier = ">=0.3.0" },
|
||||||
{ name = "sentry-sdk", specifier = ">=2.0.0" },
|
{ name = "sentry-sdk", specifier = ">=2.0.0" },
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue