Skip to content

feat(manifest): name failing JVM dependencies and remedies the command accepts - #1638

Merged
Jeppe Fredsgaard Blaabjerg (jfblaa) merged 5 commits into
v1.xfrom
jfblaa/dsi-resolution-hints
Oct 22, 2026
Merged

Jeppe Fredsgaard Blaabjerg (jfblaa) merged 5 commits into
v1.xfrom
jfblaa/dsi-resolution-hints

Conversation

@jfblaa

@jfblaa Jeppe Fredsgaard Blaabjerg (jfblaa) commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

LLM Description written by Claude Code:claude-opus-5-5

When JVM dependency resolution failed under --dynamic-sbom-inference, the CLI told users to re-run with flags the command silently ignores, suggested excluding a graph configuration that does not exist, and named the user's own module instead of the dependency that broke. This makes the report accurate and the remedies actionable, and makes Maven, Gradle and sbt report failures the same way.

Reporting

  • Failures name the dependency that failed, the subproject that needed it, and its configuration/scope where the build tool's graph has one. A failure the graph cannot place has no configuration, so excluding configurations is not offered as a fix for it.
  • Maven: a dependency whose POM cannot be fetched while building the graph is reported under its own scope (was: the module itself under a made-up graph configuration). Excluding that scope now clears it.
  • Remedies name only what the invoking command accepts: flags for socket manifest <tool>, --ignore-unresolved (new) for socket manifest dynamic-sbom-inference, and the failing build's own socket.json plus its setup wizard for scan, fix and auto-manifest.
  • socket scan create and socket scan reach warn about --ignore-unresolved, --exclude-configs, --include-configs and --verbose, which they read from socket.json.
  • verbose in socket.json is honored on the dynamic-sbom-inference path, and a build tool that cannot start says why (e.g. spawn mvn ENOENT).

Facts output

  • Unresolved dependencies are reported and left out of the facts for all three tools. Maven used to emit them without children; Gradle and sbt already left them out.
  • sbt: a failed update now retries leniently (missingOk) instead of excluding the named modules. Previously, when Coursier named a missing parent POM, the exclusion retry failed too and the whole project was silently emitted empty.

Where the tools don't give us more

  • sbt 1.3+ (Coursier) names a missing parent POM rather than the dependency that declares it, so that dependency stays in the facts; Ivy (sbt 0.13) names the dependency.
  • Maven 3.2's resolver drops a dependency whose POM failed from the graph, so it gets no scope there.
  • A jar that fails to download under --with-files is still reported by Maven but only logged by Gradle; aligning that would add new blocking failures for Gradle users.

Testing

  • New compat fixtures: maven-compat/smoke-test-graph-failure.sh (scopes, excluded scope, failed nodes not emitted) and sbt-compat/smoke-test-failure.sh (project survives, failures not emitted). Maven matrix 3.2.5 to 4.0.0-rc-6 and sbt 0.13.18 to 1.9.9 pass.
  • run-compat.sh now puts each row's JDK on PATH: the sbt launcher ignores JAVA_HOME, so sbt rows ran on whatever JDK was first on PATH.
  • Unit tests for the renderer remedies and the recursive generator. Full unit suite passes apart from the socket json tests (also failing on v1.x) and two socket fix tests that need network access.

Note

Medium Risk
Changes how unresolved JVM dependencies affect facts SBOM output and exit behavior across Maven, Gradle, and sbt; incorrect handling could under-report dependencies in scans, but changes are targeted at error reporting and fail-closed semantics with added tests.

Overview
Improves JVM manifest / dynamic SBOM inference when dependencies fail to resolve: errors name the failing coordinate, subproject, and scope where applicable, and remediation text only suggests options the command you ran actually supports (CLI flags vs each build's socket.json).

CLI behavior

  • Adds --ignore-unresolved to socket manifest dynamic-sbom-inference (overrides per-root socket.json).
  • Dynamic SBOM inference honors per-build verbose from cascaded socket.json and passes build-option hints so resolution errors point at the failing root's socket.json and socket manifest setup --dynamic-sbom-inference.
  • socket scan create / socket scan reach warn when users pass --ignore-unresolved, config filters, or --verbose (those are read from socket.json only).
  • Spawn failures for Maven/Gradle/sbt always include the underlying reason (e.g. missing mvn).

Facts pipeline (Maven, Gradle, sbt)

  • Failure/unscannable records carry a project field; unresolved deps are reported and omitted from emitted facts consistently.
  • Maven stops inventing module-level graph failures and attributes collection errors to the artifact and scopes in the graph.
  • sbt retries updates with missingOk instead of excluding failed modules, so resolved deps are kept when one dependency breaks.

Tests

  • New Maven/sbt compat smoke tests for graph-level failures and partial resolution; updated assertion scripts for the new record shape.

Reviewed by Cursor Bugbot for commit faa3bcc. Configure here.

…d accepts

When dependency resolution fails, the report now names the dependency that
failed, the subproject and scope that needed it, and only remedies the
invoking command actually accepts:

- Single-build manifest commands suggest their flags; `socket manifest
  dynamic-sbom-inference` gains --ignore-unresolved; scan/fix/auto-manifest
  point at the failing build's own socket.json and its setup wizard.
- Maven no longer reports a dependency-graph failure as a `graph`
  configuration against the module itself: it names the failing dependency
  and the scope it has in the graph, so excluding that scope clears it.
- Unresolved dependencies are reported and left out of the facts for Maven,
  Gradle and sbt alike. sbt retries leniently instead of excluding modules,
  so an unresolved dependency no longer empties the whole project.
- socket.json `verbose` is honored on the dynamic-sbom-inference path, a build
  tool that cannot start says why, and scan create/reach warn about build
  flags they read from socket.json instead.
The sbt launcher runs java from PATH and ignores JAVA_HOME, so every sbt row
ran on whatever JDK came first on PATH (and sbt 0.13 failed on a modern one).
…t warning

A build root outside the shell's directory got a socket.json hint that climbed
to the filesystem root; it now gets the absolute path. A failed last build root
no longer warns that the remaining roots cannot be classified.

@mtorp Martin Torp (mtorp) left a comment

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.

[agent] Reviewed 4943bad19d37. All 36 focused tests passed, and the live Maven and sbt failure fixtures passed. The two numbered inline comments cover the remaining JSON output and sbt diagnostic-size issues.

Comment thread src/commands/manifest/generate-recursive-manifests.mts
Comment thread src/commands/manifest/scripts/socket-facts.plugin.scala Outdated
With verbose set in socket.json, Maven's log was inherited onto stdout and
broke --json output. Streamed build output is a diagnostic, so it now goes to
stderr on every path.
Every failure carried the whole batch resolve message, so the records grew
quadratically with the number of failed modules. Each failure now keeps only
its module's part of the message.
@jfblaa
Jeppe Fredsgaard Blaabjerg (jfblaa) merged commit 3c5eced into v1.x Oct 22, 2026
10 checks passed
@jfblaa
Jeppe Fredsgaard Blaabjerg (jfblaa) deleted the jfblaa/dsi-resolution-hints branch October 22, 2026 12:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants