Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions .github/workflows/uv-lock-checks.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Check the `uv` lockfile for consistency with `pyproject.toml`.
# Check the `uv` lockfile and `pins.json` for consistency with `pyproject.toml`.
#
# If this check fails, you should run `uv lock` to update the lockfile.
# If the lockfile check fails, you should run `uv lock` to update the lockfile.
# If the pins check fails, update the torch index URLs in `pins.json` to match
# the `[[tool.uv.index]]` entries in `pyproject.toml` (see scripts/check_pins.py).

name: 'uv lock checks'

Expand Down Expand Up @@ -54,15 +56,24 @@ jobs:
uvlock-pyprojecttoml:
- 'pyproject.toml'
- 'uv.lock'
- 'pins.json'
- 'scripts/check_pins.py'
- name: setup uv
if: ${{ steps.changed-files.outputs.uvlock-pyprojecttoml_any_changed == 'true' || inputs.always_run == true }}
uses: astral-sh/setup-uv@v8.1.0
with:
version: '0.6.10'
# Keep this at or above the uv version used to generate uv.lock (revision 3 lock
# format requires a modern uv; 0.6.x cannot parse it).
version: '0.11.28'
enable-cache: true

- name: check lockfile
if: ${{ steps.changed-files.outputs.uvlock-pyprojecttoml_any_changed == 'true' || inputs.always_run == true }}
run: uv lock --locked # this will exit with 1 if the lockfile is not consistent with pyproject.toml
shell: bash

- name: check pins.json
if: ${{ steps.changed-files.outputs.uvlock-pyprojecttoml_any_changed == 'true' || inputs.always_run == true }}
run: python3 scripts/check_pins.py # pins.json is consumed by the launcher; keep its torch index URLs in sync with pyproject.toml
shell: bash
4 changes: 3 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ dependencies = [
# Loosely pinned, will respect requirement of `diffusers[torch]`. Split by platform: linux/win allow
# >=2.10 so the rocm extra can use torch 2.10.0+rocm7.1, while macOS stays on 2.7.x — newer macOS torch
# wheels exercise MPS on CI runners (no usable Metal GPU) and fail with MPS OOM.
"torch>=2.7.0,<3.0; sys_platform != 'darwin'",
# Capped <2.12: torch 2.12.x+rocm7.1 breaks generation (#9328), and legacy (pre-6.14) launcher
# installs resolve this range live against the pytorch wheel indexes rather than using uv.lock.
"torch>=2.7.0,<2.12; sys_platform != 'darwin'",
"torch>=2.7.0,<2.8.0; sys_platform == 'darwin'",
"torchsde", # diffusers needs this for SDE solvers, but it is not an explicit dep of diffusers
"torchvision",
Expand Down
60 changes: 60 additions & 0 deletions scripts/check_pins.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
"""Check that pins.json is consistent with pyproject.toml.

``pins.json`` is not used anywhere in this repo — it is fetched (at the release
tag) by the Invoke Launcher (https://github.com/invoke-ai/launcher), which uses
its ``torchIndexUrl`` entries to pick the torch wheel index for legacy
(pre-6.14.0) installs. Because nothing in-repo consumes it, it can silently
drift from the ``[[tool.uv.index]]`` URLs in pyproject.toml — which is exactly
what happened when ROCm moved from 6.3 to 7.1 (issue #9328).

This script fails if any ``torchIndexUrl`` entry in pins.json differs from the
URL of the corresponding ``torch-<backend>`` index in pyproject.toml.

Run from anywhere: python scripts/check_pins.py
"""

import json
import sys
import tomllib
from pathlib import Path

REPO_ROOT = Path(__file__).resolve().parent.parent


def main() -> int:
pins = json.loads((REPO_ROOT / "pins.json").read_text())
pyproject = tomllib.loads((REPO_ROOT / "pyproject.toml").read_text())

indexes = {i["name"]: i["url"] for i in pyproject["tool"]["uv"]["index"]}

errors: list[str] = []

for platform, backends in pins["torchIndexUrl"].items():
for backend, pinned_url in backends.items():
index_name = f"torch-{backend}"
expected_url = indexes.get(index_name)
if expected_url is None:
errors.append(
f"pins.json torchIndexUrl.{platform}.{backend}: no [[tool.uv.index]] named '{index_name}' in pyproject.toml"
)
elif pinned_url != expected_url:
errors.append(
f"pins.json torchIndexUrl.{platform}.{backend} is '{pinned_url}' but pyproject.toml index '{index_name}' is '{expected_url}'"
)

if errors:
print("pins.json is out of sync with pyproject.toml:", file=sys.stderr)
for error in errors:
print(f" - {error}", file=sys.stderr)
print(
"\nUpdate pins.json to match the [[tool.uv.index]] URLs in pyproject.toml (or vice versa).",
file=sys.stderr,
)
return 1

print("pins.json is consistent with pyproject.toml")
return 0


if __name__ == "__main__":
sys.exit(main())
10 changes: 5 additions & 5 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading