From c5e1bdcfbf60956aeeb9ebc12d5086346c8c6f0e Mon Sep 17 00:00:00 2001 From: Peter van der Zee Date: Tue, 11 Feb 2025 13:48:51 +0100 Subject: [PATCH 1/4] scan create: upload a pom.xml --- src/commands/scan/create.ts | 37 ++++++++++++++++++++++++++++++------- src/utils/path-resolve.ts | 22 +++++++++++++++------- 2 files changed, 45 insertions(+), 14 deletions(-) diff --git a/src/commands/scan/create.ts b/src/commands/scan/create.ts index b14e50f03..ae761210a 100644 --- a/src/commands/scan/create.ts +++ b/src/commands/scan/create.ts @@ -29,7 +29,7 @@ export const create: CliSubcommand = { } const spinnerText = 'Creating a scan... \n' const spinner = new Spinner({ text: spinnerText }).start() - await createFullScan(input, spinner, apiToken) + await createFullScan(input, spinner, apiToken, input.cwd) } } } @@ -59,6 +59,10 @@ const createFullScanFlags: { [key: string]: any } = { default: '', description: 'Commit hash' }, + cwd: { + type: 'string', + description: 'working directory, defaults to process.cwd()' + }, pullRequest: { type: 'number', shortFlag: 'pr', @@ -76,6 +80,10 @@ const createFullScanFlags: { [key: string]: any } = { default: false, description: 'Make default branch' }, + org: { + type: 'string', + description: 'Set your org name' + }, pendingHead: { type: 'boolean', shortFlag: 'ph', @@ -93,6 +101,7 @@ const createFullScanFlags: { [key: string]: any } = { // Internal functions type CommandContext = { + cwd: string orgSlug: string repoName: string branchName: string @@ -118,7 +127,12 @@ async function setupCommand( const cli = meow( ` Usage - $ ${name} [...options] + $ ${name} [...options] FILE|DIR + + The FILE or DIR must be inside the CWD. + + When a FILE is given only that FILE is targted. Otherwise any eligible + files in the given DIR will be considered. Options ${getFlagListOutput(flags, 6)} @@ -141,8 +155,7 @@ async function setupCommand( cli.showHelp() return } - const { 0: orgSlug = '' } = cli.input - const cwd = process.cwd() + const socketSdk = await setupSdk() const supportedFiles = await socketSdk .getReportSupportedFiles() @@ -163,6 +176,13 @@ async function setupCommand( }) } ) + + // TODO: I think the cwd should be set to the DIR|FILE arg of this command and the DIR/FILE be either '.' or the filename() of the arg + const cwd = + cli.flags['cwd'] && cli.flags['cwd'] !== 'process.cwd()' + ? String(cli.flags['cwd']) + : process.cwd() + const packagePaths = await getPackageFilesFullScans( cwd, cli.input, @@ -181,7 +201,8 @@ async function setupCommand( return } return { - orgSlug, + cwd, + orgSlug: cli.flags['org'], repoName, branchName, commitMessage: cli.flags['commitMessage'], @@ -198,7 +219,8 @@ async function setupCommand( async function createFullScan( input: CommandContext, spinner: Spinner, - apiToken: string + apiToken: string, + cwd: string = process.cwd() ): Promise { const socketSdk = await setupSdk(apiToken) const { @@ -222,7 +244,8 @@ async function createFullScan( set_as_pending_head: pendingHead, tmp }, - packagePaths + packagePaths, + cwd ), 'Creating scan' ) diff --git a/src/utils/path-resolve.ts b/src/utils/path-resolve.ts index 10e1498c6..96b150522 100644 --- a/src/utils/path-resolve.ts +++ b/src/utils/path-resolve.ts @@ -25,13 +25,18 @@ async function filterGlobResultToSupportedFiles( entries: string[], supportedFiles: SocketSdkReturnType<'getReportSupportedFiles'>['data'] ): Promise { - const patterns = ['golang', NPM, 'pypi'].reduce((r: string[], n: string) => { - const supported = supportedFiles[n] - r.push( - ...(supported ? Object.values(supported).map(p => `**/${p.pattern}`) : []) - ) - return r - }, []) + const patterns = ['golang', NPM, 'maven', 'pypi'].reduce( + (r: string[], n: string) => { + const supported = supportedFiles[n] + r.push( + ...(supported + ? Object.values(supported).map(p => `**/${p.pattern}`) + : []) + ) + return r + }, + [] + ) return entries.filter(p => micromatch.some(p, patterns)) } @@ -84,6 +89,9 @@ async function globWithGitIgnore( return result } const { absolute } = globOptions + + // Note: the input files must be INSIDE the cwd. If you get strange looking + // relative path errors here, most likely your path is outside the given cwd. const filtered = ignore() .add(ignores) .filter(absolute ? result.map(p => path.relative(cwd, p)) : result) From 074595681c4b6daecf6b6a9aa3bd2c72da357196 Mon Sep 17 00:00:00 2001 From: Peter van der Zee Date: Thu, 13 Feb 2025 18:45:32 +0100 Subject: [PATCH 2/4] Keep org slug as first param as not to break backwards compat --- src/commands/scan/create.ts | 47 ++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/src/commands/scan/create.ts b/src/commands/scan/create.ts index aa644db19..3f1a984c9 100644 --- a/src/commands/scan/create.ts +++ b/src/commands/scan/create.ts @@ -80,10 +80,6 @@ const createFullScanFlags: { [key: string]: any } = { default: false, description: 'Make default branch' }, - org: { - type: 'string', - description: 'Set your org name' - }, pendingHead: { type: 'boolean', shortFlag: 'ph', @@ -127,18 +123,18 @@ async function setupCommand( const cli = meow( ` Usage - $ ${name} [...options] FILE|DIR + $ ${name} [...options] [TARGET ...] - The FILE or DIR must be inside the CWD. + Where TARGET is a FILE or DIR that _must_ be inside the CWD. - When a FILE is given only that FILE is targted. Otherwise any eligible + When a FILE is given only that FILE is targeted. Otherwise any eligible files in the given DIR will be considered. Options ${getFlagListOutput(flags, 6)} Examples - $ ${name} --org=FakeOrg --repo=test-repo --branch=main ./package.json + $ ${name} --repo=test-repo --branch=main FakeOrg ./package.json `, { argv, @@ -147,14 +143,8 @@ async function setupCommand( flags } ) + let showHelp = cli.flags['help'] - if (!cli.input[0]) { - showHelp = true - } - if (showHelp) { - cli.showHelp() - return - } const socketSdk = await setupSdk() const supportedFiles = await socketSdk @@ -183,26 +173,41 @@ async function setupCommand( ? String(cli.flags['cwd']) : process.cwd() + const [orgSlug, ...targets] = cli.input + const packagePaths = await getPackageFilesFullScans( cwd, - cli.input, + targets, supportedFiles ) + const { branch: branchName, repo: repoName } = cli.flags - if (!repoName || !branchName || !packagePaths.length) { + if (!orgSlug || !repoName || !branchName || !packagePaths.length) { showHelp = true console.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n - - Repository name using --repo ${!repoName ? colors.red('(missing!)') : colors.green('(ok)')}\n - - Branch name using --branch ${!branchName ? colors.red('(missing!)') : colors.green('(ok)')}\n - - At least one file path (e.g. ./package.json) ${!packagePaths.length ? colors.red('(missing or no matching/supported files found!)') : colors.green('(ok)')}`) + - Org name as first arg ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\n + - Repository name using --repo ${!repoName ? colors.red('(missing!)') : colors.green('(ok)')}\n + - Branch name using --branch ${!branchName ? colors.red('(missing!)') : colors.green('(ok)')}\n + - At least one file path (e.g. ./package.json) ${ + !packagePaths.length + ? colors.red( + targets.length > 0 + ? '(TARGET' + + (targets.length ? 's' : '') + + ' contained no matching/supported files!)' + : '(missing)' + ) + : colors.green('(ok)') + }`) } if (showHelp) { cli.showHelp() return } + return { cwd, - orgSlug: cli.flags['org'], + orgSlug, repoName, branchName, commitMessage: cli.flags['commitMessage'], From f528f4b12b53fd31e520d1cc852f5d9042804871 Mon Sep 17 00:00:00 2001 From: Peter van der Zee Date: Thu, 13 Feb 2025 19:16:19 +0100 Subject: [PATCH 3/4] use TARGET --- src/commands/scan/create.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/scan/create.ts b/src/commands/scan/create.ts index 3f1a984c9..f61780e8b 100644 --- a/src/commands/scan/create.ts +++ b/src/commands/scan/create.ts @@ -188,7 +188,7 @@ async function setupCommand( - Org name as first arg ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\n - Repository name using --repo ${!repoName ? colors.red('(missing!)') : colors.green('(ok)')}\n - Branch name using --branch ${!branchName ? colors.red('(missing!)') : colors.green('(ok)')}\n - - At least one file path (e.g. ./package.json) ${ + - At least TARGET (e.g. \`.\` or \`./package.json\`) ${ !packagePaths.length ? colors.red( targets.length > 0 From a5beb27ee05af76c1e381bca679728411824717f Mon Sep 17 00:00:00 2001 From: Peter van der Zee Date: Thu, 13 Feb 2025 21:38:15 +0100 Subject: [PATCH 4/4] Drop merge conflict reappeared file, update doc --- src/commands/scan/cmd-create.ts | 2 +- src/commands/scan/create.ts | 281 -------------------------------- 2 files changed, 1 insertion(+), 282 deletions(-) delete mode 100644 src/commands/scan/create.ts diff --git a/src/commands/scan/cmd-create.ts b/src/commands/scan/cmd-create.ts index 53af6c70a..6546d7618 100644 --- a/src/commands/scan/cmd-create.ts +++ b/src/commands/scan/cmd-create.ts @@ -150,7 +150,7 @@ async function run( - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\n - Repository name using --repo ${!repoName ? colors.red('(missing!)') : colors.green('(ok)')}\n - Branch name using --branch ${!branchName ? colors.red('(missing!)') : colors.green('(ok)')}\n - - At least TARGET (e.g. \`.\` or \`./package.json\`) ${ + - At least one TARGET (e.g. \`.\` or \`./package.json\`) ${ !packagePaths.length ? colors.red( targets.length > 0 diff --git a/src/commands/scan/create.ts b/src/commands/scan/create.ts deleted file mode 100644 index f61780e8b..000000000 --- a/src/commands/scan/create.ts +++ /dev/null @@ -1,281 +0,0 @@ -import process from 'node:process' -import readline from 'node:readline/promises' - -import meow from 'meow' -import open from 'open' -import colors from 'yoctocolors-cjs' - -import { Spinner } from '@socketsecurity/registry/lib/spinner' - -import { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api' -import { AuthError } from '../../utils/errors' -import { getFlagListOutput } from '../../utils/output-formatting' -import { getPackageFilesFullScans } from '../../utils/path-resolve' -import { getDefaultToken, setupSdk } from '../../utils/sdk' - -import type { CliSubcommand } from '../../utils/meow-with-subcommands' - -export const create: CliSubcommand = { - description: 'Create a scan', - async run(argv, importMeta, { parentName }) { - const name = `${parentName} create` - const input = await setupCommand(name, create.description, argv, importMeta) - if (input) { - const apiToken = getDefaultToken() - if (!apiToken) { - throw new AuthError( - 'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.' - ) - } - const spinnerText = 'Creating a scan... \n' - const spinner = new Spinner({ text: spinnerText }).start() - await createFullScan(input, spinner, apiToken, input.cwd) - } - } -} - -const createFullScanFlags: { [key: string]: any } = { - repo: { - type: 'string', - shortFlag: 'r', - default: '', - description: 'Repository name' - }, - branch: { - type: 'string', - shortFlag: 'b', - default: '', - description: 'Branch name' - }, - commitMessage: { - type: 'string', - shortFlag: 'm', - default: '', - description: 'Commit message' - }, - commitHash: { - type: 'string', - shortFlag: 'ch', - default: '', - description: 'Commit hash' - }, - cwd: { - type: 'string', - description: 'working directory, defaults to process.cwd()' - }, - pullRequest: { - type: 'number', - shortFlag: 'pr', - description: 'Commit hash' - }, - committers: { - type: 'string', - shortFlag: 'c', - default: '', - description: 'Committers' - }, - defaultBranch: { - type: 'boolean', - shortFlag: 'db', - default: false, - description: 'Make default branch' - }, - pendingHead: { - type: 'boolean', - shortFlag: 'ph', - default: false, - description: 'Set as pending head' - }, - tmp: { - type: 'boolean', - shortFlag: 't', - default: false, - description: 'Set the visibility (true/false) of the scan in your dashboard' - } -} - -// Internal functions - -type CommandContext = { - cwd: string - orgSlug: string - repoName: string - branchName: string - committers: string - commitMessage: string - commitHash: string - pullRequest: number | undefined - defaultBranch: boolean - pendingHead: boolean - tmp: boolean - packagePaths: string[] -} - -async function setupCommand( - name: string, - description: string, - argv: readonly string[], - importMeta: ImportMeta -): Promise { - const flags: { [key: string]: any } = { - ...createFullScanFlags - } - const cli = meow( - ` - Usage - $ ${name} [...options] [TARGET ...] - - Where TARGET is a FILE or DIR that _must_ be inside the CWD. - - When a FILE is given only that FILE is targeted. Otherwise any eligible - files in the given DIR will be considered. - - Options - ${getFlagListOutput(flags, 6)} - - Examples - $ ${name} --repo=test-repo --branch=main FakeOrg ./package.json - `, - { - argv, - description, - importMeta, - flags - } - ) - - let showHelp = cli.flags['help'] - - const socketSdk = await setupSdk() - const supportedFiles = await socketSdk - .getReportSupportedFiles() - .then(res => { - if (!res.success) - handleUnsuccessfulApiResponse( - 'getReportSupportedFiles', - res, - new Spinner() - ) - return (res as any).data - }) - .catch( - /** @type {(cause: Error) => never} */ - cause => { - throw new Error('Failed getting supported files for report', { - cause - }) - } - ) - - // TODO: I think the cwd should be set to the DIR|FILE arg of this command and the DIR/FILE be either '.' or the filename() of the arg - const cwd = - cli.flags['cwd'] && cli.flags['cwd'] !== 'process.cwd()' - ? String(cli.flags['cwd']) - : process.cwd() - - const [orgSlug, ...targets] = cli.input - - const packagePaths = await getPackageFilesFullScans( - cwd, - targets, - supportedFiles - ) - - const { branch: branchName, repo: repoName } = cli.flags - if (!orgSlug || !repoName || !branchName || !packagePaths.length) { - showHelp = true - console.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n - - Org name as first arg ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\n - - Repository name using --repo ${!repoName ? colors.red('(missing!)') : colors.green('(ok)')}\n - - Branch name using --branch ${!branchName ? colors.red('(missing!)') : colors.green('(ok)')}\n - - At least TARGET (e.g. \`.\` or \`./package.json\`) ${ - !packagePaths.length - ? colors.red( - targets.length > 0 - ? '(TARGET' + - (targets.length ? 's' : '') + - ' contained no matching/supported files!)' - : '(missing)' - ) - : colors.green('(ok)') - }`) - } - if (showHelp) { - cli.showHelp() - return - } - - return { - cwd, - orgSlug, - repoName, - branchName, - commitMessage: cli.flags['commitMessage'], - defaultBranch: cli.flags['defaultBranch'], - pendingHead: cli.flags['pendingHead'], - tmp: cli.flags['tmp'], - packagePaths, - commitHash: cli.flags['commitHash'], - committers: cli.flags['committers'], - pullRequest: cli.flags['pullRequest'] - } -} - -async function createFullScan( - input: CommandContext, - spinner: Spinner, - apiToken: string, - cwd: string = process.cwd() -): Promise { - const socketSdk = await setupSdk(apiToken) - const { - branchName, - commitMessage, - defaultBranch, - orgSlug, - packagePaths, - pendingHead, - repoName, - tmp - } = input - const result = await handleApiCall( - socketSdk.createOrgFullScan( - orgSlug, - { - repo: repoName, - branch: branchName, - commit_message: commitMessage, - make_default_branch: defaultBranch, - set_as_pending_head: pendingHead, - tmp - }, - packagePaths, - cwd - ), - 'Creating scan' - ) - - if (!result.success) { - handleUnsuccessfulApiResponse('CreateOrgFullScan', result, spinner) - return - } - - spinner.success('Scan created successfully') - - const link = colors.underline(colors.cyan(`${result.data.html_report_url}`)) - console.log(`Available at: ${link}`) - - const rl = readline.createInterface({ - input: process.stdin, - output: process.stdout - }) - - const answer = await rl.question( - 'Would you like to open it in your browser? (y/n)' - ) - - if (answer.toLowerCase() === 'y') { - await open(`${result.data.html_report_url}`) - } - rl.close() -}