Skip to content

[ANE-2886] Handle missing version field in uv.lock editable packages#1682

Open
zlav wants to merge 11 commits intomasterfrom
fix/uv-lock-optional-version
Open

[ANE-2886] Handle missing version field in uv.lock editable packages#1682
zlav wants to merge 11 commits intomasterfrom
fix/uv-lock-optional-version

Conversation

@zlav
Copy link
Copy Markdown
Member

@zlav zlav commented Apr 2, 2026

Overview

This PR fixes a parse error when FOSSA CLI encounters a uv.lock file containing editable/workspace packages with dynamic versions. The uv lockfile spec allows omitting the version field on source tree packages (editable, directory, virtual) that declare dynamic = ["version"] in their pyproject.toml. Our parser treated version as required, causing the file parse to fail and drop all dependencies.

This PR makes version optional in the parser and filters out versionless packages during graph construction.

Acceptance criteria

When users scan a project that has a uv.lock file containing editable/workspace packages without a version field, the CLI should successfully parse the lockfile and report all third-party dependencies instead of failing with:

Error: parsing file: ./backend/uv.lock["1214:3: missing key: version in package[83]"]

Testing plan

  1. Added a unit test should skip editable packages without a version that constructs a UvLock with a Nothing version on the root package and verifies the graph is built correctly with only the versioned dependencies.
  2. Added a TOML parsing integration test correctly parse uv.lock with editable package missing version with a new test fixture (test/Python/testdata/uv-editable.lock) that contains a [[package]] entry with source = { editable = "." } and no version field.
  3. Existing tests continue to pass with the updated Maybe Text version field.

Risks

Minimal. The change is surgical:

  • reqKey "version"\ -> optKey "version"` in the TOML parser
  • Text -> Maybe Text for the version field
  • Versionless packages filtered before graph construction
  • These packages are always the user's own project root (never third-party deps) and were already removed by shrinkRoots

References

Checklist

  • I added tests for this PR's change (or explained in the PR description why tests don't make sense).
  • If this PR introduced a user-visible change, I added documentation into docs/.
  • If this PR added docs, I added links as appropriate to the user manual's ToC in docs/README.ms and gave consideration to how discoverable or not my documentation is.
  • If this change is externally visible, I updated Changelog.md. If this PR did not mark a release, I added my changes into an ## Unreleased section at the top.
  • If I made changes to .fossa.yml or fossa-deps.{json.yml}, I updated docs/references/files/*.schema.json AND I have updated example files used by fossa init command. You may also need to update these if you have added/removed new dependency type (e.g. pip) or analysis target type (e.g. poetry).
  • If I made changes to a subcommand's options, I updated docs/references/subcommands/<subcommand>.md.

The uv lockfile format allows packages to omit the version field when they are source trees with dynamic versions. Our parser treated version as required, causing a fatal parse error that dropped all dependencies from the file.

Make version optional and filter out versionless packages during graph construction. These are always the users own project, never third-party deps, so they carry no license implications and were already removed by shrinkRoots.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@zlav zlav requested a review from a team as a code owner April 2, 2026 22:25
@zlav zlav requested a review from tjugdev April 2, 2026 22:25
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@zlav zlav removed the request for review from tjugdev April 2, 2026 22:25
@zlav zlav marked this pull request as draft April 2, 2026 22:25
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 2, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: bb0fb95e-aa47-49ab-b9a6-4b1e441114a0

📥 Commits

Reviewing files that changed from the base of the PR and between 3341930 and d0df380.

⛔ Files ignored due to path filters (1)
  • test/Python/testdata/uv-editable.lock is excluded by !**/*.lock
📒 Files selected for processing (3)
  • Changelog.md
  • src/Strategy/Python/Uv.hs
  • test/Python/UvSpec.hs

Walkthrough

The changes address parsing of uv.lock files with editable and workspace packages that lack explicit versions. The uvlockPackageVersion field in UvLockPackage was changed from Text to Maybe Text, making the version optional in TOML schema parsing. Corresponding updates were made to dependency version construction logic. Test fixtures and test cases were updated to reflect the optional version representation, including a new test case for editable packages without versions using test data from test/Python/testdata/uv-editable.lock.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: handling missing version fields in uv.lock editable packages, which is the core fix in this PR.
Description check ✅ Passed The PR description comprehensively covers all required template sections: Overview, Acceptance criteria, Testing plan, Risks, References, and a completed Checklist with explanations.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

zlav and others added 4 commits April 2, 2026 15:34
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
The previous approach filtered out versionless packages before graph
construction, which removed the root package too early and broke the
edge structure. The root package holds the prod/dev dependency lists
needed by markRootEnvs. Instead, include all packages in the graph and
let shrinkRoots naturally remove the versionless root after the graph
is properly built.

Also fixes fourmolu formatting (then/else indentation).

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
In uv-editable.lock, anyio and idna are only reachable via httpx (prod),
so they should have [EnvProduction] only — unlike the main uv.lock test
where starlette (dev) also reaches anyio.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@zlav
Copy link
Copy Markdown
Member Author

zlav commented Apr 3, 2026

@coderabbitai help

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 3, 2026

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

CodeRabbit commands

These commands are invoked using PR/Issue comments.

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai evaluate custom pre-merge check --instructions <custom-checks-instructions> --name <custom-checks-title> [--mode <error|warning>] to validate the custom pre-merge checks instructions. Defaults to error when --mode is omitted.
    • @coderabbitai ignore pre-merge checks to override pre-merge checks and get an approval on PR.
    • @coderabbitai run pre-merge checks to run pre-merge checks on the pull request.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve merge conflict to automatically resolve merge conflicts.
  • @coderabbitai autofix to automatically fix issues identified in unresolved review comments.
  • @coderabbitai resolve to resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai generate configuration to create a PR that adds the current resolved configuration as .coderabbit.yaml (or show it if already present).
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Status, support, documentation and community

  • Visit our status page to check the current availability of CodeRabbit.
  • Create a ticket on our support page for assistance with any issues or questions.
  • Visit our documentation site for detailed information on how to use CodeRabbit.
  • Join our Discord community to connect with other users and get help from the community.
  • Follow us on X/Twitter for updates and announcements.

@zlav
Copy link
Copy Markdown
Member Author

zlav commented Apr 3, 2026

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 3, 2026

✅ Actions performed

Full review triggered.

@zlav zlav requested a review from csasarak April 3, 2026 17:19
@zlav zlav marked this pull request as ready for review April 3, 2026 17:19
Copy link
Copy Markdown
Contributor

@csasarak csasarak left a comment

Choose a reason for hiding this comment

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

LG, I'd add some explanation around what an editable package actually is.

zlav and others added 5 commits April 3, 2026 11:49
Instead of relying solely on shrinkRoots to remove workspace packages,
explicitly parse the source field for editable/virtual keys and filter
them from the final graph using shrink (which rewires edges through
removed nodes to preserve transitivity).

This correctly handles workspace members that are not graph roots (e.g.,
a workspace member depended on by the root project) which would
previously survive shrinkRoots.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
The url field was parsed but never read anywhere. Only editable and
virtual are needed for workspace package detection.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
A package source is always exactly one of: editable, virtual, registry,
git, url, or path. A sum type makes this invariant unrepresentable to
violate — no more Maybe fields that could theoretically all be Nothing
or multiple be Just simultaneously.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Map UvLockPackageSource variants to the appropriate DepType:
- SourceGit -> GitType (URL as name, commit hash as version)
- SourcePath -> UnresolvedPathType (path as name)
- SourceUrl -> URLType (URL as name)
- SourceRegistry -> PipType (package name, unchanged)

Git URLs in uv.lock encode the commit hash as a URL fragment
(e.g., https://github.com/owner/repo?tag=v1#abc123), which is
extracted as the version.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants