feat: migrate to uv with lockfile for supply chain security#270
feat: migrate to uv with lockfile for supply chain security#270
Conversation
Supply chain hardening via uv lockfile with cryptographic hashes for all direct and transitive dependencies. Covers build backend swap, CI workflows, Dockerfile, and pre-commit enforcement. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
8-task plan covering build backend, lockfile, CI workflows, Dockerfile, pre-commit hook, and AGENTS.md updates. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Swap build-system to uv_build, remove [tool.setuptools] sections, add [tool.uv] config with platform-restricted environments (Linux + macOS, x86_64 + arm64).
Pin Python 3.12 for uv auto-selection. Generated lockfile with cryptographic hashes for all direct and transitive dependencies across Linux + macOS (x86_64 + arm64). Also fix index-url field name (default-index is not valid in [tool.uv] for uv 0.9.28). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace setup-python + pip install with setup-uv + uv run --frozen. Lockfile hashes are now enforced in CI.
Use uv binary from official image, uv sync --frozen for hash-verified installs, improved Docker layer caching.
Runs uv lock --check when pyproject.toml changes, fails if lockfile is stale.
Add uv sync/run commands alongside existing pip instructions. Document uv add for dependency management. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Show both uv (recommended) and pip+venv installation options in README. Remove internal planning documents from branch. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
MLCommons CLA bot All contributors have signed the MLCommons CLA ✍️ ✅ |
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request migrates the project's dependency management and build system from setuptools/pip to uv. Key changes include updating pyproject.toml to use uv_build, adding a .python-version file, updating documentation (README.md, AGENTS.md) with uv-specific commands, and refactoring the development Dockerfile to utilize uv for faster, reproducible builds. Feedback focuses on correcting the build-system requirement name, fixing file exclusion paths in the build configuration, and optimizing the Dockerfile for better layer caching and volume mount compatibility.
| [build-system] | ||
| requires = ["setuptools==78.1.1", "wheel==0.46.3"] | ||
| build-backend = "setuptools.build_meta" | ||
| requires = ["uv_build>=0.7.6,<0.8"] |
There was a problem hiding this comment.
The build system requirement should be uv-build-backend, not uv_build. While the backend entry point is named uv_build, the package name on PyPI is uv-build-backend. Using the incorrect name will cause pip and other PEP 517 compatible tools to fail when attempting to build the project from source.
| requires = ["uv_build>=0.7.6,<0.8"] | |
| requires = ["uv-build-backend>=0.1.0"] |
| ENV PATH="/home/appuser/.local/bin:$PATH" | ||
|
|
||
| RUN pip install -e .[dev,test] | ||
| RUN uv sync --frozen --extra dev --extra test |
There was a problem hiding this comment.
When running the container with a volume mount (as suggested in the file header: -v $(pwd):/mnt/inference-endpoint), the .venv directory created here will be obscured by the host directory. This will result in the installed dependencies being unavailable in the running container. To resolve this, consider setting UV_PROJECT_ENVIRONMENT to a location outside the project root (e.g., /opt/venv) and adding that location to the PATH.
| [tool.uv.build] | ||
| module-root = "src" | ||
| data = {"inference_endpoint" = ["config/templates/*.yaml"]} | ||
| exclude = ["evaluation/livecodebench/_server.py"] |
There was a problem hiding this comment.
The exclude path should be relative to the project root to ensure the file is correctly identified and excluded from the build. Since module-root is set to src, the path should include the src/ prefix to match the actual file location.
| exclude = ["evaluation/livecodebench/_server.py"] | |
| exclude = ["src/inference_endpoint/evaluation/livecodebench/_server.py"] |
| COPY pyproject.toml uv.lock .python-version ./ | ||
| COPY src/ ./src/ |
There was a problem hiding this comment.
To optimize Docker layer caching, it is recommended to install dependencies before copying the full source code. This prevents the uv sync step from re-running every time a source file is modified. You can use uv sync --no-install-project to install only the dependencies first.
COPY pyproject.toml uv.lock .python-version ./
RUN uv sync --frozen --no-install-project --extra dev --extra test
COPY src/ ./src/
There was a problem hiding this comment.
Pull request overview
Migrates the project’s packaging, local/dev environment, and CI installation flow to uv with a committed uv.lock to improve reproducibility and supply-chain integrity.
Changes:
- Switch build backend from
setuptoolstouv_buildand addtool.uv/tool.uv.buildconfiguration. - Introduce
uv.lock(+.python-version) and update Docker/CI/pre-commit to use frozen, lockfile-verified installs. - Update contributor docs (README, AGENTS) with both uv and pip workflows.
Reviewed changes
Copilot reviewed 8 out of 9 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| scripts/Dockerfile.dev | Installs uv and uses uv sync --frozen for dev image builds. |
| README.md | Documents uv-based setup alongside the existing pip+venv path. |
| pyproject.toml | Moves build backend to uv_build and adds uv configuration for builds/resolution. |
| AGENTS.md | Updates common commands and dependency guidance to include uv. |
| .python-version | Adds a Python version hint for tooling (3.12). |
| .pre-commit-config.yaml | Adds a uv lock --check hook to enforce lock freshness. |
| .github/workflows/test.yml | Runs tests and pip-audit via uv run --frozen. |
| .github/workflows/pre-commit.yml | Runs pre-commit via uv with frozen dependencies. |
| uv.lock | Adds a hash-verified lockfile for direct + transitive dependencies. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| [tool.uv.build] | ||
| module-root = "src" | ||
| data = {"inference_endpoint" = ["config/templates/*.yaml"]} | ||
| exclude = ["evaluation/livecodebench/_server.py"] |
There was a problem hiding this comment.
tool.uv.build.exclude path looks incorrect given the actual file location is src/inference_endpoint/evaluation/livecodebench/_server.py. With module-root = "src", the exclude entry likely needs to include the inference_endpoint/ prefix; otherwise _server.py may be unintentionally packaged.
| exclude = ["evaluation/livecodebench/_server.py"] | |
| exclude = ["inference_endpoint/evaluation/livecodebench/_server.py"] |
| - id: uv-lock-check | ||
| name: Check uv.lock is up-to-date | ||
| entry: uv lock --check | ||
| language: system |
There was a problem hiding this comment.
This hook runs uv lock --check with language: system, so pre-commit will fail on machines that don’t have the uv binary installed on PATH (including pip-only setups). Consider switching to a hook that provisions uv automatically or ensure uv is installed as part of the documented/dev dependency setup so non-uv contributors aren’t blocked.
| language: system | |
| language: python | |
| additional_dependencies: | |
| - uv |
| # Copy uv binary from official image | ||
| COPY --from=ghcr.io/astral-sh/uv:0.7.6 /uv /uvx /bin/ |
There was a problem hiding this comment.
For supply-chain reproducibility, copying uv from an image tag (ghcr.io/astral-sh/uv:0.7.6) is still mutable. Consider pinning the --from image to an immutable digest so builds can’t change if the tag is retargeted.
| # Copy uv binary from official image | |
| COPY --from=ghcr.io/astral-sh/uv:0.7.6 /uv /uvx /bin/ | |
| # Copy uv binary from an immutable official image reference | |
| COPY --from=ghcr.io/astral-sh/uv:0.7.6@sha256:<verified-digest-for-0.7.6> /uv /uvx /bin/ |
| - name: Install uv | ||
| uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5 | ||
|
|
||
| - name: Run tests | ||
| run: | | ||
| pytest -xv -m "not slow and not performance" --cov=src --cov-report=xml --cov-report=html | ||
| run: uv run --frozen --extra test pytest -xv -m "not slow and not performance" --cov=src --cov-report=xml --cov-report=html |
There was a problem hiding this comment.
CI no longer pins/sets up a specific Python version. Since this project requires Python >=3.12 and previously enforced 3.12, consider explicitly setting up Python (or configuring the uv setup step to install/use 3.12) to keep CI reproducible and avoid breakage if the runner’s default Python changes.
| with: | ||
| python-version: "3.12" | ||
| - name: Install uv | ||
| uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5 |
There was a problem hiding this comment.
This workflow now relies on whatever Python happens to be on the runner. To avoid non-reproducible pre-commit results, explicitly set up the intended Python version (3.12) or configure the uv setup step accordingly.
| uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5 | |
| uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5 | |
| with: | |
| python-version: "3.12" |
Summary
uv_build— auto-discovers src layout, pure Pythonuv.lockwith cryptographic hashes for all 133 direct + transitive dependencies (Linux + macOS, x86_64 + arm64)test.yml,pre-commit.yml) from pip touv run --frozenfor hash-verified installsDockerfile.devto use uv binary withuv sync --frozenuv-lock-checkpre-commit hook to enforce lockfile freshness whenpyproject.tomlchangesSupply chain protection
--frozen+ hashes = reproducibleBackward compatibility
pip install -e ".[dev,test]"still works (pip downloadsuv_buildfrom PyPI automatically)Test plan
uv-lock-check)uv run pytestpip install -e ".[test]"+ import OK🤖 Generated with Claude Code