Skip to content

fix(uv): prefer uv.lock versions in parser output#15074

Open
Nishnha wants to merge 2 commits into
mainfrom
nishnha/uv-prefer-lockfile-version-over-requirements-txt
Open

fix(uv): prefer uv.lock versions in parser output#15074
Nishnha wants to merge 2 commits into
mainfrom
nishnha/uv-prefer-lockfile-version-over-requirements-txt

Conversation

@Nishnha
Copy link
Copy Markdown
Member

@Nishnha Nishnha commented May 19, 2026

What are you trying to accomplish?

Fix the underlying bug from #14954 (which I had to roll back because it broke the file updater). Credit to @jmcgrath-tractian for the original report and fixture.

When both uv.lock and a requirements.txt / .in file list the same package, Dependabot::Uv::FileParser#parse previously returned the requirements.txt version. DependencySet#combined_version prefers the entry whose top_level? is true, and uv.lock entries always have empty requirements: [], so the requirements.txt entry wins — even when it is stale.

Result: the dependency graph reports the stale version, and Dependabot security alerts don't auto-dismiss after uv lock has already shipped the patched version.

What changed

Follows @v-HaripriyaC's suggestion on #14954 to move the fix out of "skip the requirements parser entirely" and into dependency selection:

  • Build the full dependency set as before (pyproject + uv.lock + requirements.*)
  • Then post-process it: any package that also appears in uv.lock takes the lockfile-resolved version, while keeping the requirements collected from other files
  • Lift uv.lock parsing into a dedicated FileParser::LockFileDependencyParser helper

Net effect:

  • The dependency graph gets the correct uv.lock version
  • The FileUpdater still sees the requirements.txt entry in dep.requirements, so it can update those files when needed — no spike in Expected lockfile to change! from LockFileUpdater#fetch_updated_dependency_files
  • Packages that appear only in requirements.txt (no uv.lock entry) are unaffected

Tests

Three new specs in uv/spec/dependabot/uv/file_parser_spec.rb:

  • stale requirements.txt + uv.lock → parser returns the uv.lock version
  • same scenario → requirements.txt is still listed in the dep's requirements (so the file updater path still works)
  • package only in requirements.txt (not in uv.lock) → still parsed normally

Verified all 70 file_parser_spec examples plus dependency_grapher_spec and file_updater_spec pass. The one workspace-member failure that shows up is pre-existing on main.

Checklist

  • I have run the complete test suite to ensure all tests and linters pass.
  • I have thoroughly tested my code changes to ensure they work as expected, including adding additional tests for new functionality.
  • I have written clear and descriptive commit messages.
  • I have provided a detailed description of the changes in the pull request, including the problem it addresses, how it fixes the problem, and any relevant details about the implementation.
  • I have ensured that the code is well-documented and easy to understand.

When both uv.lock and a requirements.txt/.in file list the same package, the
parser previously returned the requirements.txt version (because DependencySet
prefers a top_level? entry, and uv.lock entries have empty requirements). That
caused stale versions to be submitted to the dependency graph and blocked
Dependabot security alerts from auto-dismissing after a uv lock had already
shipped the patched version.

PR #14954 attempted to skip requirement_dependencies entirely when uv.lock was
present, but that stripped requirements from deps that the FileUpdater needs to
update, surfacing as a spike in 'Expected lockfile to change!' errors in
LockFileUpdater#fetch_updated_dependency_files.

Instead, build the full dependency set as before, then post-process it so any
package that also appears in uv.lock takes the lockfile-resolved version while
keeping its requirements (so the FileUpdater can still operate on those files).
Lift the lockfile parsing into a dedicated LockFileDependencyParser helper.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Nishnha Nishnha requested a review from a team as a code owner May 19, 2026 18:42
Copilot AI review requested due to automatic review settings May 19, 2026 18:42
Copy link
Copy Markdown
Contributor

Copilot AI left a 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 fixes uv dependency parsing so resolved versions from uv.lock are preferred over stale versions from requirements files while preserving requirements metadata for file updates.

Changes:

  • Adds a nested LockFileDependencyParser helper for parsing uv.lock.
  • Post-processes parsed dependencies to replace versions with lockfile-resolved versions when available.
  • Adds specs covering stale requirements files and requirements-only packages.
Show a summary per file
File Description
uv/lib/dependabot/uv/file_parser.rb Wires in the lockfile parser and applies lockfile version preference after building the full dependency set.
uv/lib/dependabot/uv/file_parser/lock_file_dependency_parser.rb Adds uv.lock parsing and dependency version preference logic.
uv/spec/dependabot/uv/file_parser_spec.rb Adds regression coverage for stale requirements versions and requirements preservation.

Copilot's findings

  • Files reviewed: 3/3 changed files
  • Comments generated: 0

Rename prefer_lockfile_versions -> override_with_lockfile_versions and split
out override_version so the two early-return cases (not-in-lockfile, version
already correct) are obvious. Add a comment on the public method explaining
why we override after DependencySet has merged, not before.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

@brrygrdn brrygrdn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, this makes sense to me from a dependency graphing perspective. Because it affects updates as well I'll hold off on giving a formal ✅ as it's probably worth a second pair of eyes

@jakecoffman
Copy link
Copy Markdown
Member

Wait, why is the uv ecosystem fetching and parsing requirements.txt and .in files?

@Nishnha
Copy link
Copy Markdown
Member Author

Nishnha commented May 21, 2026

Wait, why is the uv ecosystem fetching and parsing requirements.txt and .in files?

Yeah good question - customers can have both in their repo and uv lets you export lockfiles to requirements.txt https://docs.astral.sh/uv/concepts/projects/export/#requirementstxt-format

But we can also go the route of ignoring requirements.txt for uv graph jobs. I'll take a look at that option.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants