.PHONY: install-backend install-frontend install setup-hooks backend frontend worker db db-stop db-ready db-ready-backend-tests db-ready-e2e-tests db-seed dev test test-backend test-frontend test-e2e typecheck generate-types generate-types-standalone check-types-fresh check-constants lint-backend format-backend fix-backend security-backend lint-frontend fix-frontend format-frontend pre-commit lint -include .env export install-backend: cd backend && uv sync --all-groups install-frontend: cd frontend && npm install install: install-backend install-frontend setup-hooks setup-hooks: git config core.hooksPath .githooks backend: cd backend && uv run uvicorn main:app --reload frontend: cd frontend && npm run dev worker: cd backend && uv run python worker.py db: docker compose up -d db db-stop: docker compose down db-clean: docker compose down -v db-ready: @docker compose up -d db @echo "Waiting for PostgreSQL to be ready..." @until docker compose exec -T db pg_isready -U postgres > /dev/null 2>&1; do \ sleep 1; \ done @docker compose exec -T db psql -U postgres -tc "SELECT 1 FROM pg_database WHERE datname = 'arbret'" | grep -q 1 || \ docker compose exec -T db psql -U postgres -c "CREATE DATABASE arbret" @echo "PostgreSQL is ready" # Create worker-specific databases for parallel backend test execution (pytest-xdist) db-ready-backend-tests: db-ready @echo "Creating backend test databases..." @docker compose exec -T db psql -U postgres -tc "SELECT 1 FROM pg_database WHERE datname = 'arbret_test'" | grep -q 1 || \ docker compose exec -T db psql -U postgres -c "CREATE DATABASE arbret_test" @for i in 0 1 2 3 4 5 6 7; do \ docker compose exec -T db psql -U postgres -tc "SELECT 1 FROM pg_database WHERE datname = 'arbret_test_gw$$i'" | grep -q 1 || \ docker compose exec -T db psql -U postgres -c "CREATE DATABASE arbret_test_gw$$i"; \ done @echo "Backend test databases ready" # Create worker-specific databases for parallel e2e test execution db-ready-e2e-tests: db-ready @echo "Creating e2e test databases..." @for i in 0 1 2 3 4 5 6 7; do \ docker compose exec -T db psql -U postgres -tc "SELECT 1 FROM pg_database WHERE datname = 'arbret_e2e_worker$$i'" | grep -q 1 || \ docker compose exec -T db psql -U postgres -c "CREATE DATABASE arbret_e2e_worker$$i"; \ done @echo "E2E test databases ready" db-seed: db-ready cd backend && uv run python seed.py dev: $(MAKE) db-seed cd backend && uv run uvicorn main:app --reload & \ cd backend && uv run python worker.py & \ cd frontend && npm run dev & \ wait # TEST variable can be used to select specific tests: # Backend: TEST="-m auth" (marker) or TEST="tests/test_booking.py" (file) or TEST="tests/test_booking.py::TestBooking::test_specific" (specific test) # Frontend: TEST="app/login" (file pattern matching app/**/*.test.{ts,tsx}) # E2E: TEST="auth" (file pattern matching e2e/*.spec.ts) TEST ?= test-backend: db-ready-backend-tests test-backend-clean-dbs cd backend && uv run pytest -v -n 8 $(TEST) # Clean only backend test databases (not e2e or main db) test-backend-clean-dbs: @for db in arbret_test arbret_test_gw0 arbret_test_gw1 arbret_test_gw2 arbret_test_gw3 arbret_test_gw4 arbret_test_gw5 arbret_test_gw6 arbret_test_gw7; do \ docker compose exec -T db psql -U postgres -c "DROP DATABASE IF EXISTS $$db" 2>/dev/null || true; \ docker compose exec -T db psql -U postgres -c "CREATE DATABASE $$db"; \ done test-frontend: cd frontend && npm run test $(if $(TEST),-- $(TEST),) test-e2e: db-ready-e2e-tests test-e2e-clean-db ./scripts/e2e.sh $(TEST) # Clean only e2e databases (not backend test dbs or main db) # Create worker-specific databases for parallel e2e test execution test-e2e-clean-db: @for i in 0 1 2 3 4 5 6 7; do \ docker compose exec -T db psql -U postgres -c "DROP DATABASE IF EXISTS arbret_e2e_worker$$i" 2>/dev/null || true; \ docker compose exec -T db psql -U postgres -c "CREATE DATABASE arbret_e2e_worker$$i" 2>/dev/null || true; \ done test: check-constants check-types-fresh test-backend test-frontend test-e2e typecheck: generate-types-standalone cd backend && uv run mypy . cd frontend && npx tsc --noEmit generate-types: cd frontend && npm run generate-api-types generate-types-standalone: db-seed @echo "Starting backend for type generation..." @cd backend && uv run uvicorn main:app --port 8000 --log-level warning & \ BACKEND_PID=$$!; \ sleep 3; \ cd frontend && npm run generate-api-types; \ EXIT_CODE=$$?; \ kill $$BACKEND_PID 2>/dev/null || true; \ exit $$EXIT_CODE check-types-fresh: generate-types-standalone @if git diff --quiet frontend/app/generated/api.ts 2>/dev/null; then \ echo "✓ Generated types are up to date"; \ else \ echo "✗ Generated types are stale. Run 'make generate-types-standalone' and commit."; \ git diff frontend/app/generated/api.ts; \ exit 1; \ fi check-constants: @cd backend && uv run python validate_constants.py lint-backend: cd backend && uv run ruff check . format-backend: cd backend && uv run ruff format . fix-backend: cd backend && uv run ruff check --fix . && uv run ruff format . security-backend: cd backend && uv run bandit -r . -c pyproject.toml lint-frontend: cd frontend && npm run lint fix-frontend: cd frontend && npm run lint:fix format-frontend: cd frontend && npm run format pre-commit: cd backend && uv run pre-commit run --all-files lint: lint-backend lint-frontend security-backend @echo "All linting passed!"