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
22 changes: 11 additions & 11 deletions src/commands/manifest/scripts/assemble.mts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,11 @@ export function assembleFacts(
const { directByRoot, finalNodes } = mergeByCoordinate(perRoot)

const tool = (parsed.tool || 'gradle') as SocketFactsSbomMetadata['tool']
const components = buildComponents(finalNodes)
const projectsByGav = new Map<string, RawProject>()
Comment thread
jfblaa marked this conversation as resolved.
for (const p of parsed.projects.values()) {
projectsByGav.set(gav(p.group, p.name, p.version), p)
}
const components = buildComponents(finalNodes, projectsByGav)
const projects =
opts.emitProjects === false
? []
Expand All @@ -77,6 +81,7 @@ export function assembleFacts(
artifactPaths: buildArtifactPaths(
finalNodes,
[...parsed.projects.values()],
projectsByGav,
perRoot,
fileExists,
),
Expand Down Expand Up @@ -173,6 +178,7 @@ function mergeByCoordinate(perRoot: Map<string, PerRoot>): {

function buildComponents(
finalNodes: Map<string, MergedNode>,
projectsByGav: Map<string, RawProject>,
): SocketFactsSbomComponent[] {
return [...finalNodes.keys()].sort().map(id => {
const fn = finalNodes.get(id)!
Expand Down Expand Up @@ -200,6 +206,9 @@ function buildComponents(
if (!fn.prod) {
comp.dev = true
}
if (projectsByGav.has(gav(c.group, c.name, c.version ?? ''))) {
comp.firstParty = true
}
if (fn.children.size) {
comp.dependencies = [...fn.children].sort()
}
Expand Down Expand Up @@ -303,19 +312,10 @@ function buildClasspathByProject(
function buildArtifactPaths(
finalNodes: Map<string, MergedNode>,
projects: RawProject[],
projectsByGav: Map<string, RawProject>,
perRoot: Map<string, PerRoot>,
fileExists: (path: string) => boolean,
): ResolvedArtifactPaths {
const projectsByGav = new Map<
string,
{ sources: string[]; targets: string[] }
>()
for (const p of projects) {
projectsByGav.set(gav(p.group, p.name, p.version), {
sources: p.sources,
targets: p.targets,
})
}
const targetsByCoord = new Map<string, string[]>()
const targetsByGav = new Map<string, string[]>()
const sourcesByCoord = new Map<string, string[]>()
Expand Down
33 changes: 33 additions & 0 deletions src/commands/manifest/scripts/assemble.test.mts
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,37 @@ describe('records → assemble → sidecar', () => {
'g:lib:jar:1',
])
})
it('marks only components with the exact coordinate of a build module as firstParty', () => {
const records = [
'meta\tmaven\t3.9.6\t17',
'project\t:a\tg\ta\t1.0-SNAPSHOT\ta',
'project\t:b\tg\tb\t1.0-SNAPSHOT\tb',
'root\tr1\t:a\truntimeClasspath\t1',
'node\tr1\tg:ext:jar:2\tg\text\t2\tjar\t\t1',
'root\tr2\t:b\truntimeClasspath\t1',
'node\tr2\tg:a:jar:1.0-SNAPSHOT\tg\ta\t1.0-SNAPSHOT\tjar\t\t1',
'node\tr2\tg:ext:jar:2\tg\text\t2\tjar\t\t0',
'edge\tr2\tg:a:jar:1.0-SNAPSHOT\tg:ext:jar:2',
'node\tr2\tg:b:jar:0.9\tg\tb\t0.9\tjar\t\t1',
].join('\n')
const { artifactPaths, facts } = assembleFacts(parseRecords(records))

expect(facts.components.map(c => [c.id, c.firstParty ?? 'absent'])).toEqual(
[
['g:a:jar:1.0-SNAPSHOT', true],
['g:b:jar:0.9', 'absent'],
['g:ext:jar:2', 'absent'],
],
)

const acc: SidecarAccumulator = new Map()
accumulateSidecar(acc, facts, artifactPaths, '/abs/.socket.facts.json')
const bucket = serializeSidecar(acc)['/abs/.socket.facts.json']!
expect(
bucket.components.find(c => c.id === 'g:a:jar:1.0-SNAPSHOT')?.firstParty,
).toBe(true)
for (const project of bucket.projects) {
expect(project).not.toHaveProperty('firstParty')
}
})
})
2 changes: 2 additions & 0 deletions src/commands/manifest/scripts/facts.mts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ export type SocketFactsSbomComponent = AnyPURL & {
id: string
direct?: boolean | undefined
dev?: boolean | undefined
// A module of the scanned build itself (same GAV as a projects[] entry).
firstParty?: true | undefined
dependencies?: string[] | undefined
}

Expand Down
Loading