Skip to content

Commit 23ef123

Browse files
authored
Filter by pr better (#630)
1 parent 7ae08c5 commit 23ef123

23 files changed

+318
-209
lines changed

src/commands/fix/git.mts

Lines changed: 64 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import semver from 'semver'
2+
13
import { PackageURL } from '@socketregistry/packageurl-js'
24
import { debugFn } from '@socketsecurity/registry/lib/debug'
35
import { normalizePath } from '@socketsecurity/registry/lib/path'
@@ -7,11 +9,12 @@ import { spawn } from '@socketsecurity/registry/lib/spawn'
79
import constants from '../../constants.mts'
810
import { getPurlObject } from '../../utils/purl.mts'
911
import {
10-
getPkgFullNameFromPurlObj,
12+
getPkgFullNameFromPurl,
1113
getSocketDevPackageOverviewUrlFromPurl,
1214
} from '../../utils/socket-url.mts'
1315

1416
import type { CResult } from '../../types.mts'
17+
import type { SocketArtifact } from '../../utils/alert/artifact.mts'
1518
import type { SpawnOptions } from '@socketsecurity/registry/lib/spawn'
1619

1720
export type GitCreateAndPushBranchOptions = {
@@ -21,10 +24,7 @@ export type GitCreateAndPushBranchOptions = {
2124
}
2225

2326
function formatBranchName(name: string): string {
24-
return name
25-
.replace(/[-_.\\/]+/g, '-')
26-
.replace(/[^-a-zA-Z0-9]+/g, '')
27-
.replace(/^-+|-+$/g, '')
27+
return name.replace(/[^-a-zA-Z0-9/._-]+/g, '+')
2828
}
2929

3030
export function getBaseGitBranch(): string {
@@ -37,19 +37,54 @@ export function getBaseGitBranch(): string {
3737
)
3838
}
3939

40-
export function getSocketBranchName(
41-
purl: string | PackageURL,
42-
newVersion: string,
43-
workspace?: string | undefined,
40+
export function getSocketBranchPurlTypeComponent(
41+
purl: string | PackageURL | SocketArtifact,
4442
): string {
4543
const purlObj = getPurlObject(purl)
46-
const fmtType = formatBranchName(purlObj.type)
47-
const fmtWorkspace = workspace ? `${formatBranchName(workspace)}` : 'root'
44+
return formatBranchName(purlObj.type)
45+
}
46+
47+
export function getSocketBranchFullNameComponent(
48+
pkgName: string | PackageURL | SocketArtifact,
49+
): string {
50+
const purlObj = getPurlObject(
51+
typeof pkgName === 'string' && !pkgName.startsWith('pkg:')
52+
? PackageURL.fromString(`pkg:unknown/${pkgName}`)
53+
: pkgName,
54+
)
4855
const fmtMaybeNamespace = purlObj.namespace
4956
? `${formatBranchName(purlObj.namespace)}--`
5057
: ''
51-
const fmtFullName = `${fmtMaybeNamespace}${formatBranchName(purlObj.name)}`
52-
const fmtVersion = formatBranchName(purlObj.version!)
58+
return `${fmtMaybeNamespace}${formatBranchName(purlObj.name)}`
59+
}
60+
61+
export function getSocketBranchPackageVersionComponent(
62+
version: string | PackageURL | SocketArtifact,
63+
): string {
64+
const purlObj = getPurlObject(
65+
typeof version === 'string' && !version.startsWith('pkg:')
66+
? PackageURL.fromString(`pkg:unknown/unknown@${version}`)
67+
: version,
68+
)
69+
return formatBranchName(purlObj.version!)
70+
}
71+
72+
export function getSocketBranchWorkspaceComponent(
73+
workspace: string | undefined,
74+
): string {
75+
return workspace ? formatBranchName(workspace) : 'root'
76+
}
77+
78+
export function getSocketBranchName(
79+
purl: string | PackageURL | SocketArtifact,
80+
newVersion: string,
81+
workspace?: string | undefined,
82+
): string {
83+
const purlObj = getPurlObject(purl)
84+
const fmtType = getSocketBranchPurlTypeComponent(purlObj)
85+
const fmtWorkspace = getSocketBranchWorkspaceComponent(workspace)
86+
const fmtFullName = getSocketBranchFullNameComponent(purlObj)
87+
const fmtVersion = getSocketBranchPackageVersionComponent(purlObj.version!)
5388
const fmtNewVersion = formatBranchName(newVersion)
5489
return `socket/${fmtType}_${fmtWorkspace}_${fmtFullName}_${fmtVersion}_${fmtNewVersion}`
5590
}
@@ -94,18 +129,21 @@ export type SocketBranchParser = (
94129
) => SocketBranchParseResult | null
95130

96131
export type SocketBranchParseResult = {
132+
fullName: string
97133
newVersion: string
98-
purl: PackageURL
134+
type: string
99135
workspace: string
136+
version: string
100137
}
101138

102139
export function createSocketBranchParser(
103140
options?: SocketBranchPatternOptions | undefined,
104141
): SocketBranchParser {
105142
const pattern = getSocketBranchPattern(options)
106143
return function parse(branch: string): SocketBranchParseResult | null {
107-
debugFn('pattern', pattern.toString())
108-
const match = pattern.exec(branch)
144+
const match = pattern.exec(branch) as
145+
| [string, string, string, string, string, string]
146+
| null
109147
if (!match) {
110148
return null
111149
}
@@ -117,41 +155,43 @@ export function createSocketBranchParser(
117155
5: newVersion,
118156
} = match
119157
return {
120-
newVersion,
121-
purl: getPurlObject(`pkg:${type}/${fullName}@${version}`),
158+
fullName,
159+
newVersion: semver.coerce(newVersion.replaceAll('+', '.'))?.version,
160+
type,
122161
workspace,
162+
version: semver.coerce(version.replaceAll('+', '.'))?.version,
123163
} as SocketBranchParseResult
124164
}
125165
}
126166

127167
export function getSocketPullRequestTitle(
128-
purl: string | PackageURL,
168+
purl: string | PackageURL | SocketArtifact,
129169
newVersion: string,
130170
workspace?: string | undefined,
131171
): string {
132172
const purlObj = getPurlObject(purl)
133-
const fullName = getPkgFullNameFromPurlObj(purlObj)
173+
const fullName = getPkgFullNameFromPurl(purlObj)
134174
return `Bump ${fullName} from ${purlObj.version} to ${newVersion}${workspace ? ` in ${workspace}` : ''}`
135175
}
136176

137177
export function getSocketPullRequestBody(
138-
purl: string | PackageURL,
178+
purl: string | PackageURL | SocketArtifact,
139179
newVersion: string,
140180
workspace?: string | undefined,
141181
): string {
142182
const purlObj = getPurlObject(purl)
143-
const fullName = getPkgFullNameFromPurlObj(purlObj)
183+
const fullName = getPkgFullNameFromPurl(purlObj)
144184
const pkgOverviewUrl = getSocketDevPackageOverviewUrlFromPurl(purlObj)
145185
return `Bump [${fullName}](${pkgOverviewUrl}) from ${purlObj.version} to ${newVersion}${workspace ? ` in ${workspace}` : ''}.`
146186
}
147187

148188
export function getSocketCommitMessage(
149-
purl: string | PackageURL,
189+
purl: string | PackageURL | SocketArtifact,
150190
newVersion: string,
151191
workspace?: string | undefined,
152192
): string {
153193
const purlObj = getPurlObject(purl)
154-
const fullName = getPkgFullNameFromPurlObj(purlObj)
194+
const fullName = getPkgFullNameFromPurl(purlObj)
155195
return `socket: Bump ${fullName} from ${purlObj.version} to ${newVersion}${workspace ? ` in ${workspace}` : ''}`
156196
}
157197

src/commands/fix/npm-fix.mts

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,11 @@ import {
1515
import { naturalCompare } from '@socketsecurity/registry/lib/sorts'
1616

1717
import {
18+
createSocketBranchParser,
1819
getBaseGitBranch,
20+
getSocketBranchFullNameComponent,
1921
getSocketBranchName,
22+
getSocketBranchPurlTypeComponent,
2023
getSocketCommitMessage,
2124
gitCreateAndPushBranch,
2225
gitRemoteBranchExists,
@@ -49,21 +52,22 @@ import {
4952
import { getAlertsMapFromPurls } from '../../utils/alerts-map.mts'
5053
import { removeNodeModules } from '../../utils/fs.mts'
5154
import { globWorkspace } from '../../utils/glob.mts'
55+
import { getPurlObject } from '../../utils/purl.mts'
5256
import { applyRange } from '../../utils/semver.mts'
5357
import { getCveInfoFromAlertsMap } from '../../utils/socket-package-alert.mts'
5458
import { idToPurl } from '../../utils/spec.mts'
5559

60+
import type { SocketBranchParseResult } from './git.mts'
5661
import type {
5762
ArboristInstance,
5863
NodeClass,
5964
} from '../../shadow/npm/arborist/types.mts'
6065
import type { CResult } from '../../types.mts'
66+
import type { PURL_Type } from '../../utils/alert/artifact.mts'
6167
import type { EnvDetails } from '../../utils/package-environment.mts'
6268
import type { RangeStyle } from '../../utils/semver.mts'
6369
import type { PackageJson } from '@socketsecurity/registry/lib/packages'
6470

65-
const { NPM } = constants
66-
6771
type InstallOptions = {
6872
cwd?: string | undefined
6973
}
@@ -171,16 +175,17 @@ export async function npmFix(
171175
}
172176
}
173177

174-
const infoByPkgName = getCveInfoFromAlertsMap(alertsMap, {
178+
const infoByPartialPurl = getCveInfoFromAlertsMap(alertsMap, {
175179
limit: limit + openPrs.length,
176180
})
177-
if (!infoByPkgName) {
181+
if (!infoByPartialPurl) {
178182
spinner?.stop()
179183
logger.info('No fixable vulns found.')
180184
return { ok: true, data: { fixed: false } }
181185
}
182186

183187
const baseBranch = isCi ? getBaseGitBranch() : ''
188+
const branchParser = isCi ? createSocketBranchParser() : null
184189
const workspacePkgJsonPaths = await globWorkspace(
185190
pkgEnvDetails.agent,
186191
rootPath,
@@ -190,7 +195,7 @@ export async function npmFix(
190195
// Process the workspace root last since it will add an override to package.json.
191196
pkgEnvDetails.editablePkgJson.filename!,
192197
]
193-
const sortedInfoEntries = [...infoByPkgName.entries()].sort((a, b) =>
198+
const sortedInfoEntries = [...infoByPartialPurl.entries()].sort((a, b) =>
194199
naturalCompare(a[0], b[0]),
195200
)
196201

@@ -215,16 +220,29 @@ export async function npmFix(
215220
) {
216221
const isLastInfoEntry = i === length - 1
217222
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-
)
223+
const partialPurlObj = getPurlObject(infoEntry[0])
224+
const name = resolvePackageName(partialPurlObj)
225+
let infos = [...infoEntry[1].values()]
226+
if (isCi) {
227+
const branchFullName = getSocketBranchFullNameComponent(partialPurlObj)
228+
const branchPurlType = getSocketBranchPurlTypeComponent(partialPurlObj)
229+
const activeBranches: SocketBranchParseResult[] = []
230+
for (const pr of openPrs) {
231+
const parsedBranch = branchParser!(pr.headRefName)
232+
if (
233+
branchPurlType === parsedBranch?.type &&
234+
branchFullName === parsedBranch?.fullName
235+
) {
236+
activeBranches.push(parsedBranch)
237+
}
238+
}
239+
infos = infos.filter(
240+
info =>
241+
!activeBranches.find(
242+
b => b.newVersion === info.firstPatchedVersionIdentifier,
243+
),
244+
)
245+
}
228246

229247
if (!infos.length) {
230248
continue infoEntriesLoop
@@ -234,7 +252,7 @@ export async function npmFix(
234252
logger.indent()
235253
spinner?.indent()
236254

237-
if (getManifestData(NPM, name)) {
255+
if (getManifestData(partialPurlObj.type as PURL_Type, name)) {
238256
debugFn(`found: Socket Optimize variant for ${name}`)
239257
}
240258
// eslint-disable-next-line no-await-in-loop
@@ -295,7 +313,7 @@ export async function npmFix(
295313

296314
oldVersionsLoop: for (const oldVersion of oldVersions) {
297315
const oldId = `${name}@${oldVersion}`
298-
const oldPurl = idToPurl(oldId)
316+
const oldPurl = idToPurl(oldId, partialPurlObj.type)
299317

300318
const node = findPackageNode(actualTree, name, oldVersion)
301319
if (!node) {

0 commit comments

Comments
 (0)