-
Notifications
You must be signed in to change notification settings - Fork 580
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(protect): skip previously patched files #2175
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,7 @@ | ||
#!/usr/bin/env node | ||
require('../dist/index.js').protect(); | ||
require('../dist/index.js') | ||
.protect() | ||
.catch((error) => { | ||
// don't block pipelines on unexpected errors | ||
console.error(error); | ||
}); | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,7 +26,7 @@ async function protect(projectFolderPath: string) { | |
const snykFilePath = path.resolve(projectFolderPath, '.snyk'); | ||
|
||
if (!fs.existsSync(snykFilePath)) { | ||
console.log('No .snyk file found'); | ||
console.log('No .snyk file found.'); | ||
sendAnalytics({ | ||
type: ProtectResultType.NO_SNYK_FILE, | ||
}); | ||
|
@@ -67,7 +67,7 @@ async function protect(projectFolderPath: string) { | |
> = await getAllPatches(vulnIdAndPackageNames, packageNameToVersionsMap); | ||
|
||
if (packageAtVersionsToPatches.size === 0) { | ||
console.log('Nothing to patch'); | ||
console.log('Nothing to patch.'); | ||
sendAnalytics({ | ||
type: ProtectResultType.NOTHING_TO_PATCH, | ||
}); | ||
|
@@ -83,7 +83,8 @@ async function protect(projectFolderPath: string) { | |
vuldIdAndPatches?.forEach((vp) => { | ||
vp.patches.forEach((patchDiffs) => { | ||
patchDiffs.patchDiffs.forEach((diff) => { | ||
applyPatchToFile(diff, fpp.path); | ||
const patchedPath = applyPatchToFile(diff, fpp.path); | ||
console.log(`Patched: ${patchedPath}`); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I moved this log line here so it's clear exactly what we're printing to stdout for the user to see in a single top-level file. |
||
}); | ||
}); | ||
patchedModules.push({ | ||
|
@@ -94,7 +95,7 @@ async function protect(projectFolderPath: string) { | |
}); | ||
}); | ||
|
||
console.log('Successfully applied Snyk patches'); | ||
console.log('Applied Snyk patches.'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "Applied" already implies success. Less words, better. |
||
|
||
sendAnalytics({ | ||
type: ProtectResultType.APPLIED_PATCHES, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,10 +6,17 @@ export function applyPatchToFile(patchContents: string, baseFolder: string) { | |
baseFolder, | ||
extractTargetFilePathFromPatch(patchContents), | ||
); | ||
|
||
const flagPath = `${targetFilePath}.snyk-protect.flag`; | ||
if (fs.existsSync(flagPath)) { | ||
return targetFilePath; | ||
} | ||
|
||
const contentsToPatch = fs.readFileSync(targetFilePath, 'utf-8'); | ||
const patchedContents = patchString(patchContents, contentsToPatch); | ||
fs.writeFileSync(targetFilePath, patchedContents); | ||
console.log(`patched ${targetFilePath}`); | ||
fs.writeFileSync(flagPath, ''); | ||
return targetFilePath; | ||
} | ||
|
||
export function extractTargetFilePathFromPatch(patchContents: string): string { | ||
|
@@ -39,13 +46,11 @@ export function patchString( | |
const contentsToPatchLines = contentsToPatch.split('\n'); | ||
|
||
if (!patchContentLines[2]) { | ||
// return; | ||
throw new Error('Invalid patch'); | ||
throw new Error('Invalid patch.'); | ||
} | ||
const unparsedLineToPatch = /^@@ -(\d*),.*@@/.exec(patchContentLines[2]); | ||
if (!unparsedLineToPatch || !unparsedLineToPatch[1]) { | ||
// return; | ||
throw new Error('Invalid patch'); | ||
throw new Error('Invalid patch.'); | ||
} | ||
let lineToPatch = parseInt(unparsedLineToPatch[1], 10) - 2; | ||
|
||
|
@@ -66,16 +71,13 @@ export function patchString( | |
} | ||
case ' ': { | ||
if (currentLine !== nextLine) { | ||
console.log( | ||
'Expected\n line from local file\n', | ||
JSON.stringify(currentLine), | ||
'\n to match patch line\n', | ||
JSON.stringify(nextLine), | ||
'\n', | ||
); | ||
Comment on lines
-69
to
-75
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I moved this into the error message, otherwise it prints out back-to-front which is confusing. |
||
throw new Error( | ||
// `File ${filename} to be patched does not match, not patching`, | ||
`File to be patched does not match, not patching`, | ||
'File does not match patch contents.' + | ||
' Expected\n' + | ||
' line from local file\n' + | ||
` ${JSON.stringify(currentLine)}\n` + | ||
' to match patch line\n' + | ||
` ${JSON.stringify(nextLine)}\n`, | ||
); | ||
} | ||
break; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is existing behaviour. Previously we let NodeJS handle "unhandled rejections" which it does by printing a warning and exiting with zero. However, the warnings state they'll change it to a non-zero in the future so it's best that we handle it ourselves. We still exit with zero as errors on our end should not block pipelines.