Skip to content

Commit b7de045

Browse files
committed
fix(scan report): handle large alert output
1 parent e1e489f commit b7de045

2 files changed

Lines changed: 46 additions & 9 deletions

File tree

‎src/command/scan/output-scan-report.mts‎

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ export type OutputScanReportConfig = {
3636
short: boolean
3737
}
3838

39+
function isFullScanReport(
40+
report: ScanReport | { healthy: boolean },
41+
): report is ScanReport {
42+
return 'alerts' in report
43+
}
44+
3945
export type ReportAlertRow = {
4046
alertType: string
4147
introducedBy: string
@@ -86,9 +92,12 @@ export function formatAlertTable(rows: ReportAlertRow[]): string[] {
8692
row.introducedBy,
8793
row.manifest,
8894
])
89-
const widths = headers.map((header, i) =>
90-
Math.max(header.length, ...cells.map(cell => (cell[i] ?? '').length)),
91-
)
95+
const widths = headers.map(header => header.length)
96+
for (const cell of cells) {
97+
for (let i = 0, { length } = cell; i < length; i += 1) {
98+
widths[i] = Math.max(widths[i] ?? 0, cell[i]?.length ?? 0)
99+
}
100+
}
92101
const toRow = (values: string[]) =>
93102
` ${values
94103
.map((value, i) => value.padEnd(widths[i] ?? 0))
@@ -159,10 +168,10 @@ export async function outputGeneratedScanReport(
159168

160169
if (short) {
161170
logger.log(scanReport.data.healthy ? 'OK' : 'ERR')
171+
} else if (isFullScanReport(scanReport.data)) {
172+
logger.log(toPlainTextReport(scanReport.data, includeLicensePolicy))
162173
} else {
163-
logger.log(
164-
toPlainTextReport(scanReport.data as ScanReport, includeLicensePolicy),
165-
)
174+
logger.log(scanReport.data.healthy ? 'OK' : 'ERR')
166175
}
167176
}
168177

@@ -401,8 +410,10 @@ export function toPlainTextReport(
401410
lines.push(
402411
` ${rows.length} ${pluralize('alert', { count: rows.length })} with a policy set to at least "${reportLevel}".`,
403412
'',
404-
...formatAlertTable(rows),
405-
'',
406413
)
414+
for (const line of formatAlertTable(rows)) {
415+
lines.push(line)
416+
}
417+
lines.push('')
407418
return lines.join('\n')
408419
}

‎test/unit/command/scan/output-scan-report-text.test.mts‎

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ import {
1616
toPlainTextReport,
1717
} from '../../../../src/command/scan/output-scan-report.mts'
1818

19-
import type { ScanReport } from '../../../../src/command/scan/report-generation.mts'
19+
import type {
20+
ReportLeafNode,
21+
ScanReport,
22+
} from '../../../../src/command/scan/report-generation.mts'
2023

2124
// Matches any ANSI escape sequence, the codes that show up as literal noise
2225
// like "[32m" in a log viewer that does not interpret them.
@@ -204,6 +207,29 @@ describe('toPlainTextReport', () => {
204207
expect(overlong).toEqual([])
205208
})
206209

210+
it('renders a large alert report without argument-count failures', () => {
211+
const alertRow: ReportLeafNode = {
212+
manifest: ['package.json'],
213+
policy: 'error',
214+
type: 'envVars',
215+
url: '',
216+
}
217+
const packages = new Map<string, Map<string, ReportLeafNode>>()
218+
const alertCount = 200_000
219+
for (let i = 0; i < alertCount; i += 1) {
220+
packages.set(
221+
`package-${String(i).padStart(6, '0')}`,
222+
new Map([['1.0.0', alertRow]]),
223+
)
224+
}
225+
const alerts: ScanReport['alerts'] = new Map([['npm', packages]])
226+
const text = toPlainTextReport(buildReport({ alerts, healthy: false }))
227+
228+
expect(text).toContain('200000 alerts with a policy')
229+
expect(text).toContain('package-000000')
230+
expect(text).toContain('package-199999')
231+
})
232+
207233
it('says so plainly when there are no alerts', () => {
208234
const text = toPlainTextReport(
209235
buildReport({ alerts: new Map(), healthy: true }),

0 commit comments

Comments
 (0)