[#12302] Fix TransitiveDependencyManager version downgrade from parent-inherited depMgmt#12316
Closed
gnodet wants to merge 2 commits into
Closed
[#12302] Fix TransitiveDependencyManager version downgrade from parent-inherited depMgmt#12316gnodet wants to merge 2 commits into
gnodet wants to merge 2 commits into
Conversation
Adds integration test that verifies TransitiveDependencyManager does not silently downgrade dependency versions when an intermediate POM's <dependencyManagement> declares a lower version of a transitive dependency. Dependency chain: root → module-a:1.0 (parent=parent-a) → module-b:1.0 → lib-c:2.0 parent-a manages lib-c to 1.0 Expected: lib-c resolves to 2.0 (declared by module-b) Actual (bug): lib-c downgraded to 1.0 by parent-a's dependencyManagement because TransitiveDependencyManager has deriveUntil=MAX_VALUE. This test is expected to FAIL (RED) until the fix is applied.
…dependency descriptors TransitiveDependencyManager collects <dependencyManagement> from every POM in the dependency graph. When a POM inherits depMgmt from its parent, those entries leak into the transitive graph and can override version declarations in deeper dependencies, causing unintended version downgrades. The fix strips parent-inherited depMgmt entries in DefaultArtifactDescriptorReader.loadPom() before passing the model to the resolver. Only entries directly declared in the POM (or from its own BOM imports) are kept. This is safe because ArtifactDescriptorReader is only called for transitive dependencies — the root project's depMgmt goes via CollectRequest.setManagedDependencies(). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Contributor
Author
|
Closing this PR — after discussion with Tamas, the current behavior is correct.
The fix for consumers who need a different version is to explicitly declare the dependency in their own Claude Code on behalf of Guillaume Nodet |
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.
Summary
<dependencyManagement>entries from transitive dependency descriptors to preventTransitiveDependencyManagerfrom propagating them through the dependency graphProblem
When a transitive dependency's parent POM declares
<dependencyManagement>, those entries are inherited into the child's effective model.TransitiveDependencyManagercollects depMgmt from every POM in the graph and applies it at depth 2+, causing parent-inherited management rules to override version declarations in deeper transitive dependencies.Example:
root → module-a (parent=parent-a, manages lib-c:1.0) → module-b → lib-c:2.0. Parent-a'slib-c:1.0management leaks through module-a and downgradeslib-cfrom 2.0 to 1.0.Fix
In
DefaultArtifactDescriptorReader.loadPom(), compare the effective model's depMgmt with the parent model's depMgmt. Entries that appear in both with the same key and version are parent-inherited and stripped. This is safe becauseArtifactDescriptorReaderis only called for transitive dependencies — the root project's depMgmt goes viaCollectRequest.setManagedDependencies().Applied to both
impl/maven-implandcompat/maven-resolver-provider.Test plan
gh-12302IT:lib-c:2.0resolved correctly (not downgraded to 1.0)MNG-8347transitive mode: level4 managed by level2's own depMgmt, level3 unmanaged, root wins for level5/6MNG-7982non-transitive mode: only root depMgmt applies (Maven 3 behavior preserved)Fixes #12302
🤖 Generated with Claude Code