# Команды разработки scan-gateway. Запуск из корня репозитория; рецепты сами переходят в api/ (как и в arm-core), # поэтому backend-команды работают с каталогом api/ и окружением api/.venv. VENV := api/.venv BIN := $(CURDIR)/$(VENV)/bin # docs/dev — соседний репозиторий и в основном workspace, и в worktree .wt/<срез>/ COMPOSE_FILE ?= ../docs/dev/docker-compose.yml COMPOSE_PROJECT ?= arm-ka IMAGE ?= scan-gateway:dev STATEMENTS_DIR ?= ../pylib_ai_arm_statements # Тег выпуска библиотеки — по версии, закреплённой в api/requirements.txt STATEMENTS_TAG ?= v$(shell sed -n 's/^pylib_ai_arm_statements==//p' api/requirements.txt) .PHONY: help venv install statements-version lint test test-integration check docker-build check-full up emulator golden-update help: @echo "venv - окружение api/.venv (Python 3.11) с зависимостями и локальной библиотекой arm_statements" @echo "install - установить или переустановить локальную библиотеку arm_statements" @echo "statements-version - сверить checkout библиотеки (STATEMENTS_DIR) с версией в api/requirements.txt" @echo "lint - ruff check, ruff format --check, mypy src" @echo "test - pytest без интеграционных тестов" @echo "test-integration - интеграционные тесты (нужны NATS и MinIO: make up)" @echo "check - lint + test" @echo "docker-build - собрать docker-образ $(IMAGE) (контекст — корень репозитория)" @echo "check-full - check + test-integration + docker-build (по порядку, до первой ошибки)" @echo "up - поднять NATS/MinIO/PostgreSQL общим compose-проектом arm-ka и создать бакет (minio-init)" @echo "emulator - запустить эмулятор ИС Сканирование (python -m src.scan_emulator)" @echo "golden-update - пересобрать эталоны нормализатора ../fixtures/ocr/expected_normalize/ (diff смотреть в fixtures)" # Сверка 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)" # Установить или переустановить библиотеку в окружение 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 test: cd api && $(BIN)/pytest -m "not integration" test-integration: cd api && $(BIN)/pytest -m integration check: lint test # Образ собирается без Nexus (raisa_* в образ не ставятся, см. Dockerfile). Тесты в образе не запускаются: # tests/ в нём есть, но api/.env.test исключён через .dockerignore, поэтому pytest внутри контейнера не пройдёт. 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 $(IMAGE) . # Полная проверка перед PR. Шаги вызываются последовательно через $(MAKE), а не как пререквизиты: # так порядок check -> test-integration -> docker-build и остановка на первой ошибке гарантированы и при make -j. check-full: $(MAKE) check $(MAKE) test-integration $(MAKE) docker-build # Общий compose-проект workspace (arm-ka): его используют и другие сервисы, поэтому целей down/stop/restart нет. # --wait — только со списком долгоживущих сервисов: одноразовый minio-init завершается кодом 0, и compose считает это сбоем. # Поэтому бакет создаётся отдельным шагом: `run --rm minio-init` (идемпотентно: `mc mb --ignore-existing`; на свежем # томе без него интеграционные тесты падают на NoSuchBucket). Код выхода шага пробрасывается в make. up: docker compose -f $(COMPOSE_FILE) --project-name $(COMPOSE_PROJECT) up -d --wait postgres nats minio docker compose -f $(COMPOSE_FILE) --project-name $(COMPOSE_PROJECT) run --rm minio-init # Эмулятор ИС Сканирование (параметры — SCAN_HOTFOLDER_PATH, SCAN_FIXTURES_DIR, SCAN_EMULATOR_DELAY из api/.env) emulator: cd api && $(BIN)/python -m src.scan_emulator # Эталоны нормализатора на реальных ответах ИС: пишет ../fixtures/ocr/expected_normalize/.json; diff смотреть в fixtures golden-update: cd api && $(BIN)/python -m tests.golden_update