-
Notifications
You must be signed in to change notification settings - Fork 1
chore: switch from downloading uv binaries to building it with the CLI #138
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
base: develop
Are you sure you want to change the base?
Conversation
|
|
||
| outputs = { self, nixpkgs, flake-utils, rust-overlay, naersk }: | ||
| flake-utils.lib.eachSystem [ "x86_64-linux" "aarch64-darwin" "x86_64-darwin" "aarch64-linux" ] (system: | ||
| outputs = |
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.
most of the changes in this file are unfortunately from just running nixfmt. Only real changes are in tower-rpm-{ARCH} and tower-deb-{ARCH} where we also copy and chmod uv-wrapper.
| @@ -1,2 +1,2 @@ | |||
| [toolchain] | |||
| channel = "1.88" | |||
| channel = "1.89" | |||
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 depends on at least this version of rust
1. It sucks to have a brittle bunch of uv downloads. I can guarantee you it won't work in NixOS ;) 2. We are building with cargo as part of the build process 3. UV is also in Rust, and can be built as part of the built process 4. We can add UV as a separate target in our Cargo.toml, and then build it accordingly 5. This lets us be able to delete the download files 6. Unfortunately, uv does not yet have a stable library interface to use directly in rust, and do not recommend you to do that. And calling the cli main function directly in the code means we would have to dramatically refactor our tokio code somehow 7. As such, we make a wrapper script that just calls the built code - it'll get installed next to the cli 8. To actually be able to depend on it, and see it working, add a `tower doctor` command that checks to see if it can find the uv we downloaded
This comment was marked as resolved.
This comment was marked as resolved.
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.
Pull request overview
This PR refactors the UV installation mechanism by building UV from source as a separate binary target instead of downloading pre-built binaries for different platforms. This eliminates the brittle platform-specific download logic and improves compatibility, particularly with NixOS. The implementation adds a uv-wrapper binary alongside the main tower CLI and includes a new tower doctor command to verify the installation.
Key changes:
- Replaced UV download logic with a build-from-source approach using a
uv-wrapperbinary - Added
tower doctorcommand to validate UV availability and configuration - Updated Rust toolchain from 1.88 to 1.89
Reviewed changes
Copilot reviewed 10 out of 12 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| rust-toolchain.toml | Updated Rust channel version to support new dependencies |
| flake.nix | Added uv-wrapper binary to package distributions and reformatted Nix code |
| crates/tower-uv/tests/install_test.rs | Replaced UV download test with wrapper existence verification |
| crates/tower-uv/src/lib.rs | Removed download logic and implemented wrapper discovery mechanism |
| crates/tower-uv/src/install.rs | Deleted entire platform-specific download implementation |
| crates/tower-uv/Cargo.toml | Added uv dependency and defined uv-wrapper binary target |
| crates/tower-cmd/src/lib.rs | Integrated doctor command into CLI |
| crates/tower-cmd/src/doctor.rs | New diagnostic command implementation |
| crates/tower-cmd/Cargo.toml | Added tower-uv dependency for doctor command |
| Cargo.toml | Updated minimum Rust version to 1.89 |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
I thought about this over night. I think the premise for the problem here is your first bullet point: It sucks to download Packaging |
|
Hmm, looks like I didn't post a reply, even though I was sure I had. I think this is what I said:
I think downloading executable code at runtime is a worry and a codesmell, and I think trying to divine what code is going to run on the machine we're currently running on is a brittle process that's likely to break. I know for a fact it doesn't work on NixOS, which isn't a huge concern usually (people truly using it tend to have workarounds involving I'm not too worried about relying on other people's infra — sure, it sucks to have to rely on infra to be up. But we rely on that same infra to be up when you install the software, and it's not like we do this every time on running, just the first time, so I don't think colocating the binaries improves resilience here much.
For me it's just the simplest and easiest solution, since it by definitions means that you can guarantee that the binary for tower and the binary for uv will be compatible — since they were built for the same architecture, at the same time, with the same process. And it's semantically the same as saying "this package depends upon this one being built", which is how we'd do it if it were a normal rust lib, so it feels like relying on cargo to deal with all that stuff for us is ideal. But I'm definitely not married to the idea. RE: the other options
But I think both of those are still preferable to downloading at runtime, so would be happy if we explore those too. As seen by the failing tests in the CI here, it clearly isn't a walk in the park to build a simultaneous binary with uv/maturin and expect it to always be where you want it, and all the solutions (e.g. the tests are always in a subdir, so let's always check the parent dir for the binary as well as the current one) seem like janky workarounds to me. IMO ideally we'd depend upon UV as a lib in cargo — since it is a dependency, and it is in rust, and it makes a lot of sense to me to then let cargo just do its thing. But as explored before, they both discourage that use case and also we would have to rearchitect how we spawn processes for runs, since we can't use the existing tokio code we have for that, except if we wrap their main CLI entry point, and spawn that... which is exactly what this PR does. |
Proof of concept - WDYT?
Reasoning:
tower doctorcommand that checks to see if it can find the uv we downloaded