# Команды разработки arm-core. Backend — api/.venv; запуск из корня репозитория. VENV := api/.venv BIN := $(CURDIR)/$(VENV)/bin STATEMENTS_DIR ?= ../pylib_ai_arm_statements # Тег выпуска библиотеки — по версии, закреплённой в api/requirements.txt STATEMENTS_TAG ?= v$(shell sed -n 's/^pylib_ai_arm_statements==//p' api/requirements.txt) COMPOSE_FILE ?= ../docs/dev/docker-compose.yml # DBML относительно api/: и в основном workspace, и в worktree .wt/<срез>/ это соседний docs/ DBML ?= ../../docs/model/data-model-v5.23.dbml .PHONY: venv install statements-version lint test test-integration e2e dbml-check migration-cycle check check-infra docker-build web-check check-full up migrate seed seed-dev # Сверка checkout библиотеки с версией из api/requirements.txt (pylib_ai_arm_statements==<версия>): VERSION checkout # не равен закреплённой — ошибка; checkout не на теге v<версия> — предупреждение (правка библиотеки до выпуска). # docker-build требует тег строго. statements-version: @ver=$$(cat "$(STATEMENTS_DIR)/VERSION" 2>/dev/null) || \ { echo "Ошибка: нет $(STATEMENTS_DIR)/VERSION — клонируйте RSHB/pylib_ai_arm_statements рядом или задайте STATEMENTS_DIR" >&2; exit 1; }; \ [ "v$$ver" = "$(STATEMENTS_TAG)" ] || \ { echo "Ошибка: в $(STATEMENTS_DIR) версия $$ver, в api/requirements.txt — $(STATEMENTS_TAG:v%=%)" >&2; exit 1; }; \ release=$$(git -C "$(STATEMENTS_DIR)" rev-parse -q --verify "refs/tags/$(STATEMENTS_TAG)^{commit}"); \ [ -n "$$release" ] && [ "$$release" = "$$(git -C "$(STATEMENTS_DIR)" rev-parse HEAD)" ] || \ echo "Предупреждение: $(STATEMENTS_DIR) не на теге $(STATEMENTS_TAG) — ставится рабочее дерево библиотеки" # Python 3.11 (версия платформы); пропускаем внутренние raisa_* и устанавливаемые локально pylib_ai* venv: statements-version cd api && uv venv --python 3.11 --allow-existing .venv cd api && grep -Ev '^(raisa_|pylib_ai)' requirements.txt | uv pip install --python .venv/bin/python -r - cd api && grep -v '^-r' requirements-dev.txt | uv pip install --python .venv/bin/python -r - uv pip install --python "$(BIN)/python" --reinstall-package pylib-ai-arm-statements "$(STATEMENTS_DIR)" # Установить или переустановить Python-пакет из соседнего репозитория в окружение backend. install: statements-version uv venv --python 3.11 --allow-existing "$(VENV)" uv pip install --python "$(BIN)/python" --reinstall-package pylib-ai-arm-statements "$(STATEMENTS_DIR)" lint: cd api && $(BIN)/ruff check . cd api && $(BIN)/ruff format --check . cd api && $(BIN)/mypy src scripts test: cd api && $(BIN)/pytest -m "not integration" # e2e (профиль services, реальный tabular-parser) идёт отдельной целью `e2e`, поэтому здесь исключён test-integration: cd api && $(BIN)/pytest -m "integration and not e2e" # Сквозной прогон загрузки ОСВ (Срез 2c): нужны compose-инфраструктура и сервис tabular-parser из профиля `services` # (README, «Сквозной прогон (e2e)»); без профиля тест пропускается с причиной «профиль services не поднят», код 0 e2e: cd api && $(BIN)/pytest -m e2e -rs # Сверка ORM с DBML (spec data-model): пустой вывод и код 0 — совпадение 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. Входит в test-integration, отдельно запускается для быстрой проверки миграций migration-cycle: cd api && $(BIN)/pytest -m integration tests/test_migrations.py check: lint test # Быстрая проверка доступности PostgreSQL и NATS из api/.env.test (порты compose); иначе — подсказка поднять инфраструктуру check-infra: cd api && $(BIN)/python scripts/check_infra.py # Сборка образа из корня репозитория (Dockerfile — бэкенд) docker-build: @release=$$(git -C "$(STATEMENTS_DIR)" rev-parse --verify "refs/tags/$(STATEMENTS_TAG)^{commit}") || \ { echo "Ошибка: в библиотеке отсутствует тег $(STATEMENTS_TAG); выполните git fetch --tags в $(STATEMENTS_DIR)" >&2; exit 1; }; \ head=$$(git -C "$(STATEMENTS_DIR)" rev-parse HEAD) || exit 1; \ [ "$$head" = "$$release" ] || \ { echo "Ошибка: HEAD библиотеки не совпадает с $(STATEMENTS_TAG)" >&2; exit 1; } docker build --build-context "statements=$(STATEMENTS_DIR)" -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), поэтому отдельным шагом не гоняется: второй запуск только удлинил бы прогон. e2e — после # test-integration; без профиля `services` пропускается (не падает) check-full: check dbml-check check-infra test-integration e2e docker-build web-check up: docker compose -f $(COMPOSE_FILE) up -d migrate: cd api && $(BIN)/alembic upgrade head seed: cd api && $(BIN)/python -m scripts.seed seed-dev: cd api && $(BIN)/python -m scripts.seed --dev