# «Контракт-чек» — everyday commands (uv + docker) # Usage: make (see `make help`) .PHONY: help install lint lint-fix isort isort-check typecheck test test-unit test-integration migrate \ infra-up infra-down infra-logs services-up services-down services-logs \ api api-logs bot bot-logs worker-extract worker-analyze worker-notify \ seed-token jwt-secret jwt-token jwt-verify health shell-api shell-bot \ shell-db admin-promote admin-list clean # ───────────────────────────────────────────────────────────────────────────── # Help # ───────────────────────────────────────────────────────────────────────────── help: ## Show available commands @echo "Usage: make " @grep -E '^[a-zA-Z0-9_-]+:.*##' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*##"}; {printf " \033[36m%-18s\033[0m %s\n", $$1, $$2}' # ───────────────────────────────────────────────────────────────────────────── # Local dev (uv) # ───────────────────────────────────────────────────────────────────────────── install: ## Sync dev dependencies (uv) uv sync --group dev lint: ## Run ruff linter + format check uv run ruff check src tests uv run ruff format --check src tests lint-fix: ## Run ruff autofix + format + isort fix uv run ruff check --fix src tests uv run ruff format src tests uv run isort src tests isort: ## Run isort (sort imports in-place) uv run isort src tests isort-check: ## Run isort in check-only mode uv run isort --check-only src tests typecheck: ## Run ty type checker uv run ty check src test: ## Run all tests (unit + integration) uv run pytest test-unit: ## Run unit tests only (fast) uv run pytest -m "not integration" test-integration: ## Run integration tests (needs docker infra) uv run pytest -m integration # ───────────────────────────────────────────────────────────────────────────── # Docker: infrastructure (postgres + redis + rabbitmq + minio) # ───────────────────────────────────────────────────────────────────────────── infra-up: ## Start infra containers docker compose up -d infra-down: ## Stop infra containers docker compose down infra-logs: ## Tail infra logs docker compose logs -f # ───────────────────────────────────────────────────────────────────────────── # Docker: all services (api + workers + bot) # ───────────────────────────────────────────────────────────────────────────── services-up: ## Start all services (needs infra running) docker compose --profile services up -d --build --remove-orphans services-down: ## Stop all services docker compose --profile services down services-logs: ## Tail all service logs docker compose --profile services logs -f services-ps: ## Show running containers docker compose --profile services ps # ───────────────────────────────────────────────────────────────────────────── # Individual services # ───────────────────────────────────────────────────────────────────────────── api: ## Start/restart API service docker compose --profile services up -d --build --remove-orphans api api-logs: ## Tail API logs docker compose logs -f api bot: ## Start/restart Telegram bot docker compose --profile services up -d --build --remove-orphans bot bot-logs: ## Tail bot logs docker compose logs -f bot worker-extract: ## Start/restart extract worker docker compose --profile services up -d --build --remove-orphans worker-extract worker-analyze: ## Start/restart analyze worker docker compose --profile services up -d --build --remove-orphans worker-analyze worker-analyze-logs: ## Tail analyze worker logs docker compose logs -f worker-analyze worker-prescreen: ## Start/restart prescreen worker docker compose --profile services up -d --build --remove-orphans worker-prescreen worker-prescreen-logs: ## Tail prescreen worker logs docker compose logs -f worker-prescreen worker-notify: ## Start/restart notify worker docker compose --profile services up -d --build --remove-orphans worker-notify worker-notify-logs: ## Tail notify worker logs docker compose logs -f worker-notify # ───────────────────────────────────────────────────────────────────────────── # Database # ───────────────────────────────────────────────────────────────────────────── migrate: ## Run Alembic migrations (inside api container) docker compose --profile services build api docker compose --profile services run --rm api alembic upgrade head shell-db: ## Open psql inside postgres container docker compose exec postgres psql -U contract_check -d contract_check # ───────────────────────────────────────────────────────────────────────────── # Admin panel (/admin — manage users; needs role = 'admin') # ───────────────────────────────────────────────────────────────────────────── admin-promote: ## Grant admin role to a user (usage: make admin-promote EMAIL=a@b.c) @if [ -z "$(EMAIL)" ]; then \ echo "Usage: make admin-promote EMAIL=a@b.c"; \ exit 1; \ fi @docker compose exec -T postgres psql -U contract_check -d contract_check \ -c "UPDATE users SET role = 'admin' WHERE email = '$(EMAIL)';" \ -c "SELECT id, email, role FROM users WHERE email = '$(EMAIL)';" admin-list: ## List current admin users @docker compose exec -T postgres psql -U contract_check -d contract_check \ -c "SELECT id, email, telegram_id, role, is_active FROM users WHERE role = 'admin';" # ───────────────────────────────────────────────────────────────────────────── # Auth / tokens # ───────────────────────────────────────────────────────────────────────────── seed-token: ## Generate bot service token (prints bearer token) docker compose --profile services exec api python -m contract_check.api seed-token bot-prod bot jwt-secret: ## Generate a fresh JWT_SECRET for .env @openssl rand -hex 32 jwt-token: ## Exchange a telegram_id for a user JWT (usage: make jwt-token TG_ID=123456) @if [ -z "$(TG_ID)" ]; then \ echo "Usage: make jwt-token TG_ID=123456"; \ exit 1; \ fi @TOKEN=$$(grep -E '^BOT_SERVICE_TOKEN=' .env | cut -d= -f2); \ if [ -z "$$TOKEN" ]; then \ echo "BOT_SERVICE_TOKEN not found in .env"; \ exit 1; \ fi; \ curl -s -X POST -H "Authorization: Bearer $$TOKEN" \ -H "Content-Type: application/json" \ -d '{"telegram_id":$(TG_ID)}' \ http://localhost:8000/api/v1/auth/telegram/bot | jq . jwt-verify: ## Introspect a user JWT (usage: make jwt-verify JWT=eyJ...) @if [ -z "$(JWT)" ]; then \ echo "Usage: make jwt-verify JWT=eyJ..."; \ exit 1; \ fi @curl -s -H "Authorization: Bearer $(JWT)" \ http://localhost:8000/api/v1/auth/me | jq . # ───────────────────────────────────────────────────────────────────────────── # Health / diagnostics # ───────────────────────────────────────────────────────────────────────────── health: ## Check API health endpoint @echo "API health:" @curl -s http://localhost:8000/healthz | jq . 2>/dev/null || curl -s http://localhost:8000/healthz @echo "" @echo "RabbitMQ: http://localhost:15672 (guest/guest → contract_check/contract_check)" @echo "MinIO: http://localhost:9001 (contract_check/contract_check)" @echo "Postgres: localhost:15432 (contract_check/contract_check)" shell-api: ## Open shell inside API container docker compose --profile services exec api /bin/sh shell-bot: ## Open shell inside bot container docker compose --profile services exec bot /bin/sh # ───────────────────────────────────────────────────────────────────────────── # Cleanup # ───────────────────────────────────────────────────────────────────────────── clean: ## Remove containers, volumes, caches docker compose --profile services down -v docker compose down -v rm -rf .mypy_cache .pytest_cache .ruff_cache uv cache clean # ───────────────────────────────────────────────────────────────────────────── # Full workflow shortcuts # ───────────────────────────────────────────────────────────────────────────── dev: install infra-up migrate services-up ## Bootstrap full dev environment stop: services-down infra-down ## Stop everything