Summary
make install upgrades transitive dependencies to their latest PyPI versions even when those packages are pinned in constraints.txt / constraints-mxdev.txt. Local venvs diverge from what CI builds (CI typically runs only make packages, which honors pins via -r requirements-mxdev.txt). This breaks reproducibility for projects that rely on pin discipline.
Affected topic templates
Several pip install recipes pass -U (or no constraints at all) instead of routing through -c <constraints-file>:
| File |
Line |
Command |
Issue |
core/mxenv.mk |
170 |
install -U pip setuptools wheel |
-U + no -c |
core/mxenv.mk |
172 |
install -U $(MXDEV) $(MXMAKE) |
-U + no -c |
docs/sphinx.mk |
49 |
install -U sphinx sphinx-autobuild $(DOCS_REQUIREMENTS) |
-U + no -c |
qa/coverage.mk |
25 |
install -U coverage |
-U + no -c |
qa/ruff.mk |
53 |
install ruff |
no -c (installs latest on first run) |
docs/sphinx.mk is the most damaging in practice. sphinx-autobuild declares starlette>=0.35, uvicorn>=0.25, websockets>=11, watchfiles>=0.20. These overlap with FastAPI/Starlette application dependencies. When the docs sentinel runs first in the install chain, it pulls these transitive deps to latest. The subsequent pip install -r requirements-mxdev.txt does not downgrade them: pip only honors -c during resolution, not retroactively for already-installed packages.
Reproduction
A FastAPI project with the relevant pins:
$ grep -E '^(starlette|uvicorn|websockets)==' constraints.txt
starlette==0.49.3
uvicorn==0.38.0
websockets==15.0.1
$ make install
...
+ starlette==1.0.0 # upgraded beyond pin
+ uvicorn==0.46.0 # upgraded beyond pin
+ websockets==16.0 # upgraded beyond pin
+ setuptools==82.0.1 # upgraded beyond pin (was 80.9.0)
+ wheel==0.46.3 # upgraded beyond pin (was 0.45.1)
+ ruff==0.15.11 # upgraded beyond pin (was 0.14.3)
Expected behavior
make install produces a venv whose pip freeze exactly matches the pinned constraints (modulo development sources installed editable).
Root cause
Two coupled problems in the topic templates:
-U flag: forces upgrade to latest, overriding any pin.
- No
-c <constraints>: pip doesn't apply project pins to transitive deps of stand-alone tools.
Proposed fix
For each pip install recipe in the topic templates, drop -U and pass -c $(MXDEV_CONSTRAINTS) (or whatever variable resolves to the active constraints file). For docs/sphinx.mk:
- @$(PYTHON_PACKAGE_COMMAND) install -U sphinx sphinx-autobuild $(DOCS_REQUIREMENTS)
+ @$(PYTHON_PACKAGE_COMMAND) install -c $(MXDEV_CONSTRAINTS) sphinx sphinx-autobuild $(DOCS_REQUIREMENTS)
Caveat for core/mxenv.mk: this template runs before mxfiles generates constraints-mxdev.txt, so it would need either:
- a fallback to the un-rewritten
constraints.txt from the project root, or
- a re-ordering so
mxfiles runs before mxenv for the bootstrap pip/setuptools install (with the chicken-and-egg of needing pip to run mxdev in the first place — likely solvable by using python -m pip directly).
Happy to send a PR if the maintainers agree on the approach.
Local workaround
Hand-patch the generated Makefile to add -c constraints.txt and drop -U on the offending lines. Survives until the next mxmake update.
Summary
make installupgrades transitive dependencies to their latest PyPI versions even when those packages are pinned inconstraints.txt/constraints-mxdev.txt. Local venvs diverge from what CI builds (CI typically runs onlymake packages, which honors pins via-r requirements-mxdev.txt). This breaks reproducibility for projects that rely on pin discipline.Affected topic templates
Several
pip installrecipes pass-U(or no constraints at all) instead of routing through-c <constraints-file>:core/mxenv.mkinstall -U pip setuptools wheelcore/mxenv.mkinstall -U $(MXDEV) $(MXMAKE)docs/sphinx.mkinstall -U sphinx sphinx-autobuild $(DOCS_REQUIREMENTS)qa/coverage.mkinstall -U coverageqa/ruff.mkinstall ruffdocs/sphinx.mkis the most damaging in practice.sphinx-autobuilddeclaresstarlette>=0.35,uvicorn>=0.25,websockets>=11,watchfiles>=0.20. These overlap with FastAPI/Starlette application dependencies. When the docs sentinel runs first in the install chain, it pulls these transitive deps to latest. The subsequentpip install -r requirements-mxdev.txtdoes not downgrade them: pip only honors-cduring resolution, not retroactively for already-installed packages.Reproduction
A FastAPI project with the relevant pins:
Expected behavior
make installproduces a venv whosepip freezeexactly matches the pinned constraints (modulo development sources installed editable).Root cause
Two coupled problems in the topic templates:
-Uflag: forces upgrade to latest, overriding any pin.-c <constraints>: pip doesn't apply project pins to transitive deps of stand-alone tools.Proposed fix
For each
pip installrecipe in the topic templates, drop-Uand pass-c $(MXDEV_CONSTRAINTS)(or whatever variable resolves to the active constraints file). Fordocs/sphinx.mk:Caveat for
core/mxenv.mk: this template runs beforemxfilesgeneratesconstraints-mxdev.txt, so it would need either:constraints.txtfrom the project root, ormxfilesruns beforemxenvfor the bootstrap pip/setuptools install (with the chicken-and-egg of needing pip to run mxdev in the first place — likely solvable by usingpython -m pipdirectly).Happy to send a PR if the maintainers agree on the approach.
Local workaround
Hand-patch the generated
Makefileto add-c constraints.txtand drop-Uon the offending lines. Survives until the nextmxmake update.