-
-
Notifications
You must be signed in to change notification settings - Fork 570
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: uv lock rule instead of genrule #2657
base: main
Are you sure you want to change the base?
feat: uv lock rule instead of genrule #2657
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, after doing self review I think I want to have:
- A script for launching
uv
frombash
that would be compatible with UNIX. - A script for launching
uv
frompowershell
that would be compatible with Windows (generative AI may help with initial translation here). - Rewrite the internals a little to drop the Python usage (or at least most of it).
fcc17c3
to
7ddfd28
Compare
928f1e2
to
2c29ae2
Compare
The core of the implementation looks good to me (rule that looks up toolchains to run an build action; lock_run uses info lock provides via a provider). I have a variety of smaller comments about some particulars, but gtg now, so I'll have to wait until, ah, probably the weekend sometime. The |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
got about half way through
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, to clarify, this is the sort of interface I imagined:
bazel build //:requirements
generates a requirements file using a build actionbazel run //:requirements.update
generates a requirements file using a build action and copies it into the local client to update the requirements filebazel run //:requirements.run -- <args>
more of a direct invocation; runs uv directly; this is for debugging or experimenting with settings without having to modify the BUILD file.
The reason for (2) to use the output of (1) is because that's where the magic of bazel happens. By this i mean: build actions have isolated/deterministic/hermetic capabilities, can run remotely, are more amenable to having transitions applied, and are better about not having different output per user machine.
OK, addressed the comments, PTAL. I see that Windows is failing, because something is not compatible with the CI Windows version. I wonder if this means we should just tell users that Windows may be unsupported? |
This change implements the uv pip compile as a rule. In order to also make things easier to debug we provide a runnable rule that has the same arguments and updates the source tree output file automatically. The main design is to have a regular lock rule and then it returns a custom provider that has all of the recipe ingredients to construct an executable rule. The execution depends on having bash or powershell, however the powershell script is not yet complete and requires some help from the community. Work towards bazel-contrib#1975.
add the upgrade flag back
43bd183
to
daab523
Compare
daab523
to
c67cdcd
Compare
Open questions:
|
Sorry, some short notice deadlines came upon me. I'll be able to have another look Weds evening or after |
Since uv is coming from a toolchain, and we need python to match uv, I think both should come from a toolchain. A behavior unique to toolchains is that a group of toolchains can get resolved with the same config state. Getting the same behavior using labels, or a mix of a label and toolchain, might be tricky (it might be possible using exec groups?). |
return [ | ||
DefaultInfo( | ||
executable = executable, | ||
runfiles = ctx.runfiles(transitive_files = info.srcs), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there's a subtle config mismatch here: info.srcs contains uv in exec config, but here it's going to run in target config.
I'm OK with ignoring this for now, though, to keep progress moving along.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have added a transition, but I am still new as to how to ensure that this will be in exec
configuration.
I can follow this up with a separate PR.
python/uv/private/lock.bzl
Outdated
args.run_shell.add("--no-progress") | ||
args.run_shell.add("--quiet") | ||
|
||
ctx.actions.run_shell( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm having trouble understanding why this step needs the copy step as part of its execution.
Isn't this the same behavior?
srcs = list(ctx.attr.srcs)
if existing_file:
srcs.append(existing_file)
output = declare_file(name + ".out")
ctx.actions.run([uv, "--output={output}"] + srcs, inputs=srcs, output=output)
uv is going to overwrite whatever --output specifies, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
uv
expects the previous output to be in the location that is defined by --output={output}
. If you pass it as a source then you will have extra log lines via requirements-existing.txt
, which is not what you want here.
# FIXME @aignas 2025-03-17: should we have one more target that transitions | ||
# the python_version to ensure that if somebody calls `bazel build | ||
# :requirements` that it is locked with the right `python_version`? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A separate target, no. An attribute with rule-level cfg transition, yes.
This also enables tricks like this:
lock(python_version="3.10", srcs=select(":py310": "requirements_310.txt", ...))
Similarly, because an attr.output
is not used, the outputs can be varied to e.g. include the python version (or platform, etc) into the output file name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the nudge. I have added the transition to the lock rule and I think the overall design is now simpler.
I have also created an internal expand_template
rule that makes the wiring of files easier. I have added the python version to the file name, so it might be both, a good and a bad decision and we will see. :)
…ects in the output attr
RBE is failing with an error:
Not sure exactly why this is happening because I am passing I think the documentation mentioning to use EDIT: this guess was wrong. I am fiddling with the EDIT2: the |
This change implements the uv pip compile as a rule.
In order to also make things easier to debug we provide
a runnable rule that has the same arguments and updates
the source tree output file automatically.
The main design is to have a regular lock rule and then
it returns a custom provider that has all of the recipe
ingredients to construct an executable rule. The execution
depends on having
bash
orbat
files on Windows when runningthe debugging rule target.
There are integration tests that exercise the locker. However,
things that are untested:
running the
uv
binary. Need help from some Windows users.RBE
seems to not workbut locking when using
RBE
still works - there is anative_test
exercising this.
keyring
integration to pull packages from privateindex servers. https://docs.astral.sh/uv/configuration/authentication/
should be supported.
Work towards #1325
Work towards #1975
Related #2663