Feature request: Add native uv support and configuration
- Dominant language
- Python
- Stars
- 380
- Forks
- 161
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 2
Description
### Describe your idea/feature/enhancement
I wish the AWS Lambda Builders would support native `uv` usage instead of using `uv export` to facilitate dependency management (as designed [here](https://github.com/aws/aws-lambda-builders/blob/051c6ef2fd0079190c758f1622af7a68e48eb723/aws_lambda_builders/workflows/python_uv/DESIGN.md)).
I know that experimental uv support was just added (related: https://github.com/aws/aws-lambda-builders/pull/756 and https://github.com/aws/aws-lambda-builders/issues/818). It mirrors the workaround I've been using for a while, but lacks certain capabilities that I need (and also have workarounds for).
### Additional Details
It would be nice to be able to pass certain variables or arguments in order to use specific `uv` features, like described below
1. I noticed that the `uv export` doesn't include a `--no-dev`, which bloats the final artifact:
https://github.com/aws/aws-lambda-builders/blob/ed7d955598e4f8974f9baba25cf1600176aa0054/aws_lambda_builders/workflows/python_uv/packager.py#L326-L338
This seems to be in conflict with one statement from the design document:
https://github.com/aws/aws-lambda-builders/blob/051c6ef2fd0079190c758f1622af7a68e48eb723/aws_lambda_builders/workflows/python_uv/DESIGN.md?plain=1#L26
2. Currently, `--no-hashes` is hard coded, but in my environment I do require hashes in my `pyproject.toml`. This causes an issue because my `[tool.uv.pip]` config leaks into the builder subprocess, causing a conflict.
I'm not sure what phase things are currently in, given this is deployed, but still experimental, but I did note the following:
https://github.com/aws/aws-lambda-builders/blob/051c6ef2fd0079190c758f1622af7a68e48eb723/aws_lambda_builders/workflows/python_uv/DESIGN.md?plain=1#L311-L329
Which mentions "Advanced configuration options", and so it may be planned, future work to add support for `--no-dev`, etc.
3. It would be very useful to be able to natively mount a local package into the final build artifact. I already support this in my flow which wraps `aws-lambda-builder`/`sam` but I'd rather it be supported natively
I had Opus 4.6 do a write-up of some of the details/issues it had migrating from my current workaround to the new experimental approach, which may be helpful. I'm doing this with the `sam` cli.
Details
```md
Upstream Issues in aws-lambda-builders UV Workflow
All bugs are in the experimental PythonUvBuilder workflow (aws-lambda-builders, shipped with SAM CLI >= 1.155.2). The
relevant code lives in aws_lambda_builders/workflows/python_uv/.
Bug 1: Dev dependencies included in build artifact
File: packager.py, _build_from_lock_file() ~line 326-338
Problem: The uv export command is missing --no-dev. All dependencies from [dependency-groups] dev in pyproject.toml
are exported and installed into the Lambda artifact.
Impact: Build artifact balloons from ~144M to ~408M (in our case), including pytest, pyright, cfn-lint, coverage,
etc. Exceeds Lambda's 250MB unzipped size limit.
Expected: uv export should include --no-dev to exclude development dependencies from production builds.
Current code:
export_args = [
"export",
"--format", "requirements.txt",
"--no-emit-project",
"--no-hashes",
"--output-file", temp_requirements,
"--python", python_version,
]
Fix: Add "--no-dev" to export_args.
---
Bug 2: --cached mode fails with CopyDependenciesAction
File: workflow.py, _setup_build_actions() ~line 142-151
Problem: When --cached is used (i.e. dependencies_dir is set), deps are installed to .aws-sam/deps// but the
CopyDependenciesAction is constructed with swapped semantics. It tries to os.listdir(artifact_dir)
(.aws-sam/build/ExampleFunction) which doesn't exist yet — the deps are in destination_dir (.aws-sam/deps/).
Error: [Errno 2] No such file or directory: '.aws-sam/build/ExampleFunction'
Current code:
CopyDependenciesAction(
source_dir=source_dir,
artifact_dir=artifacts_dir, # .aws-sam/build/ExampleFunction (empty)
destination_dir=self.dependencies_dir, # .aws-sam/deps/... (has deps)
)
The DependencyManager.yield_source_dest() does os.listdir(self._artifact_dir) then copies FROM artifact_dir TO
dest_dir — which is backwards. Deps are in dependencies_dir but it tries to read from artifacts_dir.
Impact: Every sam build with --cached fails for the UV workflow. Without --cached, builds always re-download deps.
---
Bug 3: [tool.uv.pip] config leaks into builder subprocess
File: packager.py, _build_from_lock_file() ~line 345-353
Problem: The uv pip install command runs with cwd=project_dir, which makes uv read [tool.uv.pip] settings from the
project's pyproject.toml. If the project has require-hashes = true (common security practice), but the builder
exported with --no-hashes, uv pip install fails because it requires hashes that aren't present.
Error: error: In --require-hashes mode, all requirements must have a hash, but none were provided for: aenum==3.1.16
Root cause: The builder explicitly exports with --no-hashes (line 331) but doesn't account for the project's
[tool.uv.pip] config overriding the install behavior. The uv pip install inherits the project's pyproject.toml
settings since it runs from the project directory.
Possible fixes:
- Pass --no-verify-hashes to the uv pip install command
- Run uv pip install with UV_NO_VERIFY_HASHES=true in the subprocess env
- Export WITH hashes instead of --no-hashes (then the require-hashes config is satisfied)
- Run uv pip install from a temp dir without pyproject.toml context
---
Our Workarounds
┌────────────────────────┬───────────────────────────────────────────────────────────────────────────┐
│ Bug │ Workaround │
├────────────────────────┼───────────────────────────────────────────────────────────────────────────┤
│ Bug 1 (dev deps) │ Generate our own uv export --no-dev requirements file, pass as --manifest │
├────────────────────────┼───────────────────────────────────────────────────────────────────────────┤
│ Bug 2 (--cached) │ Don't use --cached flag │
├────────────────────────┼───────────────────────────────────────────────────────────────────────────┤
│ Bug 3 (require-hashes) │ Removed generate-hashes/require-hashes from pyproject.toml [tool.uv.pip] │
└────────────────────────┴───────────────────────────────────────────────────────────────────────────┘
Bugs 1 and 2 are worked around by the same mechanism: since we generate our own requirements-*.txt via uv export
--no-dev --no-hashes --frozen --no-emit-project, the lambda-builders use the _build_from_requirements path (simple uv
pip install -r) instead of the buggy _build_from_lock_file path. This also avoids the --cached
CopyDependenciesAction issue since we don't use --cached.
```
Contributor guide
Assessment
This issue has not been assessed yet.