Fix Gradle scan crash and build impact paths per module - #190
Draft
Jordanh1996 wants to merge 6 commits into
Draft
Jordanh1996 wants to merge 6 commits into
Jordanh1996 wants to merge 6 commits into
Conversation
A component that appears in more than one module's dependency-tree file may be resolved there with different transitive dependencies. Replacing the node let the last file win, which could leave a transitive dependency with no parent at all and crash impact-graph construction.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The prior assertions on 'modb' were vacuously true whether or not module scopes aliased the merged node map, since 'modb' never resolves commons-lang3 in its own file. Assert on modb's own commons-text node's children instead, which does regress if a module's DepTreeNode is aliased to the merged map's node. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Jordanh1996
requested a deployment
to
frogbot
September 22, 2026 17:21 — with
GitHub Actions
Waiting
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueComment |
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Jordanh1996
requested a deployment
to
frogbot
September 22, 2026 17:43 — with
GitHub Actions
Waiting
Read each module's dependency-tree file into its own module tree first, then merge those, so each step reads on its own. Fold the two shared-dependency tests into one and drop a test that only restated the DepTree constructor. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Jordanh1996
requested a deployment
to
frogbot
September 23, 2026 11:23 — with
GitHub Actions
Waiting
This branch is waiting to be deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Background
A Gradle build emits one dependency-tree file per module, and
GradleTreeBuildermerges them into asingle map keyed by component ID — one slot per component for the whole project. When two modules
resolve the same component differently, that difference cannot be represented.
The merge used
nodes.put, so the last file processed won. A transitive dependency reachable onlythrough the overwritten node lost its only parent edge, and the IDE plugin's impact-graph builder
then dereferenced a null parent set and aborted the entire scan:
jf auditon the same project succeeded, because the CLI keeps a tree per module rather than mergingthem.
What changed
gradle-dep-tree's ownGradleDependencyTreeUtils.addChild, which already merges. Scopes weresilently overwritten the same way and are now unioned too.
DepTreecarries the per-module trees alongside the merged map, andGradleTreeBuilderfills oneentry per dependency-tree file. The merged map stays exactly as it was —
createScanTreeneeds theunion to decide what to send to Xray — while consumers that must respect module boundaries, such as
impact-path construction, can now use the per-module trees.
DepTreekeeps a two-argument constructor, so the npm, Yarn, Go and PyPI builders are untouched andleave the module list empty.
The companion change in
jfrog-idea-pluginbuilds impact paths from these per-module trees. Withoutit, a dependency excluded by one module is still shown as reachable through it.
How this was verified
GradleTreeBuilderTestcases over a two-module fixture wheremodbexcludescommons-lang3from
commons-textandmodadoes not: the merged map keeps the edge, and the module trees staydistinct. Both fail without this change.
GradleTreeBuilderTestcases still pass.the stack trace above; after it, the scan completes and the vulnerable transitive dependency is
reported with its impact paths.
Notes for the reviewer
Two consequences of merging rather than replacing, both intended:
scopesin the merged map is now the union across modules instead of whichever filehappened to be read last. For multi-module Gradle projects this widens the IDE's scope filter, which
is the correct behaviour — a dependency really is in every configuration its modules resolve it under.
computeIfAbsentalso stops a later module's file from wipingdescriptorFilePathoff a module rootthat appears as a plain node elsewhere. Previously
puterased it, and the module was then sent toXray as if it were an external component.
MavenScanner.buildTreeinjfrog-idea-pluginbuilds a synthetic root over one flat map the sameway, so multi-module Maven is theoretically exposed to the same thing. It is not the reported bug and
is not reproduced here;
DepTreeModuleis deliberately ecosystem-neutral so Maven can adopt it later.About the red CI
The
testmatrix fails on every OS with the same three failures, all inJfrogCliDriverTest:testRunAudit_MultiMavenProject,testRunAudit_NpmProjectandtestRunAudit_WithExcludedPattern. They shell out to a realjf auditagainst a configured serverID and need credentials the PR build does not have. This branch does not touch them, and
master'sown
testworkflow has been failing since 30 April 2026.Everything this change touches passes in CI, including both new tests —
gradleTreeBuilderModuleScopesTest,gradleTreeBuilderSharedDependencyTest, and the fourpre-existing
GradleTreeBuilderTestcases.