ReviewOS

also looking at this

craft-native/craft

fix(sbom): preserve the full dependency inventory when merging

#297
Merged glennmichael123 wants to merge codex/sbom-inventory into main
4 files +106 -120
scripts/merge-sbom.test.tsadded+32-0
Changes to scripts/merge-sbom.test.ts
@@ -0,0 +1,32 @@
1import { expect, test } from 'bun:test'
2import { mergeSbom } from './merge-sbom'
3
4const source = {
5 bomFormat: 'CycloneDX', specVersion: '1.7',
6 metadata: { component: { name: '.', 'bom-ref': 'source-root' }, tools: { components: [{ name: 'syft', version: '1.52.0' }] } },
7 components: [{ name: 'first', 'bom-ref': 'one' }, { name: 'second', 'bom-ref': 'two' }],
8 dependencies: [{ ref: 'source-root', dependsOn: ['one'] }, { ref: 'one', dependsOn: ['two'] }],
9}
10
11test('preserves the scanned inventory and dependency graph when adding runtime supplements', () => {
12 const original = structuredClone(source)
13 const { combined, zig, platform } = mergeSbom(source, '0.0.93', '0.17.0-dev.1963')
14 expect(combined.components).toHaveLength(7)
15 expect(combined.components.slice(0, 2)).toEqual(source.components)
16 expect(combined.dependencies?.find(dependency => dependency.ref === 'one')).toEqual(source.dependencies[1])
17 expect(combined.dependencies?.find(dependency => dependency.ref === 'source-root')?.dependsOn).toContain('one')
18 expect(combined.dependencies?.find(dependency => dependency.ref === 'source-root')?.dependsOn).toHaveLength(6)
19 expect(combined.metadata?.tools).toEqual(source.metadata.tools)
20 expect(combined.metadata?.component).toMatchObject({ name: 'craft', version: 'v0.0.93', 'bom-ref': 'source-root' })
21 expect(zig.metadata?.component?.version).toBe('0.0.93')
22 expect(platform.metadata?.component?.version).toBe('0.0.93')
23 expect(zig.components[0].version).toBe('0.17.0-dev.1963')
24 expect(Number.isNaN(Date.parse(String(zig.metadata?.timestamp)))).toBe(false)
25 expect(source).toEqual(original)
26})
27
28test('refuses missing inventory and colliding component references', () => {
29 expect(() => mergeSbom({ ...source, components: [] }, '1.0.0', 'dev')).toThrow('populated')
30 expect(() => mergeSbom({ ...source, bomFormat: 'SPDX' }, '1.0.0', 'dev')).toThrow('CycloneDX')
31 expect(() => mergeSbom({ ...source, components: [{ name: 'collision', 'bom-ref': 'urn:craft:zig-std' }] }, '1.0.0', 'dev')).toThrow('collides')
32})