Skip to content

Commit

Permalink
Handle workspace with duplicate names (#1603)
Browse files Browse the repository at this point in the history
* Handle workspace with duplicate names

Signed-off-by: Prabhu Subramanian <[email protected]>

---------

Signed-off-by: Prabhu Subramanian <[email protected]>
  • Loading branch information
prabhu authored Jan 28, 2025
1 parent 0bc0e6f commit 47d8e4d
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 10 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/npm-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ jobs:
if: github.repository == 'CycloneDX/cdxgen'
runs-on: ubuntu-latest
permissions:
contents: read
contents: write
packages: write
id-token: write
steps:
Expand Down
2 changes: 1 addition & 1 deletion deno.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@cyclonedx/cdxgen",
"version": "11.1.3",
"version": "11.1.4",
"exports": "./lib/cli/index.js",
"compilerOptions": {
"lib": ["deno.window"],
Expand Down
2 changes: 1 addition & 1 deletion jsr.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@cyclonedx/cdxgen",
"version": "11.1.3",
"version": "11.1.4",
"exports": "./lib/cli/index.js",
"include": ["*.js", "lib/**", "bin/**", "data/**", "types/**"],
"exclude": [
Expand Down
49 changes: 44 additions & 5 deletions lib/cli/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
writeFileSync,
} from "node:fs";
import { platform as _platform, arch, homedir } from "node:os";
import { basename, dirname, join, resolve, sep } from "node:path";
import { basename, dirname, join, relative, resolve, sep } from "node:path";
import process from "node:process";
import { URL } from "node:url";
import got from "got";
Expand Down Expand Up @@ -2277,7 +2277,11 @@ export async function createNodejsBom(path, options) {
let allImports = {};
let allExports = {};
if (
!hasAnyProjectType(["docker", "oci", "container", "os"], options, false) &&
!hasAnyProjectType(
["docker", "oci", "container", "os", "pnpm"],
options,
false,
) &&
!options.noBabel
) {
if (DEBUG_MODE) {
Expand Down Expand Up @@ -2504,6 +2508,7 @@ export async function createNodejsBom(path, options) {
const depsWorkspaceRefs = {};
let workspaceCatalogs = {};
let workspaceWarningShown = false;
const seenPkgJsonFiles = {};
// Is this a pnpm workspace?
for (const f of pnpmWorkspaceFiles) {
if (DEBUG_MODE) {
Expand All @@ -2524,15 +2529,34 @@ export async function createNodejsBom(path, options) {
continue;
}
for (const apj of wpkgJsonFiles) {
if (seenPkgJsonFiles[apj]) {
continue;
}
seenPkgJsonFiles[apj] = true;
const pkgData = JSON.parse(readFileSync(apj, "utf-8"));
if (pkgData?.name) {
const relativePkgJsonFile = relative(path, apj);
let workspaceRef = `pkg:npm/${pkgData.name}`;
if (pkgData?.version) {
workspaceRef = `${workspaceRef}@${pkgData.version}`;
}
// Track all workspace purls
workspacePackages.push(workspaceRef);
workspaceSrcFiles[workspaceRef] = apj;
// Track all workspace purls. When we face duplicates, let's try to expand the purl to
// include the subpath.
if (!workspacePackages.includes(workspaceRef)) {
workspacePackages.push(workspaceRef);
} else {
console.log(
`Found a duplicate workspace with the name: ${pkgData.name}, ref: ${workspaceRef} at ${relativePkgJsonFile} and ${workspaceSrcFiles[workspaceRef]}. This is likely an error in the project that needs fixing.`,
);
workspaceRef = `${workspaceRef}#${relativePkgJsonFile.replace(`${sep}package.json`, "")}`;
if (!workspacePackages.includes(workspaceRef)) {
workspacePackages.push(workspaceRef);
console.log(
`Duplicate workspace tracked as ${workspaceRef} under metadata.component.components`,
);
}
}
workspaceSrcFiles[workspaceRef] = relativePkgJsonFile;
// Track the direct dependencies of each workspace and workspace refs for each direct deps.
const allDeps = {
...(pkgData.dependencies || {}),
Expand All @@ -2559,6 +2583,21 @@ export async function createNodejsBom(path, options) {
...(workspaceObj.catalogs || {}),
};
}
if (DEBUG_MODE && Object.keys(seenPkgJsonFiles).length) {
console.log(
`${Object.keys(seenPkgJsonFiles).length} package.json files were parsed to identify workspace names. Total number of package.json files: ${pkgJsonFiles.length}`,
);
if (Object.keys(seenPkgJsonFiles).length < pkgJsonFiles.length - 1) {
const seenfilenames = Object.keys(seenPkgJsonFiles);
console.log(
"Following files were not parsed:",
pkgJsonFiles.filter((p) => !seenfilenames.includes(p)),
);
console.log(
"TIP: Check the configuration in pnpm-workspace.yaml to ensure all the required workspaces are included correctly.",
);
}
}
for (const f of pnpmLockFiles) {
if (DEBUG_MODE) {
console.log(`Parsing ${f}`);
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@cyclonedx/cdxgen",
"version": "11.1.3",
"version": "11.1.4",
"description": "Creates CycloneDX Software Bill of Materials (SBOM) from source or container image",
"homepage": "http://github.com/cyclonedx/cdxgen",
"author": "Prabhu Subramanian <[email protected]>",
Expand Down
2 changes: 1 addition & 1 deletion types/lib/cli/index.d.ts.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 47d8e4d

Please sign in to comment.