-
Notifications
You must be signed in to change notification settings - Fork 565
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1707 from snyk/feat/snyk-fix
Feat: snyk fix v1 (Python) in behind FF
- Loading branch information
Showing
33 changed files
with
2,281 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { DepGraphData } from '@snyk/dep-graph'; | ||
import { TestResult } from '../../../lib/ecosystems/types'; | ||
import { TestResult as LegacyTestResult } from '../../../lib/snyk-test/legacy'; | ||
|
||
export function convertLegacyTestResultToNew( | ||
testResult: LegacyTestResult, | ||
): TestResult { | ||
return { | ||
issuesData: {} as any, // TODO: add converter | ||
issues: [], // TODO: add converter | ||
remediation: testResult.remediation, | ||
// TODO: grab this once Ecosystems flow starts sending back ScanResult | ||
depGraphData: {} as DepGraphData, | ||
}; | ||
} |
25 changes: 25 additions & 0 deletions
25
src/cli/commands/fix/convert-legacy-test-result-to-scan-result.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { ScanResult } from '../../../lib/ecosystems/types'; | ||
import { TestResult } from '../../../lib/snyk-test/legacy'; | ||
|
||
export function convertLegacyTestResultToScanResult( | ||
testResult: TestResult, | ||
): ScanResult { | ||
if (!testResult.packageManager) { | ||
throw new Error( | ||
'Only results with packageManagers are supported for conversion', | ||
); | ||
} | ||
return { | ||
identity: { | ||
type: testResult.packageManager, | ||
// this is because not all plugins send it back today, but we should always have it | ||
targetFile: testResult.targetFile || testResult.displayTargetFile, | ||
}, | ||
name: testResult.projectName, | ||
// TODO: grab this once Ecosystems flow starts sending back ScanResult | ||
facts: [], | ||
policy: testResult.policy, | ||
// TODO: grab this once Ecosystems flow starts sending back ScanResult | ||
target: {} as any, | ||
}; | ||
} |
27 changes: 27 additions & 0 deletions
27
src/cli/commands/fix/convert-legacy-tests-results-to-fix-entities.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import * as fs from 'fs'; | ||
import * as pathLib from 'path'; | ||
import { convertLegacyTestResultToNew } from './convert-legacy-test-result-to-new'; | ||
import { convertLegacyTestResultToScanResult } from './convert-legacy-test-result-to-scan-result'; | ||
import { TestResult } from '../../../lib/snyk-test/legacy'; | ||
|
||
export function convertLegacyTestResultToFixEntities( | ||
testResults: (TestResult | TestResult[]) | Error, | ||
root: string, | ||
): any { | ||
if (testResults instanceof Error) { | ||
return []; | ||
} | ||
const oldResults = Array.isArray(testResults) ? testResults : [testResults]; | ||
return oldResults.map((res) => ({ | ||
workspace: { | ||
readFile: async (path: string) => { | ||
return fs.readFileSync(pathLib.resolve(root, path), 'utf8'); | ||
}, | ||
writeFile: async (path: string, content: string) => { | ||
return fs.writeFileSync(pathLib.resolve(root, path), content, 'utf8'); | ||
}, | ||
}, | ||
scanResult: convertLegacyTestResultToScanResult(res), | ||
testResult: convertLegacyTestResultToNew(res), | ||
})); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import * as pathLib from 'path'; | ||
|
||
import { isLocalFolder } from '../../../lib/detect'; | ||
|
||
export function getDisplayPath(path: string): string { | ||
if (!isLocalFolder(path)) { | ||
return path; | ||
} | ||
if (path === process.cwd()) { | ||
return '.'; | ||
} | ||
return pathLib.relative(process.cwd(), path); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
export = fix; | ||
|
||
import * as Debug from 'debug'; | ||
import * as snykFix from '@snyk/fix'; | ||
import * as ora from 'ora'; | ||
|
||
import { MethodArgs } from '../../args'; | ||
import * as snyk from '../../../lib'; | ||
import { TestResult } from '../../../lib/snyk-test/legacy'; | ||
|
||
import { convertLegacyTestResultToFixEntities } from './convert-legacy-tests-results-to-fix-entities'; | ||
import { formatTestError } from '../test/format-test-error'; | ||
import { processCommandArgs } from '../process-command-args'; | ||
import { validateCredentials } from '../test/validate-credentials'; | ||
import { validateTestOptions } from '../test/validate-test-options'; | ||
import { setDefaultTestOptions } from '../test/set-default-test-options'; | ||
import { validateFixCommandIsSupported } from './validate-fix-command-is-supported'; | ||
import { Options, TestOptions } from '../../../lib/types'; | ||
import { getDisplayPath } from './get-display-path'; | ||
|
||
const debug = Debug('snyk-fix'); | ||
const snykFixFeatureFlag = 'cliSnykFix'; | ||
|
||
interface FixOptions { | ||
dryRun?: boolean; | ||
quiet?: boolean; | ||
} | ||
async function fix(...args: MethodArgs): Promise<string> { | ||
const { options: rawOptions, paths } = await processCommandArgs<FixOptions>( | ||
...args, | ||
); | ||
const options = setDefaultTestOptions<FixOptions>(rawOptions); | ||
debug(options); | ||
await validateFixCommandIsSupported(options); | ||
validateTestOptions(options); | ||
validateCredentials(options); | ||
const results: snykFix.EntityToFix[] = []; | ||
results.push(...(await runSnykTestLegacy(options, paths))); | ||
|
||
// fix | ||
debug( | ||
`Organization has ${snykFixFeatureFlag} feature flag enabled for experimental Snyk fix functionality`, | ||
); | ||
const { dryRun, quiet } = options; | ||
const { fixSummary, meta } = await snykFix.fix(results, { dryRun, quiet }); | ||
if (meta.fixed === 0) { | ||
throw new Error(fixSummary); | ||
} | ||
return fixSummary; | ||
} | ||
|
||
/* @deprecated | ||
* TODO: once project envelope is default all code below will be deleted | ||
* we should be calling test via new Ecosystems instead | ||
*/ | ||
async function runSnykTestLegacy( | ||
options: Options & TestOptions & FixOptions, | ||
paths: string[], | ||
): Promise<snykFix.EntityToFix[]> { | ||
const results: snykFix.EntityToFix[] = []; | ||
const stdOutSpinner = ora({ | ||
isSilent: options.quiet, | ||
stream: process.stdout, | ||
}); | ||
const stdErrSpinner = ora({ | ||
isSilent: options.quiet, | ||
stream: process.stdout, | ||
}); | ||
stdErrSpinner.start(); | ||
stdOutSpinner.start(); | ||
|
||
for (const path of paths) { | ||
let displayPath = path; | ||
try { | ||
displayPath = getDisplayPath(path); | ||
stdOutSpinner.info(`Running \`snyk test\` for ${displayPath}`); | ||
// Create a copy of the options so a specific test can | ||
// modify them i.e. add `options.file` etc. We'll need | ||
// these options later. | ||
const snykTestOptions = { | ||
...options, | ||
path, | ||
projectName: options['project-name'], | ||
}; | ||
|
||
const testResults: TestResult[] = []; | ||
|
||
const testResultForPath: TestResult | TestResult[] = await snyk.test( | ||
path, | ||
{ ...snykTestOptions, quiet: true }, | ||
); | ||
testResults.push( | ||
...(Array.isArray(testResultForPath) | ||
? testResultForPath | ||
: [testResultForPath]), | ||
); | ||
const newRes = convertLegacyTestResultToFixEntities(testResults, path); | ||
results.push(...newRes); | ||
} catch (error) { | ||
const testError = formatTestError(error); | ||
const userMessage = `Test for ${displayPath} failed with error: ${testError.message}.\nRun \`snyk test ${displayPath} -d\` for more information.`; | ||
stdErrSpinner.fail(userMessage); | ||
debug(userMessage); | ||
} | ||
} | ||
stdOutSpinner.stop(); | ||
stdErrSpinner.stop(); | ||
return results; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import * as Debug from 'debug'; | ||
|
||
import { getEcosystemForTest } from '../../../lib/ecosystems'; | ||
|
||
import { isFeatureFlagSupportedForOrg } from '../../../lib/feature-flags'; | ||
import { CommandNotSupportedError } from '../../../lib/errors/command-not-supported'; | ||
import { FeatureNotSupportedByEcosystemError } from '../../../lib/errors/not-supported-by-ecosystem'; | ||
import { Options, TestOptions } from '../../../lib/types'; | ||
|
||
const debug = Debug('snyk-fix'); | ||
const snykFixFeatureFlag = 'cliSnykFix'; | ||
|
||
export async function validateFixCommandIsSupported( | ||
options: Options & TestOptions, | ||
): Promise<boolean> { | ||
if (options.docker) { | ||
throw new FeatureNotSupportedByEcosystemError('snyk fix', 'docker'); | ||
} | ||
|
||
const ecosystem = getEcosystemForTest(options); | ||
if (ecosystem) { | ||
throw new FeatureNotSupportedByEcosystemError('snyk fix', ecosystem); | ||
} | ||
|
||
const snykFixSupported = await isFeatureFlagSupportedForOrg( | ||
snykFixFeatureFlag, | ||
options.org, | ||
); | ||
|
||
if (!snykFixSupported.ok) { | ||
debug(snykFixSupported.userMessage); | ||
throw new CommandNotSupportedError('snyk fix', options.org || undefined); | ||
} | ||
|
||
return true; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...commands/test/generate-snyk-test-error.ts → src/cli/commands/test/format-test-error.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { CustomError } from './custom-error'; | ||
|
||
export class CommandNotSupportedError extends CustomError { | ||
public readonly command: string; | ||
public readonly org?: string; | ||
|
||
constructor(command: string, org?: string) { | ||
super(`${command} is not supported for org ${org}.`); | ||
this.code = 422; | ||
this.command = command; | ||
this.org = org; | ||
|
||
this.userMessage = `\`${command}\` is not supported ${ | ||
org ? `for org '${org}'` : '' | ||
}`; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { CustomError } from './custom-error'; | ||
import { SupportedPackageManagers } from '../package-managers'; | ||
import { Ecosystem } from '../ecosystems/types'; | ||
|
||
export class FeatureNotSupportedByEcosystemError extends CustomError { | ||
public readonly feature: string; | ||
|
||
constructor( | ||
feature: string, | ||
ecosystem: SupportedPackageManagers | Ecosystem, | ||
) { | ||
super(`Unsupported ecosystem ${ecosystem} for ${feature}.`); | ||
this.code = 422; | ||
this.feature = feature; | ||
|
||
this.userMessage = `\`${feature}\` is not supported for ecosystem '${ecosystem}'`; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.