From 81bb79e600c1b86ea51ffabc0db810892801964c Mon Sep 17 00:00:00 2001 From: Andrey Epifancev Date: Sun, 4 Oct 2026 00:58:57 +0400 Subject: [PATCH] =?UTF-8?q?feat:=20make=20check-full=20=E2=80=94=20check,?= =?UTF-8?q?=20dbml-check,=20=D0=B8=D0=BD=D1=82=D0=B5=D0=B3=D1=80=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D0=BE=D0=BD=D0=BD=D1=8B=D0=B5=20=D1=82=D0=B5=D1=81?= =?UTF-8?q?=D1=82=D1=8B=20=D0=BF=D1=80=D0=BE=D1=82=D0=B8=D0=B2=20compose,?= =?UTF-8?q?=20docker=20build,=20web;=20.env.test=20=D0=BD=D0=B0=20=D0=BF?= =?UTF-8?q?=D0=BE=D1=80=D1=82=D1=8B=20compose?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Цели docker-build, web-check, check-infra (подсказка «make up»); .env.test переведён на 5432/4222/9000 (R-19), test_config и README обновлены. Цикл миграций входит в test-integration и отдельным шагом не дублируется. Co-Authored-By: Claude Fable 5.1 --- Makefile | 25 +++++++++++++++++++---- README.md | 13 ++++++------ api/.env.test | 9 ++++---- api/scripts/check_infra.py | 42 ++++++++++++++++++++++++++++++++++++++ api/tests/test_config.py | 6 +++--- 5 files changed, 78 insertions(+), 17 deletions(-) create mode 100644 api/scripts/check_infra.py diff --git a/Makefile b/Makefile index b0d16b5..6acc5e2 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ COMPOSE_FILE ?= ../docs/dev/docker-compose.yml # DBML относительно api/: и в основном workspace, и в worktree .wt/<срез>/ это соседний docs/ DBML ?= ../../docs/model/data-model-v5.13.dbml -.PHONY: venv lint test test-integration dbml-check migration-cycle check check-full up migrate seed seed-dev +.PHONY: venv lint test test-integration dbml-check migration-cycle check check-infra docker-build web-check check-full up migrate seed seed-dev # Python 3.11 (версия платформы); внутренние пакеты raisa_* вне банка недоступны — пропускаем их venv: @@ -29,14 +29,31 @@ dbml-check: cd api && $(BIN)/python scripts/check_dbml_vs_orm.py $(DBML) # Миграции на временной БД (spec data-model): upgrade head -> downgrade base -> upgrade head, пустой autogenerate, -# схема после миграции = create_all ORM. Подключается в check-full (задача 25) +# схема после миграции = create_all ORM. Входит в test-integration, отдельно запускается для быстрой проверки миграций migration-cycle: cd api && $(BIN)/pytest -m integration tests/test_migrations.py check: lint test -# TODO (задача 25): добавить фронт (lint/test/build web/), проверку миграций с нуля и откат, актуальность OpenAPI -check-full: check dbml-check test-integration +# Быстрая проверка доступности PostgreSQL и NATS из api/.env.test (порты compose); иначе — подсказка поднять инфраструктуру +check-infra: + cd api && $(BIN)/python scripts/check_infra.py + +# Сборка образа из корня репозитория (Dockerfile — бэкенд) +docker-build: + docker build -t arm-core . + +# Фронт: установка зависимостей (raisa-* без Nexus пропускаются как optionalDependencies), biome, типы, сборка +web-check: + cd web && npm install + cd web && npx biome check src + cd web && npx tsc --noEmit + cd web && npm run build + +# Полная проверка перед PR. Порядок: быстрые без БД (check, dbml-check), затем БД/NATS из compose (test-integration), +# затем docker, затем web. Цикл миграций upgrade -> downgrade -> upgrade на чистой БД входит в test-integration +# (tests/test_migrations.py), поэтому отдельным шагом не гоняется: второй запуск только удлинил бы прогон +check-full: check dbml-check check-infra test-integration docker-build web-check up: docker compose -f $(COMPOSE_FILE) up -d diff --git a/README.md b/README.md index ce062b9..68e4fc4 100644 --- a/README.md +++ b/README.md @@ -246,9 +246,11 @@ docker compose -f ../docs/dev/docker-compose.yml down -v # полный сб | `make dbml-check` | сверка ORM с `../docs/model/data-model-v5.13.dbml` | | `make migration-cycle` | миграции на временной БД: `upgrade head` → `downgrade base` → `upgrade head`, пустой autogenerate | | `make check` | быстрая проверка без Docker: `lint` + `test` | -| `make check-full` | `check` + `dbml-check` + `test-integration`; выполняется перед PR (нужна поднятая инфраструктура) | +| `make docker-build` | сборка образа: `docker build -t arm-core .` | +| `make web-check` | фронт: `npm install`, `biome check src`, `tsc --noEmit`, `npm run build` | +| `make check-infra` | быстрая проверка, что PostgreSQL и NATS из compose доступны (иначе: `make up`) | +| `make check-full` | полная проверка перед PR: `check` + `dbml-check` + `check-infra` + `test-integration` (в нём цикл миграций) + `docker-build` + `web-check`; нужна поднятая инфраструктура (`make up`) и Docker | -`make check-full` пока не включает проверки фронта, OpenAPI и откат миграций отдельным шагом (задача 25 среза). ### Тесты @@ -256,10 +258,9 @@ docker compose -f ../docs/dev/docker-compose.yml down -v # полный сб - **Интеграционные** (`make test-integration`) требуют PostgreSQL, тесты обмена через NATS — ещё и NATS. Рабочую БД `armka` они не трогают: на каждую сессию pytest создаётся свежая БД `armcore_pytest_`, мигрируется `alembic` и удаляется в конце. Параметры подключения берутся из `api/.env.test` (`pytest.ini` задаёт `ENV_FILE=.env.test`). - Сейчас этот файл указывает на временную тестовую инфраструктуру (PostgreSQL `55432`, NATS `54222`, MinIO `59000`), - а не на стандартные порты compose: чтобы гонять интеграционные тесты против `make up`, поправьте порты в - `api/.env.test` на `5432`, `4222`, `9000` (не коммитьте это изменение без согласования). То же относится к - `make migration-cycle` и `make check-full`: они тоже читают `.env.test` через `pytest.ini`. + Файл указывает на стандартные порты и учётные данные compose из `../docs/dev` (PostgreSQL `5432`, NATS `4222`, + MinIO `9000`), поэтому после `make up` тесты работают «из коробки». То же относится к `make migration-cycle` и + `make check-full`: они тоже читают `.env.test` через `pytest.ini`. - **Реальные данные** — репозиторий `../fixtures/` (путь можно задать переменной `ARM_KA_FIXTURES`). Тесты с маркером `fixtures` без каталога пропускаются с понятной причиной. diff --git a/api/.env.test b/api/.env.test index fe6f5cb..0d3b09f 100644 --- a/api/.env.test +++ b/api/.env.test @@ -1,18 +1,19 @@ # Окружение тестов (pytest.ini: ENV_FILE=.env.test). Только тестовые значения, секретов здесь нет. -# Порты — временная тестовая инфраструктура: PostgreSQL 55432, NATS 54222, MinIO 59000. +# Порты и учётные данные — стандартные для docs/dev/docker-compose.yml (PostgreSQL 5432, NATS 4222, MinIO 9000): +# после `make up` тесты работают без правок. Рабочую БД тесты не трогают (создают armcore_pytest_). DEBUG=true -OPENBAO__DATABASE__DATABASE_URL=postgresql+asyncpg://armka:armka@localhost:55432/armka +OPENBAO__DATABASE__DATABASE_URL=postgresql+asyncpg://armka:armka@localhost:5432/armka -OPENBAO__MINIO__MINIO_URL=localhost:59000 +OPENBAO__MINIO__MINIO_URL=localhost:9000 OPENBAO__MINIO__MINIO_ADMIN_LOGIN=minioadmin OPENBAO__MINIO__MINIO_ADMIN_PASSWORD=minioadmin OPENBAO__MINIO__MINIO_BUCKET=arm-ka # false — MinIO по http (docker compose); по умолчанию true (https, как на платформе) OPENBAO__MINIO__MINIO_SECURE=false -OPENBAO__NATS__NATS_URL=nats://localhost:54222 +OPENBAO__NATS__NATS_URL=nats://localhost:4222 OPENBAO__NATS__NATS_SEED= OPENBAO__NATS__NATS_JWT= diff --git a/api/scripts/check_infra.py b/api/scripts/check_infra.py new file mode 100644 index 0000000..839720e --- /dev/null +++ b/api/scripts/check_infra.py @@ -0,0 +1,42 @@ +"""Быстрая проверка доступности PostgreSQL и NATS из `.env.test` (порты docker-compose из docs/dev). + +Нужна `make check-full`, чтобы вместо длинного трейсбека pytest сразу подсказать: «поднимите инфраструктуру: make up». +Только TCP-подключение, без аутентификации; коды: 0 — доступны, 1 — недоступны. +""" + +import socket +import sys +from pathlib import Path +from urllib.parse import urlparse + +from dotenv import dotenv_values + +ENV_FILE = Path(__file__).resolve().parent.parent / ".env.test" +KEYS = ("OPENBAO__DATABASE__DATABASE_URL", "OPENBAO__NATS__NATS_URL") + + +def unreachable(urls: list[str]) -> list[str]: + """Адреса host:port, к которым не удалось подключиться.""" + bad: list[str] = [] + for url in urls: + parsed = urlparse(url) + host, port = parsed.hostname or "localhost", parsed.port or 0 + try: + with socket.create_connection((host, port), timeout=3): + pass + except OSError: + bad.append(f"{host}:{port}") + return bad + + +def main() -> int: + env = dotenv_values(ENV_FILE) + bad = unreachable([env[key] or "" for key in KEYS]) + if bad: + print(f"Инфраструктура недоступна ({', '.join(bad)}): поднимите её командой make up", file=sys.stderr) + return 1 + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/api/tests/test_config.py b/api/tests/test_config.py index c4be000..22f3f05 100644 --- a/api/tests/test_config.py +++ b/api/tests/test_config.py @@ -20,10 +20,10 @@ def clean_env(monkeypatch: pytest.MonkeyPatch) -> pytest.MonkeyPatch: def test_env_test_is_read(clean_env: pytest.MonkeyPatch) -> None: - """.env.test читается: порты временной тестовой инфраструктуры.""" + """.env.test читается: стандартные порты docker-compose из docs/dev.""" s = Settings(_env_file=API_DIR / ".env.test") # type: ignore[call-arg] - assert s.OPENBAO.DATABASE.DATABASE_URL.endswith("localhost:55432/armka") - assert s.OPENBAO.NATS.NATS_URL == "nats://localhost:54222" + assert s.OPENBAO.DATABASE.DATABASE_URL.endswith("localhost:5432/armka") + assert s.OPENBAO.NATS.NATS_URL == "nats://localhost:4222" assert s.AUTH_DEV_ISSUER is True assert s.NATS_ENABLED is False assert s.OPENBAO.MINIO.MINIO_SECURE is False