Skip to content

Commit 01b45a5

Browse files
ruromeroclaude
andcommitted
fix: address qodo review findings for batch analysis
- Make generateOneSbom async and await provider.provideStack() to support async providers (e.g. python_pip) - Propagate workspaceDir as cwd for package manager commands so npm/pnpm/yarn run from workspace root in monorepos - Fix CLI --html --metadata printing wrapper object instead of HTML string Implements TC-3862 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 3e3c8d3 commit 01b45a5

4 files changed

Lines changed: 23 additions & 15 deletions

File tree

src/cli.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,12 @@ const stackBatch = {
280280
res = summaries
281281
}
282282
}
283-
console.log(html ? res : JSON.stringify(res, null, 2))
283+
if (html) {
284+
const htmlContent = res && typeof res === 'object' && 'analysis' in res ? res.analysis : res
285+
console.log(htmlContent)
286+
} else {
287+
console.log(JSON.stringify(res, null, 2))
288+
}
284289
}
285290
}
286291

src/index.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -281,12 +281,12 @@ function buildBatchAnalysisMetadata(root, ecosystem, totalSbomAttempts, successf
281281
*
282282
* @param {string} manifestPath
283283
* @param {Options} workspaceOpts - opts with `workspaceDir` set
284-
* @returns {SbomResult}
284+
* @returns {Promise<SbomResult>}
285285
* @private
286286
*/
287-
function generateOneSbom(manifestPath, workspaceOpts) {
287+
async function generateOneSbom(manifestPath, workspaceOpts) {
288288
const provider = match(manifestPath, availableProviders, workspaceOpts)
289-
const provided = provider.provideStack(manifestPath, workspaceOpts)
289+
const provided = await provider.provideStack(manifestPath, workspaceOpts)
290290
const sbom = JSON.parse(provided.content)
291291
const purl = sbom?.metadata?.component?.purl || sbom?.metadata?.component?.['bom-ref']
292292
if (!purl) {
@@ -373,7 +373,7 @@ async function generateSboms(manifestPaths, workspaceOpts, continueOnError, conc
373373

374374
if (!continueOnError) {
375375
for (const manifestPath of manifestPaths) {
376-
const result = generateOneSbom(manifestPath, workspaceOpts)
376+
const result = await generateOneSbom(manifestPath, workspaceOpts)
377377
if (!result.ok) {
378378
collectedErrors.push({ manifestPath: result.manifestPath, phase: 'sbom', reason: result.reason })
379379
throw new Error(`${result.manifestPath}: ${result.reason}`)
@@ -383,9 +383,9 @@ async function generateSboms(manifestPaths, workspaceOpts, continueOnError, conc
383383
} else {
384384
const limit = pLimit(concurrency)
385385
const settled = await Promise.all(
386-
manifestPaths.map(manifestPath => limit(() => {
386+
manifestPaths.map(manifestPath => limit(async () => {
387387
try {
388-
return generateOneSbom(manifestPath, workspaceOpts)
388+
return await generateOneSbom(manifestPath, workspaceOpts)
389389
} catch (err) {
390390
const msg = err instanceof Error ? err.message : String(err)
391391
if (process.env["TRUSTIFY_DA_DEBUG"] === "true") {

src/providers/base_javascript.js

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -181,15 +181,18 @@ export default class Base_javascript {
181181
/**
182182
* Builds the dependency tree for the project
183183
* @param {boolean} includeTransitive - Whether to include transitive dependencies
184+
* @param {Object} [opts={}] - Configuration options; when `workspaceDir` is set, commands run from workspace root
184185
* @returns {Object} The dependency tree
185186
* @protected
186187
*/
187-
_buildDependencyTree(includeTransitive) {
188+
_buildDependencyTree(includeTransitive, opts = {}) {
188189
this._version();
189-
let manifestDir = path.dirname(this.#manifest.manifestPath);
190-
this.#createLockFile(manifestDir);
190+
const manifestDir = path.dirname(this.#manifest.manifestPath);
191+
const workspaceDir = getCustom('TRUSTIFY_DA_WORKSPACE_DIR', null, opts) ?? opts.workspaceDir
192+
const cmdDir = workspaceDir ? path.resolve(workspaceDir) : manifestDir;
193+
this.#createLockFile(cmdDir);
191194

192-
let output = this.#executeListCmd(includeTransitive, manifestDir);
195+
let output = this.#executeListCmd(includeTransitive, cmdDir);
193196
output = this._parseDepTreeOutput(output);
194197
return JSON.parse(output);
195198
}
@@ -201,7 +204,7 @@ export default class Base_javascript {
201204
* @private
202205
*/
203206
#getSBOM(opts = {}) {
204-
const depsObject = this._buildDependencyTree(true);
207+
const depsObject = this._buildDependencyTree(true, opts);
205208

206209
let mainComponent = toPurl(purlType, this.#manifest.name, this.#manifest.version);
207210
const license = this.readLicenseFromManifest(this.#manifest.manifestPath);
@@ -260,7 +263,7 @@ export default class Base_javascript {
260263
* @private
261264
*/
262265
#getDirectDependencySbom(opts = {}) {
263-
const depTree = this._buildDependencyTree(false);
266+
const depTree = this._buildDependencyTree(false, opts);
264267
let mainComponent = toPurl(purlType, this.#manifest.name, this.#manifest.version);
265268
const license = this.readLicenseFromManifest(this.#manifest.manifestPath);
266269

src/providers/javascript_pnpm.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ export default class Javascript_pnpm extends Base_javascript {
1818
return ['install', '--frozen-lockfile'];
1919
}
2020

21-
_buildDependencyTree(includeTransitive, manifest) {
22-
const tree = super._buildDependencyTree(includeTransitive, manifest);
21+
_buildDependencyTree(includeTransitive, opts = {}) {
22+
const tree = super._buildDependencyTree(includeTransitive, opts);
2323
if (Array.isArray(tree) && tree.length > 0) {
2424
return tree[0];
2525
}

0 commit comments

Comments
 (0)