Makefile
Rama main · réplica de lectura del repositorio original.
.PHONY: dev test smoke lint format format-check typecheck verify-evals verify-locks coverage docker docker-run run clean ci lock lock-tools lock-upgrade _require_pip_compile help
help: ## Show this help message
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-15s\033[0m %s\n", $$1, $$2}'
dev: ## Install project in editable mode with dev dependencies
pip install --require-hashes -r requirements-dev.txt
pip install --no-deps -e .
pre-commit install
pre-commit install --hook-type pre-push
# pip-compile ships with pip-tools, which is deliberately NOT in the dev extras:
# it requires pip/setuptools/wheel, so locking it would hash-pin pip itself into
# the requirements-dev.txt that `make dev` and every CI job install.
# `requirements-build.txt` pins the wheel build backend the Docker image uses; it
# is installed only in the builder stage.
lock-tools: ## Install the pinned pip-compile toolchain (use a throwaway/worktree venv)
pip install "pip==25.1.1" "pip-tools==7.5.3"
_require_pip_compile:
@command -v pip-compile >/dev/null 2>&1 || { \
echo "pip-compile not found — the lock targets need it."; \
echo ""; \
echo " make lock-tools # installs pip==25.1.1 + pip-tools==7.5.3"; \
echo ""; \
echo "Run that in a throwaway or worktree venv: it pins pip to 25.1.1."; \
echo "pip 26 removed an internal that pip-tools 7.5.3 imports, so newer"; \
echo "pip fails every pip-compile call with an ImportError."; \
exit 1; \
}
lock: _require_pip_compile ## Regenerate pinned requirements lockfiles from pyproject.toml
pip-compile --strip-extras --generate-hashes --output-file=requirements.txt pyproject.toml
pip-compile --strip-extras --generate-hashes --extra=dev --output-file=requirements-dev.txt pyproject.toml
pip-compile --strip-extras --generate-hashes --output-file=requirements-build.txt requirements-build.in
# `lock` keeps every version already pinned in the output files, so it cannot
# pull in a bumped dependency. Use this when Dependabot's group PR fails to
# install: its updater rewrites known pins but never adds newly-introduced
# transitive packages, which breaks `pip install --require-hashes`.
lock-upgrade: _require_pip_compile ## Relock at the newest versions pyproject.toml allows
pip-compile --upgrade --strip-extras --generate-hashes --output-file=requirements.txt pyproject.toml
pip-compile --upgrade --strip-extras --generate-hashes --extra=dev --output-file=requirements-dev.txt pyproject.toml
pip-compile --upgrade --strip-extras --generate-hashes --output-file=requirements-build.txt requirements-build.in
test: ## Run tests with pytest
pytest --tb=short
smoke: ## Run hermetic end-to-end smoke tests
pytest tests/smoke -q --no-cov
lint: ## Run Ruff linter and mypy type checker
ruff check .
mypy app/ evals/ --ignore-missing-imports
format: ## Format code with Ruff
ruff format .
ruff check --fix .
format-check: ## Check formatting without modifying files (matches hosted CI)
ruff format --check .
typecheck: ## Run mypy type checker
mypy app/ evals/ --ignore-missing-imports
verify-evals: ## Verify the evals harness package imports cleanly (matches hosted CI)
python -c "import evals"
verify-locks: ## Confirm requirements.txt pins are a hash-identical subset of requirements-dev.txt (AUG-303)
@grep -Ev '^\s*#|^\s*$$' requirements.txt | while IFS= read -r line; do \
grep -qxF "$$line" requirements-dev.txt || { echo "requirements.txt line not found verbatim in requirements-dev.txt: $$line"; exit 1; }; \
done
@echo "requirements.txt pins verified as a subset of requirements-dev.txt"
coverage: ## Run tests with detailed coverage report
pytest --cov=app --cov-report=term-missing --cov-report=html --tb=short
docker: ## Build Docker image via docker compose
docker compose build
docker-run: ## Build and start the Docker container in background
docker compose up -d --build
run: ## Start dev server with auto-reload
uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
ci: lint format-check verify-evals verify-locks test ## Run all CI checks locally (matches hosted CI gate)
clean: ## Remove build artifacts and caches
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 d -name .ruff_cache -exec rm -rf {} + 2>/dev/null || true
find . -type d -name htmlcov -exec rm -rf {} + 2>/dev/null || true
find . -type f -name "*.pyc" -delete 2>/dev/null || true
find . -type f -name ".coverage" -delete 2>/dev/null || true