diff --git a/src/providers/processors/yarn_berry_processor.js b/src/providers/processors/yarn_berry_processor.js index 7da52689..6dfd2915 100644 --- a/src/providers/processors/yarn_berry_processor.js +++ b/src/providers/processors/yarn_berry_processor.js @@ -20,7 +20,10 @@ export default class Yarn_berry_processor extends Yarn_processor { * @returns {string[]} Command arguments for listing dependencies */ listCmdArgs(includeTransitive) { - return ['info', includeTransitive ? '--recursive' : '--all', '--json']; + // --all is needed to include workspace members in the output + return includeTransitive + ? ['info', '--recursive', '--all', '--json'] + : ['info', '--all', '--json']; } /** @@ -80,7 +83,8 @@ export default class Yarn_berry_processor extends Yarn_processor { if (!name) { return false; } - return name.endsWith("@workspace:."); + // Workspace members use paths like "member-a@workspace:packages/member-a", not just "@workspace:." + return name.startsWith(`${this._manifest.name}@workspace:`); } /** diff --git a/test/providers/javascript.test.js b/test/providers/javascript.test.js index 1aa0b118..48d2585c 100644 --- a/test/providers/javascript.test.js +++ b/test/providers/javascript.test.js @@ -106,6 +106,32 @@ suite('testing the javascript-npm data provider', async () => { }); + [ + { providerName: 'yarn-berry', testCase: 'workspace_member' }, + ].forEach(({ providerName, testCase }) => { + test(`verify workspace member data for ${providerName} - stack analysis`, async () => { + let expectedSbom = fs.readFileSync(`test/providers/tst_manifests/${providerName}/${testCase}/stack_expected_sbom.json`).toString(); + let listing = fs.readFileSync(`test/providers/tst_manifests/${providerName}/${testCase}/listing_stack.json`).toString(); + + const provider = await createMockProvider(providerName, listing); + const manifestPath = `test/providers/tst_manifests/${providerName}/${testCase}/packages/member-a/package.json`; + let providedDataForStack = provider.provideStack(manifestPath); + + compareSboms(providedDataForStack.content, expectedSbom); + }).timeout(30000); + + test(`verify workspace member data for ${providerName} - component analysis`, async () => { + let expectedSbom = fs.readFileSync(`test/providers/tst_manifests/${providerName}/${testCase}/component_expected_sbom.json`).toString(); + let listing = fs.readFileSync(`test/providers/tst_manifests/${providerName}/${testCase}/listing_component.json`).toString(); + + const provider = await createMockProvider(providerName, listing); + const manifestPath = `test/providers/tst_manifests/${providerName}/${testCase}/packages/member-a/package.json`; + let providedDataForComponent = provider.provideComponent(manifestPath); + + compareSboms(providedDataForComponent.content, expectedSbom); + }).timeout(15000); + }); + [ { providerName: 'npm', testCase: 'workspace_member' }, ].forEach(({ providerName, testCase }) => { diff --git a/test/providers/tst_manifests/yarn-berry/workspace_member/component_expected_sbom.json b/test/providers/tst_manifests/yarn-berry/workspace_member/component_expected_sbom.json new file mode 100644 index 00000000..b1033c7e --- /dev/null +++ b/test/providers/tst_manifests/yarn-berry/workspace_member/component_expected_sbom.json @@ -0,0 +1,36 @@ +{ + "bomFormat": "CycloneDX", + "specVersion": "1.4", + "version": 1, + "metadata": { + "timestamp": "2023-08-07T00:00:00.000Z", + "component": { + "name": "member-a", + "version": "1.0.0", + "purl": "pkg:npm/member-a@1.0.0", + "type": "application", + "bom-ref": "pkg:npm/member-a@1.0.0" + } + }, + "components": [ + { + "name": "axios", + "version": "0.21.1", + "purl": "pkg:npm/axios@0.21.1", + "type": "library", + "bom-ref": "pkg:npm/axios@0.21.1" + } + ], + "dependencies": [ + { + "ref": "pkg:npm/member-a@1.0.0", + "dependsOn": [ + "pkg:npm/axios@0.21.1" + ] + }, + { + "ref": "pkg:npm/axios@0.21.1", + "dependsOn": [] + } + ] +} diff --git a/test/providers/tst_manifests/yarn-berry/workspace_member/listing_component.json b/test/providers/tst_manifests/yarn-berry/workspace_member/listing_component.json new file mode 100644 index 00000000..3b49b82a --- /dev/null +++ b/test/providers/tst_manifests/yarn-berry/workspace_member/listing_component.json @@ -0,0 +1,30 @@ +{ + "value": "axios@npm:0.21.1", + "children": { + "Version": "0.21.1", + "Dependencies": [ + { + "descriptor": "follow-redirects@virtual:d192f6b3b31cd5d11a443145a3883a70c04cbd7c813c53085dbaf50263735f1162f10fdbddd53c24e162ec3bc37b90966413084323739b7cf942b8bfb4da8831#npm:^1.10.0", + "locator": "follow-redirects@virtual:d192f6b3b31cd5d11a443145a3883a70c04cbd7c813c53085dbaf50263735f1162f10fdbddd53c24e162ec3bc37b90966413084323739b7cf942b8bfb4da8831#npm:1.16.0" + } + ] + } +} +{ + "value": "member-a@workspace:packages/member-a", + "children": { + "Version": "1.0.0", + "Dependencies": [ + { + "descriptor": "axios@npm:0.21.1", + "locator": "axios@npm:0.21.1" + } + ] + } +} +{ + "value": "test-workspace-root@workspace:.", + "children": { + "Version": "0.0.0" + } +} diff --git a/test/providers/tst_manifests/yarn-berry/workspace_member/listing_stack.json b/test/providers/tst_manifests/yarn-berry/workspace_member/listing_stack.json new file mode 100644 index 00000000..e515b2a8 --- /dev/null +++ b/test/providers/tst_manifests/yarn-berry/workspace_member/listing_stack.json @@ -0,0 +1,37 @@ +{ + "value": "axios@npm:0.21.1", + "children": { + "Version": "0.21.1", + "Dependencies": [ + { + "descriptor": "follow-redirects@virtual:d192f6b3b31cd5d11a443145a3883a70c04cbd7c813c53085dbaf50263735f1162f10fdbddd53c24e162ec3bc37b90966413084323739b7cf942b8bfb4da8831#npm:^1.10.0", + "locator": "follow-redirects@virtual:d192f6b3b31cd5d11a443145a3883a70c04cbd7c813c53085dbaf50263735f1162f10fdbddd53c24e162ec3bc37b90966413084323739b7cf942b8bfb4da8831#npm:1.16.0" + } + ] + } +} +{ + "value": "follow-redirects@npm:1.16.0", + "children": { + "Instances": 1, + "Version": "1.16.0" + } +} +{ + "value": "member-a@workspace:packages/member-a", + "children": { + "Version": "1.0.0", + "Dependencies": [ + { + "descriptor": "axios@npm:0.21.1", + "locator": "axios@npm:0.21.1" + } + ] + } +} +{ + "value": "test-workspace-root@workspace:.", + "children": { + "Version": "0.0.0" + } +} diff --git a/test/providers/tst_manifests/yarn-berry/workspace_member/package.json b/test/providers/tst_manifests/yarn-berry/workspace_member/package.json new file mode 100644 index 00000000..98101a90 --- /dev/null +++ b/test/providers/tst_manifests/yarn-berry/workspace_member/package.json @@ -0,0 +1,5 @@ +{ + "name": "test-workspace-root", + "private": true, + "workspaces": ["packages/*"] +} diff --git a/test/providers/tst_manifests/yarn-berry/workspace_member/packages/member-a/package.json b/test/providers/tst_manifests/yarn-berry/workspace_member/packages/member-a/package.json new file mode 100644 index 00000000..fba8d2af --- /dev/null +++ b/test/providers/tst_manifests/yarn-berry/workspace_member/packages/member-a/package.json @@ -0,0 +1,7 @@ +{ + "name": "member-a", + "version": "1.0.0", + "dependencies": { + "axios": "0.21.1" + } +} diff --git a/test/providers/tst_manifests/yarn-berry/workspace_member/stack_expected_sbom.json b/test/providers/tst_manifests/yarn-berry/workspace_member/stack_expected_sbom.json new file mode 100644 index 00000000..28da3d7a --- /dev/null +++ b/test/providers/tst_manifests/yarn-berry/workspace_member/stack_expected_sbom.json @@ -0,0 +1,49 @@ +{ + "bomFormat": "CycloneDX", + "specVersion": "1.4", + "version": 1, + "metadata": { + "timestamp": "2023-08-07T00:00:00.000Z", + "component": { + "name": "member-a", + "version": "1.0.0", + "purl": "pkg:npm/member-a@1.0.0", + "type": "application", + "bom-ref": "pkg:npm/member-a@1.0.0" + } + }, + "components": [ + { + "name": "axios", + "version": "0.21.1", + "purl": "pkg:npm/axios@0.21.1", + "type": "library", + "bom-ref": "pkg:npm/axios@0.21.1" + }, + { + "name": "follow-redirects", + "version": "1.16.0", + "purl": "pkg:npm/follow-redirects@1.16.0", + "type": "library", + "bom-ref": "pkg:npm/follow-redirects@1.16.0" + } + ], + "dependencies": [ + { + "ref": "pkg:npm/member-a@1.0.0", + "dependsOn": [ + "pkg:npm/axios@0.21.1" + ] + }, + { + "ref": "pkg:npm/axios@0.21.1", + "dependsOn": [ + "pkg:npm/follow-redirects@1.16.0" + ] + }, + { + "ref": "pkg:npm/follow-redirects@1.16.0", + "dependsOn": [] + } + ] +} diff --git a/test/providers/tst_manifests/yarn-berry/workspace_member/yarn.lock b/test/providers/tst_manifests/yarn-berry/workspace_member/yarn.lock new file mode 100644 index 00000000..19d1db70 --- /dev/null +++ b/test/providers/tst_manifests/yarn-berry/workspace_member/yarn.lock @@ -0,0 +1,2 @@ +__metadata: + version: 8