Skip to content

Commit 332caee

Browse files
authored
Add --limit flag to fix command (#498)
1 parent 4e2ba0b commit 332caee

File tree

7 files changed

+83
-27
lines changed

7 files changed

+83
-27
lines changed

src/commands/fix/cmd-fix.mts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,6 @@ const config: CliCommandConfig = {
1919
hidden: false,
2020
flags: {
2121
...commonFlags,
22-
autopilot: {
23-
type: 'boolean',
24-
default: false,
25-
description: `Shorthand for --autoMerge --test`
26-
},
2722
autoMerge: {
2823
type: 'boolean',
2924
default: false,
@@ -32,6 +27,16 @@ const config: CliCommandConfig = {
3227
'https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-auto-merge-for-pull-requests-in-your-repository'
3328
)} for managing auto-merge for pull requests in your repository.`
3429
},
30+
autopilot: {
31+
type: 'boolean',
32+
default: false,
33+
description: `Shorthand for --autoMerge --test`
34+
},
35+
limit: {
36+
type: 'number',
37+
default: Infinity,
38+
description: 'The number of fixes to attempt at a time'
39+
},
3540
purl: {
3641
type: 'string',
3742
default: [],
@@ -112,6 +117,7 @@ async function run(
112117
await runFix({
113118
autoMerge: Boolean(cli.flags['autoMerge']),
114119
autopilot: Boolean(cli.flags['autopilot']),
120+
limit: Number(cli.flags['limit']),
115121
dryRun: Boolean(cli.flags['dryRun']),
116122
purls: Array.isArray(cli.flags['purl']) ? cli.flags['purl'] : [],
117123
rangeStyle: (cli.flags['rangeStyle'] ?? undefined) as

src/commands/fix/npm-fix.mts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import {
2424
getGitHubEnvRepoInfo,
2525
openGitHubPullRequest
2626
} from './open-pr.mts'
27-
import { alertMapOptions } from './shared.mts'
27+
import { getAlertMapOptions } from './shared.mts'
2828
import constants from '../../constants.mts'
2929
import {
3030
Arborist,
@@ -78,6 +78,7 @@ export async function npmFix(
7878
autoMerge,
7979
cwd,
8080
dryRun,
81+
limit,
8182
purls,
8283
rangeStyle,
8384
test,
@@ -102,10 +103,10 @@ export async function npmFix(
102103
await arb.reify()
103104

104105
const alertsMap = purls.length
105-
? await getAlertsMapFromPurls(purls, alertMapOptions)
106-
: await getAlertsMapFromArborist(arb, alertMapOptions)
106+
? await getAlertsMapFromPurls(purls, getAlertMapOptions({ limit }))
107+
: await getAlertsMapFromArborist(arb, getAlertMapOptions({ limit }))
107108

108-
const infoByPkg = getCveInfoByAlertsMap(alertsMap)
109+
const infoByPkg = getCveInfoByAlertsMap(alertsMap, { limit })
109110
if (!infoByPkg) {
110111
spinner?.stop()
111112
logger.info('No fixable vulnerabilities found.')
@@ -124,7 +125,8 @@ export async function npmFix(
124125
pkgEnvDetails.editablePkgJson.filename!
125126
]
126127

127-
for (const { 0: name, 1: infos } of infoByPkg) {
128+
let count = 0
129+
infoByPkgLoop: for (const { 0: name, 1: infos } of infoByPkg) {
128130
debugLog(`Processing vulnerable package: ${name}`)
129131

130132
if (getManifestData(NPM, name)) {
@@ -334,6 +336,9 @@ export async function npmFix(
334336
error
335337
)
336338
}
339+
if (++count >= limit) {
340+
break infoByPkgLoop
341+
}
337342
}
338343
}
339344
}

src/commands/fix/pnpm-fix.mts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import {
2626
getGitHubEnvRepoInfo,
2727
openGitHubPullRequest
2828
} from './open-pr.mts'
29-
import { alertMapOptions } from './shared.mts'
29+
import { getAlertMapOptions } from './shared.mts'
3030
import constants from '../../constants.mts'
3131
import {
3232
SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES,
@@ -97,6 +97,7 @@ export async function pnpmFix(
9797
autoMerge,
9898
cwd,
9999
dryRun,
100+
limit,
100101
purls,
101102
rangeStyle,
102103
test,
@@ -126,10 +127,14 @@ export async function pnpmFix(
126127
}
127128

128129
const alertsMap = purls.length
129-
? await getAlertsMapFromPurls(purls, alertMapOptions)
130-
: await getAlertsMapFromPnpmLockfile(lockfile, alertMapOptions)
130+
? await getAlertsMapFromPurls(purls, getAlertMapOptions({ limit }))
131+
: await getAlertsMapFromPnpmLockfile(
132+
lockfile,
133+
getAlertMapOptions({ limit })
134+
)
131135

132-
const infoByPkg = getCveInfoByAlertsMap(alertsMap)
136+
const infoByPkg = getCveInfoByAlertsMap(alertsMap, { limit })
137+
console.log(infoByPkg)
133138
if (!infoByPkg) {
134139
spinner?.stop()
135140
logger.info('No fixable vulnerabilities found.')
@@ -148,7 +153,8 @@ export async function pnpmFix(
148153
pkgEnvDetails.editablePkgJson.filename!
149154
]
150155

151-
for (const { 0: name, 1: infos } of infoByPkg) {
156+
let count = 0
157+
infoByPkgLoop: for (const { 0: name, 1: infos } of infoByPkg) {
152158
debugLog(`Processing vulnerable package: ${name}`)
153159

154160
if (getManifestData(NPM, name)) {
@@ -397,6 +403,9 @@ export async function pnpmFix(
397403
error
398404
)
399405
}
406+
if (++count >= limit) {
407+
break infoByPkgLoop
408+
}
400409
}
401410
}
402411
}

src/commands/fix/shared.mts

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,28 @@
11
import type { FixOptions, NormalizedFixOptions } from './types.mts'
2+
import type { GetAlertsMapFromPurlsOptions } from '../../utils/alerts-map.mts'
3+
import type { Remap } from '@socketsecurity/registry/lib/objects'
24

35
export const CMD_NAME = 'socket fix'
46

5-
export const alertMapOptions = Object.freeze({
6-
consolidate: true,
7-
include: {
8-
existing: true,
9-
unfixable: false,
10-
upgradable: false
11-
},
12-
nothrow: true
13-
})
7+
export function getAlertMapOptions(options: GetAlertsMapFromPurlsOptions = {}) {
8+
return {
9+
__proto__: null,
10+
consolidate: true,
11+
nothrow: true,
12+
...options,
13+
include: {
14+
__proto__: null,
15+
existing: true,
16+
unfixable: false,
17+
upgradable: false,
18+
...options?.include
19+
}
20+
} as Remap<
21+
Omit<GetAlertsMapFromPurlsOptions, 'include' | 'overrides' | 'spinner'> & {
22+
include: Exclude<GetAlertsMapFromPurlsOptions['include'], undefined>
23+
}
24+
>
25+
}
1426

1527
export function normalizeFixOptions(
1628
options_: FixOptions
@@ -28,6 +40,13 @@ export function normalizeFixOptions(
2840
if (typeof options.cwd !== 'string') {
2941
options.cwd = process.cwd()
3042
}
43+
const limit =
44+
typeof options.limit === 'number'
45+
? options.limit
46+
: parseInt(`${options.limit || ''}`, 10)
47+
48+
options.limit = Number.isNaN(limit) ? Infinity : limit
49+
3150
options.purls = Array.isArray(options.purls)
3251
? options.purls.flatMap(p => p.split(/, */))
3352
: []

src/commands/fix/types.mts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export type FixOptions = {
99
autopilot?: boolean | undefined
1010
cwd?: string | undefined
1111
dryRun?: boolean | undefined
12+
limit?: number | undefined
1213
purls?: string[] | readonly string[] | undefined
1314
rangeStyle?: RangeStyle | undefined
1415
test?: boolean | undefined

src/utils/alerts-map.mts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export async function getAlertsMapFromArborist(
2929
const options = {
3030
__proto__: null,
3131
consolidate: false,
32+
limit: Infinity,
3233
nothrow: false,
3334
...options_
3435
} as GetAlertsMapFromArboristOptions
@@ -87,6 +88,7 @@ export async function getAlertsMapFromPnpmLockfile(
8788
const options = {
8889
__proto__: null,
8990
consolidate: false,
91+
limit: Infinity,
9092
nothrow: false,
9193
...options_
9294
} as GetAlertsMapFromPnpmLockfileOptions
@@ -100,6 +102,7 @@ export async function getAlertsMapFromPnpmLockfile(
100102
export type GetAlertsMapFromPurlsOptions = {
101103
consolidate?: boolean | undefined
102104
include?: AlertIncludeFilter | undefined
105+
limit?: number | undefined
103106
overrides?: { [key: string]: string } | undefined
104107
nothrow?: boolean | undefined
105108
spinner?: Spinner | undefined
@@ -112,6 +115,7 @@ export async function getAlertsMapFromPurls(
112115
const options = {
113116
__proto__: null,
114117
consolidate: false,
118+
limit: Infinity,
115119
nothrow: false,
116120
...options_
117121
} as GetAlertsMapFromPurlsOptions

src/utils/socket-package-alert.mts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -321,18 +321,27 @@ export type CveInfoByPkgId = Map<
321321

322322
export type GetCveInfoByPackageOptions = {
323323
exclude?: CveExcludeFilter | undefined
324+
limit?: number | undefined
324325
}
325326

326327
export function getCveInfoByAlertsMap(
327328
alertsMap: AlertsByPkgId,
328329
options?: GetCveInfoByPackageOptions | undefined
329330
): CveInfoByPkgId | null {
331+
const { exclude: _exclude, limit = Infinity } = {
332+
__proto__: null,
333+
...options
334+
} as GetCveInfoByPackageOptions
335+
console.log('limit', limit)
330336
const exclude = {
337+
__proto__: null,
331338
upgradable: true,
332-
...({ __proto__: null, ...options } as GetCveInfoByPackageOptions).exclude
333-
}
339+
..._exclude
340+
} as CveExcludeFilter
341+
342+
let count = 0
334343
let infoByPkg: CveInfoByPkgId | null = null
335-
for (const [pkgId, sockPkgAlerts] of alertsMap) {
344+
alertsMapLoop: for (const [pkgId, sockPkgAlerts] of alertsMap) {
336345
const purlObj = PackageURL.fromString(idToPurl(pkgId))
337346
const name = resolvePackageName(purlObj)
338347
for (const sockPkgAlert of sockPkgAlerts) {
@@ -362,6 +371,9 @@ export function getCveInfoByAlertsMap(
362371
vulnerableVersionRange.replace(/, +/g, ' ')
363372
).format()
364373
})
374+
if (++count >= limit) {
375+
break alertsMapLoop
376+
}
365377
} catch (e) {
366378
debugLog('getCveInfoByAlertsMap', {
367379
firstPatchedVersionIdentifier,

0 commit comments

Comments
 (0)