Skip to content

Commit 179f11a

Browse files
authored
Skip patches for open prs (#620)
1 parent 0d754ed commit 179f11a

File tree

4 files changed

+213
-92
lines changed

4 files changed

+213
-92
lines changed

src/commands/fix/git.mts

Lines changed: 89 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { escapeRegExp } from '@socketsecurity/registry/lib/regexps'
55
import { spawn } from '@socketsecurity/registry/lib/spawn'
66

77
import constants from '../../constants.mts'
8+
import { getPurlObject } from '../../utils/purl.mts'
89
import {
910
getPkgFullNameFromPurlObj,
1011
getSocketDevPackageOverviewUrlFromPurl,
@@ -13,11 +14,6 @@ import {
1314
import type { CResult } from '../../types.mts'
1415
import type { SpawnOptions } from '@socketsecurity/registry/lib/spawn'
1516

16-
export type GetSocketPrTitlePatternOptions = {
17-
purl?: string | undefined
18-
workspace?: string | undefined
19-
}
20-
2117
export type GitCreateAndPushBranchOptions = {
2218
cwd?: string | undefined
2319
email?: string | undefined
@@ -42,72 +38,120 @@ export function getBaseGitBranch(): string {
4238
}
4339

4440
export function getSocketBranchName(
45-
purl: string,
41+
purl: string | PackageURL,
4642
newVersion: string,
47-
workspaceName?: string | undefined,
43+
workspace?: string | undefined,
4844
): string {
49-
const purlObj = PackageURL.fromString(purl)
50-
const maybeWorkspaceName = workspaceName
51-
? `${formatBranchName(workspaceName)}-`
52-
: ''
53-
const maybeNamespace = purlObj.namespace
54-
? `${formatBranchName(purlObj.namespace)}-`
45+
const purlObj = getPurlObject(purl)
46+
const fmtType = formatBranchName(purlObj.type)
47+
const fmtWorkspace = workspace ? `${formatBranchName(workspace)}` : 'root'
48+
const fmtMaybeNamespace = purlObj.namespace
49+
? `${formatBranchName(purlObj.namespace)}--`
5550
: ''
56-
const fullName = `${maybeWorkspaceName}${maybeNamespace}${formatBranchName(purlObj.name)}`
57-
return `socket/${fullName}-${formatBranchName(newVersion)}`
51+
const fmtFullName = `${fmtMaybeNamespace}${formatBranchName(purlObj.name)}`
52+
const fmtVersion = formatBranchName(purlObj.version!)
53+
const fmtNewVersion = formatBranchName(newVersion)
54+
return `socket/${fmtType}_${fmtWorkspace}_${fmtFullName}_${fmtVersion}_${fmtNewVersion}`
5855
}
5956

60-
export function getSocketPrTitlePattern(
61-
options?: GetSocketPrTitlePatternOptions | undefined,
57+
export type SocketBranchPatternOptions = {
58+
newVersion?: string | undefined
59+
purl?: string | undefined
60+
workspace?: string | undefined
61+
}
62+
63+
export function getSocketBranchPattern(
64+
options?: SocketBranchPatternOptions | undefined,
6265
): RegExp {
63-
const { purl, workspace } = {
66+
const { newVersion, purl, workspace } = {
6467
__proto__: null,
6568
...options,
66-
} as GetSocketPrTitlePatternOptions
67-
const purlObj = purl ? PackageURL.fromString(purl) : null
68-
const escapedPkgFullName = purlObj
69-
? escapeRegExp(getPkgFullNameFromPurlObj(purlObj))
70-
: '\\S+'
71-
const escapedPkgVersion = purlObj ? escapeRegExp(purlObj.version!) : '\\S+'
72-
const escapedWorkspaceDetails = workspace
73-
? ` in ${escapeRegExp(workspace)}`
69+
} as SocketBranchPatternOptions
70+
const purlObj = purl ? getPurlObject(purl) : null
71+
const escType = purlObj ? escapeRegExp(purlObj.type) : '[^_]+'
72+
const escWorkspace = workspace
73+
? `${escapeRegExp(formatBranchName(workspace))}`
74+
: 'root'
75+
const escMaybeNamespace = purlObj?.namespace
76+
? `${escapeRegExp(formatBranchName(purlObj.namespace))}--`
7477
: ''
78+
const escFullName = purlObj
79+
? `${escMaybeNamespace}${escapeRegExp(formatBranchName(purlObj.name))}`
80+
: '[^_]+'
81+
const escVersion = purlObj
82+
? escapeRegExp(formatBranchName(purlObj.version!))
83+
: '[^_]+'
84+
const escNewVersion = newVersion
85+
? escapeRegExp(formatBranchName(newVersion))
86+
: '[^_]+'
7587
return new RegExp(
76-
`Bump ${escapedPkgFullName} from ${escapedPkgVersion} to \\S+${escapedWorkspaceDetails}`,
88+
`^socket/(${escType})_(${escWorkspace})_(${escFullName})_(${escVersion})_(${escNewVersion})$`,
7789
)
7890
}
7991

92+
export type SocketBranchParser = (
93+
branch: string,
94+
) => SocketBranchParseResult | null
95+
96+
export type SocketBranchParseResult = {
97+
newVersion: string
98+
purl: PackageURL
99+
workspace: string
100+
}
101+
102+
export function createSocketBranchParser(
103+
options?: SocketBranchPatternOptions | undefined,
104+
): SocketBranchParser {
105+
const pattern = getSocketBranchPattern(options)
106+
return function parse(branch: string): SocketBranchParseResult | null {
107+
const match = pattern.exec(branch)
108+
if (!match) {
109+
return null
110+
}
111+
const {
112+
0: type,
113+
1: workspace,
114+
2: fullName,
115+
3: version,
116+
4: newVersion,
117+
} = match
118+
return {
119+
newVersion,
120+
purl: getPurlObject(`pkg:${type}/${fullName}@${version}`),
121+
workspace,
122+
} as SocketBranchParseResult
123+
}
124+
}
125+
80126
export function getSocketPullRequestTitle(
81-
purl: string,
82-
toVersion: string,
127+
purl: string | PackageURL,
128+
newVersion: string,
83129
workspace?: string | undefined,
84130
): string {
85-
const purlObj = PackageURL.fromString(purl)
86-
const pkgFullName = getPkgFullNameFromPurlObj(purlObj)
87-
const workspaceDetails = workspace ? ` in ${workspace}` : ''
88-
return `Bump ${pkgFullName} from ${purlObj.version} to ${toVersion}${workspaceDetails}`
131+
const purlObj = getPurlObject(purl)
132+
const fullName = getPkgFullNameFromPurlObj(purlObj)
133+
return `Bump ${fullName} from ${purlObj.version} to ${newVersion}${workspace ? ` in ${workspace}` : ''}`
89134
}
90135

91136
export function getSocketPullRequestBody(
92-
purl: string,
137+
purl: string | PackageURL,
93138
newVersion: string,
94-
workspaceName?: string | undefined,
139+
workspace?: string | undefined,
95140
): string {
96-
const purlObj = PackageURL.fromString(purl)
97-
const pkgFullName = getPkgFullNameFromPurlObj(purlObj)
98-
const workspaceDetails = workspaceName ? ` in ${workspaceName}` : ''
99-
return `Bump [${pkgFullName}](${getSocketDevPackageOverviewUrlFromPurl(purlObj)}) from ${purlObj.version} to ${newVersion}${workspaceDetails}.`
141+
const purlObj = getPurlObject(purl)
142+
const fullName = getPkgFullNameFromPurlObj(purlObj)
143+
const pkgOverviewUrl = getSocketDevPackageOverviewUrlFromPurl(purlObj)
144+
return `Bump [${fullName}](${pkgOverviewUrl}) from ${purlObj.version} to ${newVersion}${workspace ? ` in ${workspace}` : ''}.`
100145
}
101146

102147
export function getSocketCommitMessage(
103-
purl: string,
148+
purl: string | PackageURL,
104149
newVersion: string,
105-
workspaceName?: string | undefined,
150+
workspace?: string | undefined,
106151
): string {
107-
const purlObj = PackageURL.fromString(purl)
108-
const pkgFullName = getPkgFullNameFromPurlObj(purlObj)
109-
const workspaceDetails = workspaceName ? ` in ${workspaceName}` : ''
110-
return `socket: Bump ${pkgFullName} from ${purlObj.version} to ${newVersion}${workspaceDetails}`
152+
const purlObj = getPurlObject(purl)
153+
const fullName = getPkgFullNameFromPurlObj(purlObj)
154+
return `socket: Bump ${fullName} from ${purlObj.version} to ${newVersion}${workspace ? ` in ${workspace}` : ''}`
111155
}
112156

113157
export async function gitCleanFdx(cwd = process.cwd()): Promise<void> {

src/commands/fix/npm-fix.mts

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { runScript } from '@socketsecurity/registry/lib/npm'
1010
import {
1111
fetchPackagePackument,
1212
readPackageJson,
13+
resolvePackageName,
1314
} from '@socketsecurity/registry/lib/packages'
1415
import { naturalCompare } from '@socketsecurity/registry/lib/sorts'
1516

@@ -25,11 +26,11 @@ import {
2526
import {
2627
cleanupOpenPrs,
2728
enablePrAutoMerge,
28-
getGitHubEnvRepoInfo,
29+
getGithubEnvRepoInfo,
2930
getOpenSocketPrs,
3031
openPr,
3132
prExistForBranch,
32-
setGitRemoteGitHubRepoUrl,
33+
setGitRemoteGithubRepoUrl,
3334
} from './open-pr.mts'
3435
import { getAlertsMapOptions } from './shared.mts'
3536
import constants from '../../constants.mts'
@@ -123,7 +124,7 @@ export async function npmFix(
123124
githubToken
124125
)
125126

126-
const repoInfo = isCi ? getGitHubEnvRepoInfo()! : null
127+
const repoInfo = isCi ? getGithubEnvRepoInfo()! : null
127128

128129
spinner?.start()
129130

@@ -135,6 +136,10 @@ export async function npmFix(
135136
})
136137
: []
137138

139+
if (openPrs.length) {
140+
debugFn(`found: ${openPrs.length} open PRs`)
141+
}
142+
138143
let count = isCi ? openPrs.length : 0
139144

140145
const arb = new Arborist({
@@ -148,8 +153,14 @@ export async function npmFix(
148153
let alertsMap
149154
try {
150155
alertsMap = purls.length
151-
? await getAlertsMapFromPurls(purls, getAlertsMapOptions({ limit }))
152-
: await getAlertsMapFromArborist(arb, getAlertsMapOptions({ limit }))
156+
? await getAlertsMapFromPurls(
157+
purls,
158+
getAlertsMapOptions({ limit: limit + openPrs.length }),
159+
)
160+
: await getAlertsMapFromArborist(
161+
arb,
162+
getAlertsMapOptions({ limit: limit + openPrs.length }),
163+
)
153164
} catch (e) {
154165
spinner?.stop()
155166
debugFn('catch: PURL API\n', e)
@@ -160,7 +171,9 @@ export async function npmFix(
160171
}
161172
}
162173

163-
const infoByPkgName = getCveInfoFromAlertsMap(alertsMap, { limit })
174+
const infoByPkgName = getCveInfoFromAlertsMap(alertsMap, {
175+
limit: limit + openPrs.length,
176+
})
164177
if (!infoByPkgName) {
165178
spinner?.stop()
166179
logger.info('No fixable vulns found.')
@@ -201,7 +214,21 @@ export async function npmFix(
201214
i += 1
202215
) {
203216
const isLastInfoEntry = i === length - 1
204-
const { 0: name, 1: infos } = sortedInfoEntries[i]!
217+
const infoEntry = sortedInfoEntries[i]!
218+
const { 0: name } = infoEntry
219+
const openPrsForPkg = openPrs.filter(
220+
pr => name === resolvePackageName(pr.purl),
221+
)
222+
const infos = [...infoEntry[1].values()].filter(
223+
info =>
224+
!openPrsForPkg.find(
225+
pr => pr.newVersion === info.firstPatchedVersionIdentifier,
226+
),
227+
)
228+
229+
if (!infos.length) {
230+
continue infoEntriesLoop
231+
}
205232

206233
logger.log(`Processing vulns for ${name}:`)
207234
logger.indent()
@@ -444,13 +471,14 @@ export async function npmFix(
444471

445472
// eslint-disable-next-line no-await-in-loop
446473
await Promise.allSettled([
447-
setGitRemoteGitHubRepoUrl(
474+
setGitRemoteGithubRepoUrl(
448475
repoInfo.owner,
449476
repoInfo.repo,
450477
githubToken,
451478
cwd,
452479
),
453-
cleanupOpenPrs(repoInfo.owner, repoInfo.repo, newVersion, {
480+
cleanupOpenPrs(repoInfo.owner, repoInfo.repo, {
481+
newVersion,
454482
purl: oldPurl,
455483
workspace,
456484
}),

0 commit comments

Comments
 (0)