aspect-build / aspect-build/rules_py

[Bug]: uv cross-module projects can make @hub//pkg resolve to a version from another lockfile

Open
#1,093 0 comments 1 reaction 0 assignees View on GitHub
bug
Dominant language
Starlark
Stars
145
Forks
97
Avg merge
1d 1h
Merged PRs (30d)
71

Description

### What happened?

Related issue: https://github.com/bazel-contrib/rules_python/issues/1791

## Summary

`aspect_rules_py` uv hubs are not isolated across bzlmod modules when two modules use the same uv project / dependency-group name.

A downstream module can directly depend on a package from its own uv hub, for example `@bar_uv_deps//matplotlib`, but Bazel can resolve that label through the upstream module's generated uv project and lockfile result.

## Reproduction

There are two projects: `foo` and `bar`.

`foo/pyproject.toml`:

```toml
[project]
name = "runtime"
dependencies = [
"build",
"matplotlib",
]
```

`foo/uv.lock` resolves matplotlib `3.9.4`.

`bar/pyproject.toml`:

```toml
[project]
name = "runtime"
dependencies = [
"build",
"matplotlib<=3.7.0",
]
```

`bar/uv.lock` resolves matplotlib `3.7.0`.

`bar/BUILD.bazel` directly depends on its own uv hub label:

```starlark
py_binary(
name = "main",
srcs = ["main.py"],
deps = [
"@foo",
"@bar_uv_deps//matplotlib",
],
)
```

Run:

```sh
bazel run //:main
```

Since `bar` directly depends on `@bar_uv_deps//matplotlib`, and `bar/uv.lock` contains matplotlib `3.7.0`, the binary should run with:

```text
matplotlib version: 3.7.0
```

The binary runs with matplotlib `3.9.4`

## Workarounds considered

Using `virtual_deps` / `resolutions` can work only if the whole relevant dependency graph cooperates by exposing third-party packages as virtual dependencies.

Giving the two uv projects distinct names, such as `foo-runtime` and `bar-runtime`, avoids the collision because the generated repos become distinct:

```text
project__bar_runtime//:matplotlib
whl_install__bar_runtime__matplotlib__3_7_0
```

If duplicate project / dependency-group names across Bzlmod modules are unsupported, it would be better to fail clearly rather than silently selecting another module's package version.

### Version

Development (host) and target OS/architectures: linux x86_64

Output of `bazel --version`: 9.1.1

Version of the Aspect rules, or other relevant rules from your
`WORKSPACE` or `MODULE.bazel` file: bazel_dep(name = "aspect_rules_py", version = "2.0.0-alpha.1")

Language(s) and/or frameworks involved: python

### How to reproduce

```shell
Example project:
https://github.com/finn-ball/python_bzlmod_test/tree/finn/rules_py
```

### Any other information?

_No response_

Contributor guide

Open the contributing guide

Research direction

Start with the linked example project and reproduce the issue with foo/pyproject.toml, bar/pyproject.toml, their uv.lock files, and bar/BUILD.bazel using `bazel run //:main`. Trace how the two uv hubs and `@bar_uv_deps//matplotlib` are generated and resolved across Bzlmod modules. Done means the label uses bar's 3.7.0 package, or duplicate project names fail with a clear error instead of selecting foo's 3.9.4 result.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
build-system
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.