Skip to content

Vendetta: single-file and multi-location deps#1680

Open
nficca wants to merge 4 commits intomasterfrom
vendetta-file-and-multi-location-deps
Open

Vendetta: single-file and multi-location deps#1680
nficca wants to merge 4 commits intomasterfrom
vendetta-file-and-multi-location-deps

Conversation

@nficca
Copy link
Copy Markdown
Contributor

@nficca nficca commented Apr 1, 2026

Overview

Important

This is a breaking change. The ficus binary update (PR #163) and this CLI change must be released together.

This PR makes the following changes:

  • FicusVendoredDependency now parses "locations" (a JSON array) instead of "path" (a string).
  • vendoredDepsToSourceUnit is now effectful (IO) so it can stat each location to classify it as "file" or "directory" in the vendored metadata sent to Core. This is needed because single-file lib locations are files, not directories.
  • Each dependency's locations are flattened into sourceUnitOriginPaths and each gets its own entry in the "vendored" metadata array.

Acceptance criteria

  • Parse the new "locations" array from ficus vendetta findings
  • Correctly classify each location as file or directory in vendored metadata
  • All locations appear in sourceUnitOriginPaths

Testing plan

  1. Extract the following scan directory somewhere: scandir.tar.gz

This will be our target directory for scanning. It decompress to this:

$ tree -L 1 scandir
scandir
├── cgl.c
├── cgl.h
└── libpng

2 directories, 2 files
  1. Build a release version of Ficus using the branch from this PR.
cd /path/to/ficus
cargo build --release
  1. Copy the release bin to the CLI:
cp path/to/ficus/target/release/ficus ./vendor-bins/ficus
  1. Run the Sparkle server locally:
cd /path/to/sparkle
cargo run -p sparkle serve
  1. Run the caddy server for Sparkle:
cd /path/to/sparkle
sudo caddy run
  1. Insert the following into the Sparkle database:
INSERT INTO analysis_snippet_scan.single_file_lib (purl, reason)
VALUES ('pkg:github/jaysmito101/cgl', 'game library with single header and source file');
  1. Finally, run the CLI on this branch like so:
cabal run fossa analyze -- --x-vendetta \
  --endpoint http://localhost:8080 \
  --tee-output \
  ./scandir \
  | jq '.sourceUnits[].Build.Dependencies'

You should see the following:

[
  {
    "imports": [],
    "locator": "git+github.com/jaysmito101/cgl$411c131",
    "metadata": {
      "vendored": [
        {
          "path": "cgl.c",
          "type": "file"
        },
        {
          "path": "cgl.h",
          "type": "file"
        }
      ]
    }
  },
  {
    "imports": [],
    "locator": "git+github.com/glennrp/libpng$v1.6.54",
    "metadata": {
      "vendored": [
        {
          "path": "libpng",
          "type": "directory"
        }
      ]
    }
  }
]

Risks

Must be released in lockstep with https://github.com/fossas/ficus/pull/163 since the ficus binary is embedded in the CLI and the output format is changing.

Metrics

None

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.

@nficca nficca marked this pull request as ready for review April 2, 2026 16:00
@nficca nficca requested a review from a team as a code owner April 2, 2026 16:00
@nficca nficca requested a review from csasarak April 2, 2026 16:00
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 2, 2026

Walkthrough

This pull request refactors vendored dependency handling in the Ficus analyzer. The FicusVendoredDependency domain model changes from a single path field to a locations list. The vendoredDepsToSourceUnit function is redesigned from a pure function to an IO-based function that accepts a root directory, enabling filesystem inspection to classify each location as a file or directory. The sourceUnitOriginPaths derivation updates to flatten mapped locations. Control flow in runFicus is adjusted accordingly. Tests are added to verify multi-location support and type classification behavior.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Vendetta: single-file and multi-location deps' directly and specifically describes the main change—supporting single-file and multi-location vendored dependencies—which is the primary feature of this PR.
Description check ✅ Passed The description comprehensively covers all required template sections: Overview explains the breaking change and key modifications, Acceptance criteria lists three testable goals, Testing plan provides detailed step-by-step instructions with expected output, Risks highlights the lockstep release requirement, and all checklist items are marked complete with appropriate documentation and changelog updates.
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.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/App/Fossa/Ficus/Analyze.hs`:
- Around line 233-242: classifyLocation currently treats any non-file as
"directory" which misclassifies non-existent paths; update classifyLocation to
check existence explicitly by calling Directory.doesDirectoryExist fullPath (or
a combined exists check) in addition to Directory.doesFileExist, and set locType
to one of "file", "directory", or "not_found" (or similar) based on those
checks, keeping the same JSON shape but returning the explicit type for fullPath
and preserving the original path value loc.

In `@test/Ficus/FicusSpec.hs`:
- Around line 78-95: The test currently uses a fixed tmpDir name
"ficus-vendored-test" which can collide between parallel runs; replace the
tmpDir binding to create a unique temp directory via
Directory.createTempDirectory (use systemTmpDir and a prefix like
"ficus-vendored-test") and use the returned path for creating the vendored
subdir, writing files, calling vendoredDepsToSourceUnit, and for
Directory.removeDirectoryRecursive cleanup; update references to tmpDir in this
test block accordingly so the test uses and cleans up the unique directory.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

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

Review profile: ASSERTIVE

Plan: Pro

Run ID: 0f7345ce-bc46-4ef3-b9db-a3e43e749393

📥 Commits

Reviewing files that changed from the base of the PR and between d15da81 and dacdd8c.

📒 Files selected for processing (4)
  • Changelog.md
  • src/App/Fossa/Ficus/Analyze.hs
  • src/App/Fossa/Ficus/Types.hs
  • test/Ficus/FicusSpec.hs

Comment on lines +78 to +95
describe "vendoredDepsToSourceUnit" $ do
it "classifies directories and files correctly in vendored metadata" $ do
systemTmpDir <- Directory.getTemporaryDirectory
let tmpDir = systemTmpDir FP.</> "ficus-vendored-test"
Directory.createDirectoryIfMissing True (tmpDir FP.</> "vendored")
writeFile (tmpDir FP.</> "sqlite3.c") ""

let dep =
FicusVendoredDependency
{ ficusVendoredDependencyName = "github.com/test/dep"
, ficusVendoredDependencyEcosystem = "git"
, ficusVendoredDependencyVersion = Nothing
, ficusVendoredDependencyLocations = ["vendored", "sqlite3.c"]
}

result <- vendoredDepsToSourceUnit tmpDir [dep]

Directory.removeDirectoryRecursive tmpDir
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider using a unique temporary directory name.

Using a fixed temp directory name "ficus-vendored-test" could cause issues if tests run in parallel or if a previous test run left stale files. Consider using createTempDirectory to generate a unique directory name.

♻️ Suggested improvement
 describe "vendoredDepsToSourceUnit" $ do
     it "classifies directories and files correctly in vendored metadata" $ do
-      systemTmpDir <- Directory.getTemporaryDirectory
-      let tmpDir = systemTmpDir FP.</> "ficus-vendored-test"
-      Directory.createDirectoryIfMissing True (tmpDir FP.</> "vendored")
+      tmpDir <- Directory.createTempDirectory =<< Directory.getTemporaryDirectory $ "ficus-vendored-test"
+      Directory.createDirectoryIfMissing True (tmpDir FP.</> "vendored")
       writeFile (tmpDir FP.</> "sqlite3.c") ""
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/Ficus/FicusSpec.hs` around lines 78 - 95, The test currently uses a
fixed tmpDir name "ficus-vendored-test" which can collide between parallel runs;
replace the tmpDir binding to create a unique temp directory via
Directory.createTempDirectory (use systemTmpDir and a prefix like
"ficus-vendored-test") and use the returned path for creating the vendored
subdir, writing files, calling vendoredDepsToSourceUnit, and for
Directory.removeDirectoryRecursive cleanup; update references to tmpDir in this
test block accordingly so the test uses and cleans up the unique directory.

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.

1 participant