Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
- Maven dependencies with missing or invalid POMs are reported in every module that uses them, `system`-scope jars reach reachability analysis, and a failing dependency no longer fails scopes that `excludeConfigs` leaves out or the build when it lost a version conflict.
- Reachability scans that hit unresolved JVM dependencies now point out that ignoring them also needs `--reach-continue-on-install-errors`.
- A Gradle dependency whose variant is ambiguous in every configuration of its project now fails the run instead of quietly dropping out of the scan.
- Gradle dependencies that fail dependency verification, or whose jars cannot be fetched, are reported instead of passed on as healthy.
- Failed Gradle project dependencies are reported instead of silently dropping everything they pull in, and failures name the version that actually failed.

## [1.10.0](https://github.com/SocketDev/socket-cli/releases/tag/v1.10.0) - 2026-10-22

Expand Down
28 changes: 26 additions & 2 deletions src/commands/manifest/scripts/resolution-report-gradle.mts
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,26 @@ export function classifyGradleFailure(detail: string): FailureCategory {
) {
return 'no-matching-variant'
}
if (t.includes('cannot choose between')) {
// The artifact-level form: several transforms produce the requested variant
// ("transformation chains" from Gradle 8.12, "transforms" before it).
if (
t.includes('cannot choose between') ||
t.includes('found multiple transformation chains') ||
t.includes('found multiple transforms that can produce a variant')
) {
return 'variant-ambiguity'
}
// One line per problem of the artifact; a checksum missing from the
// metadata is no evidence against it, unlike any other problem.
const problems = t.split('\n').filter(l => l.startsWith('on artifact '))
if (
problems.length &&
problems.every(l =>
l.endsWith(': checksum is missing from verification metadata.'),
)
) {
return 'checksum-missing'
}
if (
t.includes('could not get') ||
t.includes('could not head') ||
Expand All @@ -46,7 +63,8 @@ export function classifyGradleFailure(detail: string): FailureCategory {
// Every kind blocks except variant-ambiguity: the module demonstrably exists
// and is almost always captured via another configuration, so it's benign for
// the SBOM (non-blocking, count only). The renderer blocks it anyway when the
// module resolved in no configuration of its project.
// module resolved in no configuration of its project. Nor does checksum-missing:
// teams often record checksums only for what their own tasks resolve.
export const GRADLE_DIALECT: ResolutionDialect = {
label: 'Gradle',
classify: classifyGradleFailure,
Expand Down Expand Up @@ -95,5 +113,11 @@ export const GRADLE_DIALECT: ResolutionDialect = {
notice: (n, depCount, configCount) =>
`Skipped ${depCount} dependency(ies) with ambiguous variant selection in ${configCount} configuration(s) — re-run with --verbose for ${n}'s messages.`,
},
{
key: 'checksum-missing',
blocking: false,
notice: (n, depCount, configCount) =>
`Left ${depCount} dependency(ies) uninstalled in ${configCount} configuration(s): ${n}'s verification metadata has no checksum for their artifacts — re-run with --verbose for ${n}'s messages.`,
},
],
}
1 change: 1 addition & 0 deletions src/commands/manifest/scripts/resolution-report-render.mts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export type FailureCategory =
| 'no-matching-variant'
| 'capability-conflict'
| 'variant-ambiguity'
| 'checksum-missing'
| 'repository-or-network'
| 'config-problem'
| 'other'
Expand Down
58 changes: 58 additions & 0 deletions src/commands/manifest/scripts/resolution-report-render.test.mts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
REACH_CONTINUE_ON_INSTALL_ERRORS_FLAG,
renderResolutionErrorReport,
} from './resolution-report-render.mts'
import { moduleKey } from './resolution-report.mts'

import type { BuildOptionHints } from './resolution-report-render.mts'
import type { ResolutionFailure } from './resolution-report.mts'
Expand Down Expand Up @@ -49,6 +50,63 @@ describe('resolution failure classification', () => {
expect(r.nonBlockingNotice).toContain('ambiguous variant')
})

it.each([
'Found multiple transformation chains that produce a variant of com.example:amb:1.0',
'Found multiple transforms that can produce a variant of com.example:amb:1.0',
])(
'classifies an ambiguous Gradle artifact transform as variant ambiguity: %s',
detail => {
const r = renderResolutionErrorReport(
[f('com.example:amb:1.0', detail)],
['runtimeClasspath'],
'gradle',
)
expect(r.hasBlockingFailures).toBe(false)
expect(r.nonBlockingNotice).toContain('ambiguous variant')
},
)

it('treats a checksum missing from Gradle verification metadata as non-blocking, unlike a mismatch', () => {
const header =
"Dependency verification failed for configuration ':runtimeClasspath':"
const missing = renderResolutionErrorReport(
[
f(
'com.example:lib:1.0',
`${header}\nOn artifact lib-1.0.jar (com.example:lib:1.0) in repository 'maven': checksum is missing from verification metadata.`,
),
],
['runtimeClasspath'],
'gradle',
{ resolvedModules: new Set([moduleKey(':', 'com.example:lib')]) },
)
expect(missing.hasBlockingFailures).toBe(false)
expect(missing.nonBlockingNotice).toContain('no checksum')
const mismatch = renderResolutionErrorReport(
[
f(
'com.example:lib:1.0',
`${header}\nOn artifact lib-1.0.jar (com.example:lib:1.0) in repository 'maven': expected a 'sha256' checksum of '00' but was '11'`,
),
],
['runtimeClasspath'],
'gradle',
)
expect(mismatch.hasBlockingFailures).toBe(true)
const both = renderResolutionErrorReport(
[
f(
'com.example:lib:1.0',
`${header}\nOn artifact lib-1.0.jar (com.example:lib:1.0) in repository 'a': checksum is missing from verification metadata.\nOn artifact lib-1.0.jar (com.example:lib:1.0) in repository 'b': expected a 'sha256' checksum of '00' but was '11'`,
),
],
['runtimeClasspath'],
'gradle',
{ resolvedModules: new Set([moduleKey(':', 'com.example:lib')]) },
)
expect(both.hasBlockingFailures).toBe(true)
})

it("classifies Gradle's 'unable to find a matching variant' phrasing as blocking no-matching-variant", () => {
const r = renderResolutionErrorReport(
[
Expand Down
3 changes: 3 additions & 0 deletions src/commands/manifest/scripts/run.mts
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,9 @@ async function invokeGradle(
'--init-script',
initScript,
'-Dorg.gradle.configuration-cache=false',
// Names each artifact's own verification problem, so a checksum missing
// from the metadata can be told apart from a mismatch.
'-Porg.gradle.dependency.verification.console=verbose',
`-Psocket.recordsFile=${recordsFile}`,
...commonProps(opts, '-P'),
...(opts.toolOpts ?? []),
Expand Down
Loading
Loading