pip install exiting 0 is not evidence the venv is usable (D-24) - the 2026-08-09 core-api incident was exactly this shape: a venv that "installed fine" but was missing sqlalchemy, surfacing as 11 collection errors that read like broken imports rather than an environment problem. setup now ends with `pytest --collect-only`, scoped like `make test` (excludes e2e/integration/contracts) and run with --no-cov. Collection imports every test module without running the suite, so a missing or mismatched dependency fails setup itself instead of showing up later as a confusing test failure. Workspace T-47.
90 lines
3.9 KiB
Makefile
90 lines
3.9 KiB
Makefile
.PHONY: help setup run test test-unit test-integration test-contracts lint typecheck clean
|
|
|
|
VENV := .venv
|
|
PYTHON := $(VENV)/bin/python
|
|
PIP := $(VENV)/bin/pip
|
|
PYTEST := $(VENV)/bin/pytest
|
|
RUFF := $(VENV)/bin/ruff
|
|
MYPY := $(VENV)/bin/mypy
|
|
UVICORN := $(VENV)/bin/uvicorn
|
|
|
|
HOST := 0.0.0.0
|
|
PORT := 8777
|
|
|
|
help: ## Show this help
|
|
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
|
|
|
|
setup: ## Create venv and install all dependencies
|
|
python3 -m venv $(VENV)
|
|
$(PIP) install --upgrade pip
|
|
$(PIP) install -e ".[dev]"
|
|
# Exit 0 from pip install is not evidence the environment works (D-24) - the
|
|
# 2026-08-09 core-api incident was exactly this: a venv that "installed fine"
|
|
# but was missing a declared dependency, surfacing as 11 collection errors
|
|
# that read like broken imports rather than an environment problem. Collection
|
|
# is the right cheap check here for that same reason: it imports every test
|
|
# module (and everything they import) without running the suite, so a missing
|
|
# or mismatched dependency fails setup itself instead of showing up later as a
|
|
# mysterious test failure. Scoped like `make test` (excludes e2e/integration/
|
|
# contracts, which need external services) and --no-cov since coverage
|
|
# instrumentation is irrelevant to "does this collect".
|
|
$(PYTEST) --collect-only -q --ignore=tests/e2e --ignore=tests/integration --ignore=tests/contracts --no-cov
|
|
|
|
run: ## Start the development server on port 8777
|
|
@mkdir -p build/logs
|
|
@if lsof -Pi :$(PORT) -sTCP:LISTEN -t >/dev/null 2>&1; then \
|
|
echo "Error: Port $(PORT) is already in use"; \
|
|
echo "Run: lsof -i :$(PORT) to see what's using it"; \
|
|
exit 1; \
|
|
fi
|
|
$(UVICORN) src.main:app --reload --host $(HOST) --port $(PORT) 2>&1 | tee build/logs/server.log
|
|
|
|
test: ## Run unit tests (no external services needed)
|
|
$(PYTEST) --ignore=tests/e2e --ignore=tests/integration --ignore=tests/contracts
|
|
|
|
test-unit: test ## Alias for test
|
|
|
|
test-integration: ## Run integration tests (needs Claude/Ollama)
|
|
$(PYTEST) tests/agents/test_tatlock_agent.py -v
|
|
|
|
test-contracts: ## Wire-level contract tests against live service boundaries
|
|
$(PYTEST) tests/contracts -v --no-cov
|
|
|
|
lint: ## Run ruff linter and formatter check
|
|
$(RUFF) check src tests
|
|
$(RUFF) format --check src tests
|
|
|
|
typecheck: ## Run mypy type checking
|
|
$(MYPY) src
|
|
|
|
clean: ## Remove build artifacts, caches, and coverage reports
|
|
rm -rf .cache build
|
|
find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
|
|
|
|
# git hands a hook a non-login shell, which never sees ~/.local/bin — where
|
|
# gitleaks lands. Without this the scan reports "not installed" on every push,
|
|
# which is a check that fails open (D-24).
|
|
export PATH := $(HOME)/.local/bin:/usr/local/bin:$(PATH)
|
|
|
|
.PHONY: secrets
|
|
secrets: ## Scan the commits about to be pushed for credentials
|
|
@ci/secrets.sh
|
|
|
|
# The call surface is identical in every repo; what it runs is not.
|
|
#
|
|
# `secrets` runs first, deliberately: it is the only failure here that cannot be
|
|
# undone by fixing it afterwards. A failed lint costs another commit; a pushed
|
|
# credential is cached and indexed whether or not it is later deleted.
|
|
#
|
|
# Some of these fail today, and are left wired anyway. The state was measured
|
|
# once and written down in T-56 rather than being worked around here — a gate
|
|
# quietly narrowed to what already passes is a gate that reports success for
|
|
# doing nothing, which is the failure this workspace keeps rediscovering.
|
|
.PHONY: pre-push
|
|
pre-push: secrets lint ## Everything the pre-push hook runs
|
|
@echo " -- not gated here yet: typecheck (T-1), test (T-56)"
|
|
@echo " typecheck reports 95 errors in 31 files and has never passed, so"
|
|
@echo " gating on it blocked every push to this repo — including the commit"
|
|
@echo " that added the gate. Run 'make typecheck' before pushing anything"
|
|
@echo " that touches types; T-1 is the pass that earns this line's removal."
|