269 lines
15 KiB
Makefile
269 lines
15 KiB
Makefile
# «Контракт-чек» — everyday commands (uv + docker)
|
|
# Usage: make <target> (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 \
|
|
services-obs obs-up obs-down obs-logs obs-url obs-reset \
|
|
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 <target>"
|
|
@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-cov: ## Run unit tests with coverage report (enforces threshold)
|
|
uv run pytest --cov=src/contract_check --cov-branch --cov-report=term-missing --cov-report=html --cov-fail-under=59 -m "not integration" tests/unit
|
|
|
|
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
|
|
|
|
services-obs: ## Start services + Grafana/Loki/Prometheus observability
|
|
docker compose --profile services --profile obs up -d --build --remove-orphans
|
|
|
|
services-observer: ## Start services + OpenObserve collector stack
|
|
docker compose --profile services --profile observer up -d --build --remove-orphans
|
|
|
|
services-nginx: ## Start with nginx reverse proxy
|
|
docker compose --profile services --profile edge up -d --build --remove-orphans
|
|
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
# Docker: observability (Grafana + Loki logs)
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
obs-up: ## Start Grafana/Loki/Prometheus containers
|
|
docker compose --profile obs up -d --build --remove-orphans
|
|
|
|
obs-down: ## Stop Grafana/Loki/Prometheus containers
|
|
docker compose --profile obs down
|
|
|
|
obs-logs: ## Tail Grafana/Loki/Prometheus containers logs
|
|
docker compose --profile obs logs -f
|
|
|
|
obs-url: ## Print Grafana URL and default credentials
|
|
@echo "Direct: http://localhost:$${GRAFANA_PORT:-3000}"
|
|
@echo "Via nginx: $${GRAFANA_ROOT_URL:-http://localhost}/grafana/"
|
|
@echo "User: $${GRAFANA_ADMIN_USER:-admin}"
|
|
@echo "Password: $${GRAFANA_ADMIN_PASSWORD:-admin}"
|
|
@echo "Dashboard: $${GRAFANA_ROOT_URL:-http://localhost}/grafana/d/contract-check-logs"
|
|
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
# Docker: OpenObserve collector stack
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
observer-up: ## Start OpenObserve + otel-collector containers
|
|
docker compose --profile observer up -d --build --remove-orphans
|
|
|
|
observer-down: ## Stop OpenObserve + otel-collector containers
|
|
docker compose --profile observer down
|
|
|
|
observer-logs: ## Tail OpenObserve + otel-collector containers logs
|
|
docker compose --profile observer logs -f
|
|
|
|
obs-reset: ## Reset Grafana and Loki volumes (wipes dashboards/logs data)
|
|
docker compose --profile obs down -v
|
|
rm -rf deploy/observability/grafana/dashboards/*.json.tmp
|
|
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
# Docker: nginx edge (reverse proxy)
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
nginx-up: ## Start nginx
|
|
docker compose --profile edge up -d --build --remove-orphans
|
|
|
|
nginx-down: ## Stop nginx
|
|
docker compose --profile edge down
|
|
|
|
nginx-logs: ## Tail nginx logs
|
|
docker compose --profile edge logs -f
|
|
|
|
nginx-ps: ## Show running containers
|
|
docker compose --profile edge 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 src.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 .pytest_cache .ruff_cache
|
|
uv cache clean
|
|
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
# Full workflow shortcuts
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
dev: install infra-up migrate services-up ## Bootstrap full dev environment
|
|
|
|
dev-obs: install infra-up migrate services-obs ## Bootstrap full dev environment with observability
|
|
|
|
stop: services-down infra-down ## Stop everything
|
|
|
|
stop-obs: obs-down services-down infra-down ## Stop everything including observability
|