Skip to content

make install ignores pinned constraints, upgrades transitive deps unexpectedly #70

@jensens

Description

@jensens

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:

  1. -U flag: forces upgrade to latest, overriding any pin.
  2. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions