# Makefile for Routstr Proxy # Detect if we're in a virtual environment VENV_EXISTS := $(shell test -d .venv && echo 1) ifeq ($(VENV_EXISTS), 1) PYTHON := .venv/bin/python PYTEST := .venv/bin/pytest RUFF := .venv/bin/ruff MYPY := .venv/bin/mypy ALEMBIC := .venv/bin/alembic else PYTHON := python PYTEST := pytest RUFF := ruff MYPY := mypy ALEMBIC := alembic endif .PHONY: help setup test test-unit test-integration test-integration-docker test-all test-fast test-performance clean docker-up docker-down lint format type-check dev-setup check-deps db-upgrade db-downgrade db-current db-history db-migrate db-revision db-heads db-clean ui-build ui-build-docker ui-dev # Default target help: @echo "Available targets:" @echo " make test - Run all tests (unit + integration with mocks)" @echo " make test-unit - Run unit tests only" @echo " make test-integration - Run integration tests with mocks (fast)" @echo " make test-integration-docker - Run integration tests with Docker services" @echo " make test-all - Run all tests including Docker integration" @echo " make test-fast - Run fast tests only (skip slow tests)" @echo " make test-performance - Run performance tests" @echo " make docker-up - Start Docker test services" @echo " make docker-down - Stop Docker test services" @echo " make clean - Clean up test artifacts and caches" @echo " make lint - Run linting checks" @echo " make format - Format code with ruff" @echo " make type-check - Run mypy type checking" @echo " make dev-setup - Set up development environment" @echo " make check-deps - Check system dependencies" @echo " make setup - First-time project setup" @echo "" @echo "UI targets:" @echo " make ui-build - Build UI for production (static export)" @echo " make ui-build-docker - Build UI using Docker (no Node.js needed)" @echo " make ui-dev - Start UI development server" @echo "" @echo "Docker UI build requires only Docker, no local Node.js installation needed." @echo "Database migration shortcuts:" @echo " make create-migration - Auto-generate new migration" @echo " make db-upgrade - Apply all pending migrations" @echo " make db-downgrade - Downgrade one migration" # First-time setup setup: check-deps dev-setup @echo "" @echo "๐ŸŽ‰ Setup complete! Next steps:" @echo " 1. Run tests: make test" @echo " 2. Run integration: make test-integration-docker" @echo " 3. Start developing!" # Test targets test: test-unit test-integration test-unit: @echo "๐Ÿงช Running unit tests..." $(PYTEST) tests/unit/ -v test-integration: @echo "๐ŸŽญ Running integration tests with mocks..." $(PYTEST) tests/integration/ -v test-integration-docker: @echo "๐Ÿณ Running integration tests with Docker services..." ./tests/run_integration.py test-all: test-unit test-integration-docker test-fast: @echo "โšก Running fast tests only..." $(PYTEST) -m "not slow and not requires_docker" -v test-performance: @echo "๐Ÿ“Š Running performance tests..." $(PYTEST) tests/integration/ -m "performance" -v -s # Docker management docker-up: @echo "๐Ÿš€ Starting Docker test services..." docker-compose -f compose.testing.yml up -d @echo "Waiting for services to be ready..." @sleep 5 @echo "Services started. Run 'make test-integration-docker' to test." docker-down: @echo "๐Ÿ›‘ Stopping Docker test services..." docker-compose -f compose.testing.yml down -v # Code quality lint: @echo "๐Ÿ” Running linting checks..." $(RUFF) check . $(MYPY) . format: @echo "โœจ Formatting code..." $(RUFF) format . $(RUFF) check --fix . type-check: @echo "๐Ÿ”Ž Running type checks..." $(MYPY) . # Development setup dev-setup: @echo "๐Ÿ”ง Setting up development environment..." @# Check if uv is installed @if ! command -v uv >/dev/null 2>&1; then \ echo "๐Ÿ“ฆ uv not found. Installing uv..."; \ if command -v curl >/dev/null 2>&1; then \ curl -LsSf https://astral.sh/uv/install.sh | sh; \ elif command -v pip >/dev/null 2>&1; then \ pip install uv; \ else \ echo "โŒ Neither curl nor pip found. Please install uv manually:"; \ echo " Visit https://docs.astral.sh/uv/getting-started/installation/"; \ exit 1; \ fi; \ echo "โœ… uv installed successfully!"; \ else \ echo "โœ… uv is already installed (version: $$(uv --version))"; \ fi uv sync --dev uv pip install -e . @echo "โœ… Development environment ready!" # Check dependencies check-deps: @echo "๐Ÿ” Checking system dependencies..." @echo "" @echo "Core tools:" @printf " %-18s" "Python:"; if command -v python >/dev/null 2>&1; then python --version; else echo "โŒ Not found"; fi @printf " %-18s" "uv:"; if command -v uv >/dev/null 2>&1; then uv --version; else echo "โŒ Not found - run 'make dev-setup' to install"; fi @printf " %-18s" "Docker:"; if command -v docker >/dev/null 2>&1; then docker --version; else echo "โš ๏ธ Not found (optional, needed for integration tests)"; fi @printf " %-18s" "Docker Compose:"; if command -v docker-compose >/dev/null 2>&1; then docker-compose --version; else echo "โš ๏ธ Not found (optional, needed for integration tests)"; fi @echo "" @echo "Development tools:" @printf " %-18s" "pytest:"; if $(PYTEST) --version >/dev/null 2>&1; then $(PYTEST) --version | head -1; else echo "โŒ Not found - run 'make dev-setup'"; fi @printf " %-18s" "ruff:"; if $(RUFF) --version >/dev/null 2>&1; then $(RUFF) --version; else echo "โŒ Not found - run 'make dev-setup'"; fi @printf " %-18s" "mypy:"; if $(MYPY) --version >/dev/null 2>&1; then $(MYPY) --version; else echo "โŒ Not found - run 'make dev-setup'"; fi @printf " %-18s" "alembic:"; if $(ALEMBIC) --version >/dev/null 2>&1; then $(ALEMBIC) --version; else echo "โŒ Not found - run 'make dev-setup'"; fi @echo "" @echo "Virtual environment:" @if [ -d ".venv" ]; then \ echo " โœ… .venv exists"; \ echo " Python: $$(.venv/bin/python --version)"; \ else \ echo " โŒ .venv not found - run 'make dev-setup'"; \ fi @echo "" @echo "To set up missing dependencies, run: make dev-setup" # Cleanup clean: @echo "๐Ÿงน Cleaning up..." find . -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true find . -type d -name ".pytest_cache" -exec rm -rf {} + 2>/dev/null || true find . -type d -name ".mypy_cache" -exec rm -rf {} + 2>/dev/null || true find . -type f -name "*.pyc" -delete find . -type f -name ".coverage" -delete rm -rf htmlcov/ rm -rf dist/ rm -rf build/ rm -rf *.egg-info @echo "โœจ Cleanup complete!" # Database migration management db-upgrade: @echo "โฌ†๏ธ Applying all pending migrations..." $(ALEMBIC) upgrade head @echo "โœ… Database upgraded to latest revision" db-downgrade: @echo "โฌ‡๏ธ Downgrading one migration..." $(ALEMBIC) downgrade -1 @echo "โœ… Database downgraded by one revision" db-current: @echo "๐Ÿ“ Current database revision:" $(ALEMBIC) current -v db-history: @echo "๐Ÿ“œ Migration history:" $(ALEMBIC) history --verbose db-migrate: @echo "๐Ÿ” Auto-generating migration from model changes..." @read -p "Enter migration message: " msg; \ $(ALEMBIC) revision --autogenerate -m "$$msg" @echo "โœ… Migration generated. Review and edit if needed." db-revision: @echo "๐Ÿ“ Creating empty migration file..." @read -p "Enter migration message: " msg; \ $(ALEMBIC) revision -m "$$msg" @echo "โœ… Empty migration created" db-heads: @echo "๐ŸŽฏ Current migration heads:" $(ALEMBIC) heads db-clean: @echo "๐Ÿงน Cleaning migration cache files..." find migrations/ -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true @echo "โœ… Migration cache cleaned" # Advanced testing options test-coverage: @echo "๐Ÿ“Š Running tests with coverage..." $(PYTEST) --cov=routstr --cov-report=html --cov-report=term @echo "Coverage report generated in htmlcov/" test-watch: @echo "๐Ÿ‘๏ธ Running tests in watch mode..." $(PYTEST)-watch test-parallel: @echo "๐Ÿš€ Running tests in parallel..." $(PYTEST) -n auto -v # CI/CD specific targets ci-test: @echo "๐Ÿค– Running CI test suite..." $(PYTEST) -m "not requires_docker" --tb=short -v ci-lint: @echo "๐Ÿค– Running CI linting..." $(RUFF) check . --exit-non-zero-on-fix $(MYPY) . --no-error-summary # Debug helpers test-debug: @echo "๐Ÿ› Running tests with debugging enabled..." $(PYTEST) -vvs --tb=long --pdb-trace test-failed: @echo "๐Ÿ”„ Re-running failed tests..." $(PYTEST) --lf -v # Performance profiling profile: @echo "๐Ÿ”ฅ Running with profiling..." $(PYTHON) -m cProfile -o profile.stats -m pytest tests/integration/test_performance_load.py::TestPerformanceBaseline -v @echo "Profile saved to profile.stats. Use '$(PYTHON) -m pstats profile.stats' to analyze." # Documentation docs-build: @echo "๐Ÿ“š Building documentation..." mkdocs build docs-serve: @echo "๐Ÿ“š Serving documentation at http://localhost:8001..." mkdocs serve -a localhost:8001 docs-deploy: @echo "๐Ÿ“š Deploying documentation to GitHub Pages..." mkdocs gh-deploy --force docs-install: @echo "๐Ÿ“š Installing documentation dependencies..." pip install -r docs/requirements.txt # UI build ui-build: @echo "๐ŸŽจ Building UI for static deployment..." ./scripts/build-ui.sh ui-build-docker: @echo "๐Ÿณ Building UI using Docker (no Node.js installation required)..." @echo "Building UI with environment variables from .env..." docker build -f ui/Dockerfile.build -t routstr-ui-build --build-arg NEXT_PUBLIC_API_URL=$(NEXT_PUBLIC_API_URL) --build-arg NEXT_PUBLIC_ADMIN_API_KEY=$(NEXT_PUBLIC_ADMIN_API_KEY) . docker run --rm -v $(PWD)/ui_out:/output routstr-ui-build cp -r /ui_out /output/ @echo "โœ… UI build complete! Static files available in ui_out/" ui-dev: @echo "๐ŸŽจ Starting UI development server..." cd ui && (command -v pnpm >/dev/null 2>&1 && pnpm run dev || npm run dev)