Repository navigation
fix(manifest): keep Maven dependencies below a skipped scope - #1720
Jeppe Fredsgaard Blaabjerg (jfblaa) wants to merge 2 commits into
Conversation
With --exclude-configs or --include-configs, the Maven facts extension cut off the whole subtree of a dependency whose scope it skips. Maven filters each node by its own scope and still walks past the nodes it drops, and a dependencyManagement scope is not derived from the parent's. A dependency managed to compile below a test dependency is on Maven's runtime classpath and in a packaged war, but was missing from the facts. The extension now walks the whole resolved graph and drops skipped nodes afterwards, keeping the edges Maven resolved between kept nodes. A kept node reached only through skipped ones is linked to its nearest kept ancestors, and is direct when the module is one of them; no other node gets an edge Maven did not resolve.
PR SummaryMedium Risk Overview A Maven compat regression ( Reviewed by Cursor Bugbot for commit 96bad72. Configure here. |
|
[agent] Benjamin Barslev Nielsen (@barslev), one open question for you on the With a scope excluded, the facts drop the excluded dependencies but keep the nodes Maven keeps below them. An excluded parent can still constrain a kept child, for example by declaring a version range for it. Facts carry resolved versions only, so that constraint never reaches depscan's fix computation, which works from the chain metadata stored in its backend. Our current thinking is to catch it with a validation step in Coana rather than changing the fix computation. Coana would check each Maven upgrade before or after applying it, possibly by re-resolving the patched POMs with Maven. That check would also catch REA-1166, where a managed entry without a We're also checking whether a range in some other dependency's |
|
[agent] Findings on version ranges, as promised above. Checked in source and by experiment on Maven 3.2.5, 3.9.9 and 4.0.0-rc-6.
So the constraint the facts lose matters only for fixes that rewrite a plain version. A post-fix re-resolution that checks the target version is now resolved catches exactly that case. |
… scope A range is a hard constraint whatever the scope declaring it, so an excluded test dependency's range still picks the version Maven ships. The kept dependency must keep its edge from the compile dependency whose own version lost the conflict, not become an orphan.
LLM Description written by Claude Code:claude-opus-5-5
Fixes REA-1162.
With
--exclude-configsor--include-configs, the Maven facts extension cut off the whole subtree of a dependency whose scope it skips. Maven keeps a node below such a dependency when the node's own scope passes, so dependencies Maven ships were missing from the facts, with nothing reported.How Maven behaves (checked across the supported range, 3.2.5 to 4.0.0-rc-6)
RepositoryUtils.toArtifacts(3.9.9, called byLifecycleDependencyResolver; the same in 3.2.5 and 4.0.0-rc-6).testdependency istest(JavaScopeDeriver). A scope set bydependencyManagementis not derived that way (ConflictResolver.deriveScopein resolver 1.9.22;ClassicConflictResolver.deriveScopein 2.0.21).compilebelow atestone ships. With Maven 3.9.9 and 4.0.0-rc-6,dependency:build-classpathfor the runtime scope and theWEB-INF/libof a packaged war both include it.mvn dependency:tree -Dscope=compiledoes not show it, because that view's filter hides a node's whole subtree.Change
Trade-off to weigh: that link skips the excluded nodes between, and a dependency reached only through an excluded direct dependency is marked direct, though no
<dependency>declares it. The alternative, keeping the excluded parents as structure, would put the excluded scope back into the SBOM.socket fix(Coana master, run on facts from this branch withtestexcluded)dependencyManagementsets the scope, Coana rewrites both versions in place.<dependencies>entry and stays on the runtime classpath. The transitive one gets adependencyManagemententry without<scope>, which replaces the parent'scompileand moves it off the runtime classpath. That is Coana's existing behaviour for any dependency whose managed scope comes from outside, with or without this change.Tests: a new compat smoke test,
smoke-test-excluded-scope.sh, passes on Maven 3.2.5, 3.6.3, 3.8.8, 3.9.9 and 4.0.0-rc-6, and the full Maven matrix passes. The v1.x jar fails it, missingmanagedanddeep. So does a first version that linked every kept node through skipped ones: it markedsharedandedirect and added alib -> eedge.🤖 Generated with Claude Code