Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ on:
branches: [main]
tags: ['*']
pull_request:
branches: [main]
branches: [main, fix/scan-report-large-output]
workflow_dispatch:

permissions:
Expand Down
12 changes: 6 additions & 6 deletions src/command/scan/output-scan-report.mts
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ export type OutputScanReportConfig = {

export type ReportAlertRow = {
alertType: string
introducedBy: string
manifest: string
packageName: string
packageVersion: string
policy: string
url: string
}
Expand All @@ -57,9 +57,9 @@ export function flattenReportAlerts(report: ScanReport): ReportAlertRow[] {
return {
__proto__: null,
alertType: type,
introducedBy: keys[2] || '<unknown>',
manifest: joinAnd(manifest),
packageName: keys[1] || '<unknown>',
packageVersion: keys[2] || '<unknown>',
policy,
url,
}
Expand All @@ -76,14 +76,14 @@ export function formatAlertTable(rows: ReportAlertRow[]): string[] {
'POLICY',
'ALERT TYPE',
'PACKAGE',
'INTRODUCED BY',
'VERSION',
'MANIFEST FILE',
]
const cells = rows.map(row => [
row.policy,
row.alertType,
row.packageName,
row.introducedBy,
row.packageVersion,
row.manifest,
])
const widths = headers.map(header => header.length)
Expand Down Expand Up @@ -307,7 +307,7 @@ export function toMarkdownReport(
__proto__: null,
'Alert Type': row.alertType,
Package: row.packageName,
'Introduced by': row.introducedBy,
Version: row.packageVersion,
url: row.url,
'Manifest file': row.manifest,
Policy: row.policy,
Expand Down Expand Up @@ -355,7 +355,7 @@ ${
'Policy',
'Alert Type',
'Package',
'Introduced by',
'Version',
'url',
'Manifest file',
])
Expand Down
12 changes: 6 additions & 6 deletions test/unit/command/scan/output-scan-report-markdown.test.mts
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,12 @@ describe('output-scan-report', () => {

All the alerts from the scan with a policy set to at least "warn".

| ------ | ---------- | ------- | ------------- | ------------------------------------------- | ----------------- |
| Policy | Alert Type | Package | Introduced by | url | Manifest file |
| ------ | ---------- | ------- | ------------- | ------------------------------------------- | ----------------- |
| error | envVars | tslib | 1.14.1 | https://socket.dev/npm/package/tslib/1.14.1 | package-lock.json |
| error | envVars | tslib | 1.14.1 | https://socket.dev/npm/package/tslib/1.14.1 | package-lock.json |
| ------ | ---------- | ------- | ------------- | ------------------------------------------- | ----------------- |
| ------ | ---------- | ------- | ------- | ------------------------------------------- | ----------------- |
| Policy | Alert Type | Package | Version | url | Manifest file |
| ------ | ---------- | ------- | ------- | ------------------------------------------- | ----------------- |
| error | envVars | tslib | 1.14.1 | https://socket.dev/npm/package/tslib/1.14.1 | package-lock.json |
| error | envVars | tslib | 1.14.1 | https://socket.dev/npm/package/tslib/1.14.1 | package-lock.json |
| ------ | ---------- | ------- | ------- | ------------------------------------------- | ----------------- |
"
`)
})
Expand Down
178 changes: 156 additions & 22 deletions test/unit/command/scan/output-scan-report-text.test.mts
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,17 @@ import { describe, expect, it } from 'vitest'

import {
flattenReportAlerts,
isFullScanReport,
toPlainTextReport,
} from '../../../../src/command/scan/output-scan-report.mts'

import type {
EcoMap,
FileMap,
PackageMap,
ReportLeafNode,
ScanReport,
VersionMap,
} from '../../../../src/command/scan/report-generation.mts'

// Matches any ANSI escape sequence, the codes that show up as literal noise
Expand All @@ -27,6 +32,15 @@ import type {
// oxlint-disable-next-line no-control-regex -- control chars intended
const ANSI_PATTERN = /\u001B\[[0-9;]*m/

describe('isFullScanReport', () => {
it('distinguishes full reports from short reports', () => {
expect(
isFullScanReport(buildReport({ alerts: new Map(), healthy: true })),
).toBe(true)
expect(isFullScanReport({ healthy: true })).toBe(false)
})
})

function buildReport(config: {
alerts: ScanReport['alerts']
healthy: boolean
Expand All @@ -42,30 +56,33 @@ function buildReport(config: {
}

function buildAlerts(): ScanReport['alerts'] {
return new Map([
[
'npm',
new Map([
[
'acme-widget',
new Map([
[
'1.0.0',
{
manifest: ['package.json'],
policy: 'error',
type: 'envVars',
url: 'https://socket.dev/npm/package/acme-widget',
},
],
]),
],
]),
],
]) as unknown as ScanReport['alerts']
const leaf: ReportLeafNode = {
manifest: ['package.json'],
policy: 'error',
type: 'envVars',
url: 'https://socket.dev/npm/package/acme-widget',
}
const fileMap: FileMap = new Map([['envVars at 1:2', leaf]])
const versionMap: VersionMap = new Map([['package.json', fileMap]])
const packageMap: PackageMap = new Map([['1.0.0', versionMap]])
const ecosystemMap: EcoMap = new Map([['acme-widget', packageMap]])

return new Map([['npm', ecosystemMap]])
}

describe('toPlainTextReport', () => {
it('labels the package version as a version', () => {
const report = buildReport({ alerts: buildAlerts(), healthy: false })
const text = toPlainTextReport(report)

expect(flattenReportAlerts(report)[0]).toMatchObject({
packageVersion: '1.0.0',
})
expect(text).toContain('VERSION')
expect(text).toContain('1.0.0')
expect(text).not.toContain('INTRODUCED BY')
})

it('emits no ANSI escape codes', () => {
const text = toPlainTextReport(
buildReport({ alerts: buildAlerts(), healthy: false }),
Expand Down Expand Up @@ -237,6 +254,123 @@ describe('toPlainTextReport', () => {

expect(text).toContain('No alerts')
expect(text).not.toContain('ALERT TYPE')
expect(text).not.toContain('VERSION')
})

it('retains package versions for version and file folds', () => {
const versionLeaf: ReportLeafNode = {
manifest: ['package.json'],
policy: 'error',
type: 'envVars',
url: '',
}
const versionFoldAlerts: ScanReport['alerts'] = new Map([
[
'npm',
new Map([['demo-transitive', new Map([['2.3.4', versionLeaf]])]]),
],
])
const fileFoldAlerts: ScanReport['alerts'] = new Map([
[
'npm',
new Map([
[
'demo-transitive',
new Map([
[
'2.3.4',
new Map([
['package.json', versionLeaf],
[
'src/index.js',
{ ...versionLeaf, manifest: ['package-lock.json'] },
],
]),
],
]),
],
]),
],
])
const versionFoldReport = {
...buildReport({ alerts: versionFoldAlerts, healthy: false }),
options: { fold: 'version' as const, reportLevel: 'error' as const },
}
const fileFoldReport = {
...buildReport({ alerts: fileFoldAlerts, healthy: false }),
options: { fold: 'file' as const, reportLevel: 'error' as const },
}

expect(flattenReportAlerts(versionFoldReport)[0]?.packageVersion).toBe(
'2.3.4',
)
expect(toPlainTextReport(versionFoldReport)).toContain('VERSION')
expect(toPlainTextReport(versionFoldReport)).toContain('2.3.4')
expect(flattenReportAlerts(fileFoldReport)).toEqual([
expect.objectContaining({
manifest: 'package.json',
packageVersion: '2.3.4',
}),
expect.objectContaining({
manifest: 'package-lock.json',
packageVersion: '2.3.4',
}),
])
expect(toPlainTextReport(fileFoldReport)).toContain('VERSION')
expect(toPlainTextReport(fileFoldReport)).toContain('2.3.4')
expect(toPlainTextReport(fileFoldReport)).toContain('package-lock.json')
})

it('keeps package-fold versions unknown and distinguishes package versions', () => {
const leaf: ReportLeafNode = {
manifest: ['package.json'],
policy: 'error',
type: 'envVars',
url: '',
}
const packageFoldAlerts: ScanReport['alerts'] = new Map([
['npm', new Map([['demo-transitive', leaf]])],
])
const twoVersionAlerts: ScanReport['alerts'] = new Map([
[
'npm',
new Map([
[
'demo-transitive',
new Map([
[
'2.3.4',
new Map([
['package.json', new Map([['envVars at 1:2', leaf]])],
]),
],
[
'2.3.5',
new Map([
['package.json', new Map([['envVars at 3:4', leaf]])],
]),
],
]),
],
]),
],
])
const packageFoldReport = {
...buildReport({ alerts: packageFoldAlerts, healthy: false }),
options: { fold: 'pkg' as const, reportLevel: 'error' as const },
}
const twoVersionReport = {
...buildReport({ alerts: twoVersionAlerts, healthy: false }),
options: { fold: 'none' as const, reportLevel: 'error' as const },
}

expect(flattenReportAlerts(packageFoldReport)[0]?.packageVersion).toBe(
'<unknown>',
)
expect(toPlainTextReport(packageFoldReport)).toContain('<unknown>')
expect(
flattenReportAlerts(twoVersionReport).map(row => row.packageVersion),
).toEqual(['2.3.4', '2.3.5'])
})
})

Expand All @@ -249,9 +383,9 @@ describe('flattenReportAlerts', () => {
expect(rows).toEqual([
{
alertType: 'envVars',
introducedBy: '1.0.0',
manifest: 'package.json',
packageName: 'acme-widget',
packageVersion: '1.0.0',
policy: 'error',
url: 'https://socket.dev/npm/package/acme-widget',
},
Expand Down
Loading