Avoid broken build artifacts on build failure#17276
Conversation
EliteTK
left a comment
There was a problem hiding this comment.
Thanks for this!
I left a few comments, I'm somewhat new here so my colleagues might have additional comments.
It would be good to add an integration test in crates/uv/tests/it/build_backend.rs to check the error messages.
There's something to consider, this changes the behaviour for handling pre-existing built files. Currently we start by overwriting them. This means that in the case of a failure, the existing files are lost and replaced with incomplete new ones. Now we are only overwriting the files if we succeed. Personally it's what I would expect here.
But when reporting errors, the user will see something like "Failed to ... dist/project-0.1.0-py2.py3-none-any.whl", implying the specified file was not able to be built, but if they check, they will see there is a file there.
Could this be confusing and should we do something about it? I see a couple of options aside from just leaving it as is:
- Delete any target files before attempting to write the new ones
- Mention in error reporting that the (or we could make it easier for ourselves and just say "any") existing file has not been overwritten
|
@EliteTK
I'll go with Delete any target files before attempting to write the new ones. This ensures a consistent state where the existence of the target file directly indicates a successful build. I'll implement this by deleting the target file (if it exists) before creating the temporary file. |
|
@bybrooks regarding the deleting - feel free, although once we discuss this further, we might not want to go with that option, so also feel free to wait for a verdict there. There is no rush at least on my end. Main issue is that everyone else is on annual leave :) |
CodSpeed Performance ReportMerging #17276 will not alter performanceComparing Summary
|
Deleting the target file(s) before starting the build seems to be the easiest. No strong opinion, users shouldn't rely on a specific the state of |
Thanks for the reply. |
This MR contains the following updates: | Package | Update | Change | |---|---|---| | [astral-sh/uv](https://github.com/astral-sh/uv) | patch | `0.9.22` → `0.9.24` | MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot). **Proposed changes to behavior should be submitted there as MRs.** --- ### Release Notes <details> <summary>astral-sh/uv (astral-sh/uv)</summary> ### [`v0.9.24`](https://github.com/astral-sh/uv/blob/HEAD/CHANGELOG.md#0924) [Compare Source](astral-sh/uv@0.9.23...0.9.24) Released on 2026-01-09. ##### Bug fixes - Fix handling of `UV_NO_SYNC=1 uv run ...` ([#​17391](astral-sh/uv#17391)) - Rebuild dynamic distribution when version changes with `--no-cache` ([#​17387](astral-sh/uv#17387)) ##### Documentation - Add Rust language classifier ([#​17389](astral-sh/uv#17389)) ### [`v0.9.23`](https://github.com/astral-sh/uv/blob/HEAD/CHANGELOG.md#0923) [Compare Source](astral-sh/uv@0.9.22...0.9.23) Released on 2026-01-09. ##### Enhancements - Only write portable paths in `RECORD` files ([#​17339](astral-sh/uv#17339)) - Support relative paths in `UV_PYTHON_BIN_DIR` and `UV_TOOL_BIN_DIR` ([#​17367](astral-sh/uv#17367)) ##### Preview features - Enable uploads to S3 via pre-signed URLs ([#​17349](astral-sh/uv#17349)) ##### Configuration - Allow setting proxy variables via global / user configuration ([#​16918](astral-sh/uv#16918)) - Manually parse and reconcile Boolean environment variables ([#​17321](astral-sh/uv#17321)) ##### Bug fixes - Avoid broken build artifacts on build failure ([#​17276](astral-sh/uv#17276)) - Fix missing dependencies on synthetic root in SBOM export ([#​17363](astral-sh/uv#17363)) - Recognize `armv8l` as an alias for `armv7l` in platform tag parsing ([#​17384](astral-sh/uv#17384)) - Fix redaction of a URL in a middleware trace log ([#​17346](astral-sh/uv#17346)) ##### Documentation - Add `index.md` suggestion to `llms.txt` ([#​17362](astral-sh/uv#17362)) - Clarify that `uv run` uses inexact syncing by default ([#​17366](astral-sh/uv#17366)) </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this MR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box --- This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi43NS4xIiwidXBkYXRlZEluVmVyIjoiNDIuNzUuMSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiUmVub3ZhdGUgQm90IiwiYXV0b21hdGlvbjpib3QtYXV0aG9yZWQiLCJkZXBlbmRlbmN5LXR5cGU6OnBhdGNoIl19-->
…ith `0o666 & !umask` permissions on `unix` platforms again (#18020) ## Summary Fix #18004. #17276 introduced a regression since `NamedTempFile::new_in` defaults to `0o600` permissions. Fortunately `uv_fs` already has a wrapper for a `new_in` with "normal" permissions this so this PR uses that. ## Test Plan Reliable testing would require us to support setting a umask for a test context process which we currently don't have support for and implementing it is not trivial so for now I just tested this manually. To test, you can just use: ```bash #!/usr/bin/env bash set -e tempdir=$(mktemp -d) trap 'rm -rf "$tempdir"' EXIT uv init --lib "$tempdir" cd "$tempdir" uv build umask ls -al dist/ ```
Summary
Fixes #17232
When
uv buildfails (e.g., due to missing__init__.py), partial distributionfiles were being left in the
dist/directory.Changes
NamedTempFileto write build output to a temporary file firstError::Persistvariant for handling persistence failuresTest Plan
Added
no_partial_files_on_build_failuretest that verifies:build_source_distfails when__init__.pyis missingbuild_wheelfails when__init__.pyis missingdist/directory remains empty after both failures (no partial files)