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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions