build(setup): prove the venv works instead of trusting pip's exit code

`make setup` exited 0 whether or not the environment it produced was
usable — per D-24, a step whose job is to not fail has a passing state
indistinguishable from its broken state. Adds two cheap checks at the
end: `pip check` for version drift between installed packages, and
`pytest --collect-only` to walk the full src/ import graph and catch a
missing declared dependency, which is what core-api's undetected
missing sqlalchemy looked like (T-47). Neither needs any of the five
backing services running — dependencies.py only constructs clients
inside lru_cache getters, never at import/collection time.

Also fixes `setup` to install requirements-dev.txt rather than
requirements.txt. It only ever installed the latter since the
Makefile's introduction, so `make test` and `make lint` — both of
which need pytest and ruff — were never actually reachable from a
clean `make setup`. requirements-dev.txt pulls in requirements.txt via
-r, so the runtime set installed is unchanged; only the tooling to
prove it is added. Found because the new check failed honestly on its
first clean-tree run, before this fix.

Verified: clean-tree run installs everything and passes (455 tests
collected); a second run is a fast no-op; uninstalling a declared
runtime dependency (asyncpg) makes the check fail with
ModuleNotFoundError, and rerunning setup restores and re-passes it.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-08-17 12:06:08 +02:00
co-authored by Claude
parent bf4e8849c0
commit a9a5731991
+25 -2
View File
@@ -18,9 +18,32 @@ help: ## Show this help
| awk 'BEGIN{FS=":.*?## "}{printf " \033[36m%-14s\033[0m %s\n", $$1, $$2}'
.PHONY: setup
setup: ## Create the venv and install dependencies
setup: ## Create the venv, install dependencies, and prove the result works
$(PYTHON) -m venv .venv
$(VENV)/bin/pip install -r requirements.txt
# requirements-dev.txt pulls in requirements.txt via -r, so this is still
# the full runtime set plus pytest/ruff. Installing only requirements.txt
# here (as this line originally did) left `make test` and `make lint`
# unreachable from a clean `make setup` since the Makefile's introduction
# in b9f55cb — pytest was never installed by setup at all. Found by the
# check below failing on its first clean-tree run; fixed in the same
# commit rather than filed separately, since the new check cannot pass
# honestly against the old line.
$(VENV)/bin/pip install -r requirements-dev.txt
# Exit 0 from pip install is not evidence (D-24) — it is the same exit code
# whether requirements.txt matches what's on disk or a dependency silently
# failed to install. Two cheap checks, for two different drift modes:
# pip check - installed packages satisfy each other's declared
# version constraints (a stale/partial install).
# pytest --collect-only - every test module actually imports, which
# walks the full src/ import graph and is exactly
# what catches a *missing* declared dependency
# (core-api's sqlalchemy case in T-47). It builds
# no client and opens no socket - dependencies.py
# wraps client construction in lru_cache getters,
# never called at collection time - so this needs
# none of the five backing services running.
$(VENV)/bin/pip check
$(VENV)/bin/python -m pytest tests/ --collect-only -q
.PHONY: run
run: ## Dev server on :8778 with reload (8089 is the container, not this)