Skip to content

Maven: recover duplicate-resolved dependency edges hidden by the depgraph plugin#1730

Draft
saramaebee wants to merge 3 commits into
masterfrom
sara/maven-duplicate-edges
Draft

Maven: recover duplicate-resolved dependency edges hidden by the depgraph plugin#1730
saramaebee wants to merge 3 commits into
masterfrom
sara/maven-duplicate-edges

Conversation

@saramaebee

@saramaebee saramaebee commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Overview

Maven attaches a package shared by several parents to a single winning parent, and the depgraph plugin's aggregate goal can only emit those winning edges — it hardcodes NodeResolution.INCLUDED and has no showDuplicates option, and its text format can't express duplicate edges regardless of flags. The uploaded graph therefore shows a shared transitive dependency under only one parent, and dependency paths under-report who actually uses it.

This PR adds a best-effort second run of the plugin's graph goal with -DshowDuplicates=true (JSON output; runs per reactor module in one mvn invocation) and merges the recovered OMITTED_FOR_DUPLICATE edges into the aggregate output before the graph is built. Any failure falls back to current behavior with a warning.

Two details worth knowing: edges join to artifacts by string id because the plugin's numericId/numericFrom/numericTo use unrelated counters; and OMITTED_FOR_CONFLICT edges are skipped since they point at losing versions the build doesn't ship.

Acceptance criteria

Given poi-ooxml -> log4j-api plus a direct log4j-core dependency that also imports log4j-api, fossa analyze now reports both parent edges instead of only Maven's winner, and dependency paths in the app show all real paths.

Testing plan

  1. cabal test unit-tests --test-options='-m "Maven"' — new specs cover the JSON decoding (including the numeric-id mismatch) and merge semantics (ignores INCLUDED edges and unknown artifacts, no self-edges, idempotent).
  2. End-to-end: ran the built CLI's fossa analyze -o on a demo project with the scenario above. Before: log4j-core and postgresql had imports: []. After: log4j-core -> log4j-api and postgresql -> checker-qual are present.

Risks

One extra mvn invocation per Maven analysis (plugin is already installed; failures are non-fatal by construction). The legacy 3.3.0 plugin path gets the same step and degrades gracefully if unsupported.

Metrics

None added. The Running plugin to recover duplicate-resolved edges context appears in debug bundles.

References

Root-caused during a customer engagement where OEM-vendored transitive dependencies were mis-attributed to a single parent, breaking package-label workflows that rely on accurate dependency paths.

🤖 Generated with Claude Code

saramaebee and others added 3 commits July 8, 2026 18:27
…plugin

Maven's dependency mediation attaches a package shared by several parents
to a single winning parent. The depgraph plugin's aggregate goal only ever
emits those winning edges (it hardcodes NodeResolution.INCLUDED), and its
text format cannot express duplicates regardless of flags, so the CLI
uploads a graph in which a shared transitive dependency appears exclusive
to one parent. Downstream, dependency paths under-report who actually uses
a shared package.

Recover the omitted edges with a second, best-effort plugin invocation:
the non-aggregating graph goal with showDuplicates=true emits JSON in
which Maven's verbose graph reports the hidden edges as
OMITTED_FOR_DUPLICATE. Those edges are merged into the aggregate output
before the graph is built. On any failure the aggregate output is used
unchanged, matching previous behavior.

Edges are joined to artifacts via the JSON string ids: depgraph's
numericId / numericFrom / numericTo use two unrelated counters and cannot
be used as a join key.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X9wbLEaAC42dirqDFT7eEn
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X9wbLEaAC42dirqDFT7eEn
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X9wbLEaAC42dirqDFT7eEn
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