Skip to content

Commit 1d907fc

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

2 files changed

Lines changed: 58 additions & 9 deletions

File tree

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

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,24 @@ export function formatAlertTable(rows: ReportAlertRow[]): string[] {
8686
row.introducedBy,
8787
row.manifest,
8888
])
89-
const widths = headers.map((header, i) =>
90-
Math.max(header.length, ...cells.map(cell => (cell[i] ?? '').length)),
91-
)
89+
const widths = headers.map(header => header.length)
90+
for (
91+
let rowIndex = 0, { length: rowCount } = cells;
92+
rowIndex < rowCount;
93+
rowIndex += 1
94+
) {
95+
const cell = cells[rowIndex]!
96+
for (
97+
let cellIndex = 0, { length: cellLength } = cell;
98+
cellIndex < cellLength;
99+
cellIndex += 1
100+
) {
101+
widths[cellIndex] = Math.max(
102+
widths[cellIndex] ?? 0,
103+
cell[cellIndex]?.length ?? 0,
104+
)
105+
}
106+
}
92107
const toRow = (values: string[]) =>
93108
` ${values
94109
.map((value, i) => value.padEnd(widths[i] ?? 0))
@@ -116,6 +131,12 @@ export function formatLabelledPairs(pairs: Array<[string, string]>): string[] {
116131
)
117132
}
118133

134+
export function isFullScanReport(
135+
report: ScanReport | { healthy: boolean },
136+
): report is ScanReport {
137+
return 'alerts' in report
138+
}
139+
119140
export async function outputGeneratedScanReport(
120141
scanReport: Extract<ReturnType<typeof generateReport>, { ok: true }>,
121142
config: Pick<
@@ -159,10 +180,10 @@ export async function outputGeneratedScanReport(
159180

160181
if (short) {
161182
logger.log(scanReport.data.healthy ? 'OK' : 'ERR')
183+
} else if (isFullScanReport(scanReport.data)) {
184+
logger.log(toPlainTextReport(scanReport.data, includeLicensePolicy))
162185
} else {
163-
logger.log(
164-
toPlainTextReport(scanReport.data as ScanReport, includeLicensePolicy),
165-
)
186+
logger.log(scanReport.data.healthy ? 'OK' : 'ERR')
166187
}
167188
}
168189

@@ -401,8 +422,10 @@ export function toPlainTextReport(
401422
lines.push(
402423
` ${rows.length} ${pluralize('alert', { count: rows.length })} with a policy set to at least "${reportLevel}".`,
403424
'',
404-
...formatAlertTable(rows),
405-
'',
406425
)
426+
for (const line of formatAlertTable(rows)) {
427+
lines.push(line)
428+
}
429+
lines.push('')
407430
return lines.join('\n')
408431
}

‎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)