Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions src/commands/scan/cmd-scan-create.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,21 +40,30 @@ describe('socket scan create', async () => {
When a FILE is given only that FILE is targeted. Otherwise any eligible
files in the given DIR will be considered.

Note: for a first run you probably want to set --defaultBranch to indicate
the default branch name, like "main" or "master".

Note: --pendingHead is enabled by default and makes a scan show up in your
dashboard. You can use \`--no-pendingHead\` to have it not show up.

Options
--branch Branch name
--commitHash Commit hash
--commitMessage Commit message
--committers Committers
--cwd working directory, defaults to process.cwd()
--defaultBranch Make default branch
--defaultBranch Set the default branch of the repository to the branch of this full-scan. Should only need to be done once, for example for the "main" or "master" branch.
--dryRun run input validation part of command without any concrete side effects
--help Print this help
--pendingHead Set as pending head
--json Output result as json
--markdown Output result as markdown
--pendingHead Designate this full-scan as the latest scan of a given branch. This must be set to have it show up in the dashboard.
--pullRequest Commit hash
--readOnly Similar to --dry-run except it can read from remote, stops before it would create an actual report
--repo Repository name
--report Wait for the scan creation to complete, then basically run \`socket scan report\` on it
--tmp Set the visibility (true/false) of the scan in your dashboard
--view Will wait for and return the created report. Use --no-view to disable.
--view Will wait for and return the created scan details. Use --no-view to disable.

Examples
$ socket scan create --repo=test-repo --branch=main FakeOrg ./package.json"
Expand Down
119 changes: 62 additions & 57 deletions src/commands/scan/cmd-scan-create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@ import { logger } from '@socketsecurity/registry/lib/logger'

import { handleCreateNewScan } from './handle-create-new-scan'
import { suggestOrgSlug } from './suggest-org-slug'
import { suggestRepoSlug } from './suggest-repo-slug'
import { suggestBranchSlug } from './suggest_branch_slug'
import { suggestTarget } from './suggest_target'
import constants from '../../constants'
import { commonFlags } from '../../flags'
import { commonFlags, outputFlags } from '../../flags'
import { getConfigValue } from '../../utils/config'
import { handleBadInput } from '../../utils/handle-bad-input'
import { meowOrExit } from '../../utils/meow-with-subcommands'
Expand All @@ -23,16 +21,17 @@ const config: CliCommandConfig = {
hidden: false,
flags: {
...commonFlags,
...outputFlags,
repo: {
type: 'string',
shortFlag: 'r',
default: '',
default: 'socket-default-repository',
description: 'Repository name'
},
branch: {
type: 'string',
shortFlag: 'b',
default: '',
default: 'socket-default-branch',
description: 'Branch name'
},
commitMessage: {
Expand All @@ -51,6 +50,18 @@ const config: CliCommandConfig = {
type: 'string',
description: 'working directory, defaults to process.cwd()'
},
defaultBranch: {
type: 'boolean',
default: false,
description:
'Set the default branch of the repository to the branch of this full-scan. Should only need to be done once, for example for the "main" or "master" branch.'
},
pendingHead: {
type: 'boolean',
default: true,
description:
'Designate this full-scan as the latest scan of a given branch. This must be set to have it show up in the dashboard.'
},
dryRun: {
type: 'boolean',
description:
Expand All @@ -67,23 +78,17 @@ const config: CliCommandConfig = {
default: '',
description: 'Committers'
},
defaultBranch: {
type: 'boolean',
shortFlag: 'db',
default: false,
description: 'Make default branch'
},
pendingHead: {
readOnly: {
type: 'boolean',
shortFlag: 'ph',
default: false,
description: 'Set as pending head'
description:
'Similar to --dry-run except it can read from remote, stops before it would create an actual report'
},
readOnly: {
report: {
type: 'boolean',
default: false,
description:
'Similar to --dry-run except it can read from remote, stops before it would create an actual report'
'Wait for the scan creation to complete, then basically run `socket scan report` on it'
},
tmp: {
type: 'boolean',
Expand All @@ -97,7 +102,7 @@ const config: CliCommandConfig = {
shortFlag: 'v',
default: true,
description:
'Will wait for and return the created report. Use --no-view to disable.'
'Will wait for and return the created scan details. Use --no-view to disable.'
}
},
// TODO: your project's "socket.yml" file's "projectIgnorePaths"
Expand All @@ -123,6 +128,12 @@ const config: CliCommandConfig = {
When a FILE is given only that FILE is targeted. Otherwise any eligible
files in the given DIR will be considered.

Note: for a first run you probably want to set --defaultBranch to indicate
the default branch name, like "main" or "master".

Note: --pendingHead is enabled by default and makes a scan show up in your
dashboard. You can use \`--no-pendingHead\` to have it not show up.

Options
${getFlagListOutput(config.flags, 6)}

Expand All @@ -149,9 +160,26 @@ async function run(
parentName
})

const { cwd: cwdOverride, dryRun } = cli.flags as {
const {
cwd: cwdOverride,
defaultBranch,
dryRun,
json,
markdown,
pendingHead,
readOnly,
report,
tmp
} = cli.flags as {
cwd: string
dryRun: boolean
report: boolean
json: boolean
markdown: boolean
defaultBranch: boolean
pendingHead: boolean
readOnly: boolean
tmp: boolean
}
const defaultOrgSlug = getConfigValue('defaultOrg')
let orgSlug = defaultOrgSlug || cli.input[0] || ''
Expand All @@ -161,7 +189,7 @@ async function run(
cwdOverride && cwdOverride !== 'process.cwd()'
? String(cwdOverride)
: process.cwd()
let { branch: branchName = '', repo: repoName = '' } = cli.flags as {
const { branch: branchName = '', repo: repoName = '' } = cli.flags as {
branch: string
repo: string
}
Expand All @@ -183,7 +211,6 @@ async function run(

// If the current cwd is unknown and is used as a repo slug anyways, we will
// first need to register the slug before we can use it.
let repoDefaultBranch = ''
// Only do suggestions with an apiToken and when not in dryRun mode
if (apiToken && !dryRun) {
if (!orgSlug) {
Expand All @@ -193,34 +220,15 @@ async function run(
}
updatedInput = true
}

// (Don't bother asking for the rest if we didn't get an org slug above)
if (orgSlug && !repoName) {
const suggestion = await suggestRepoSlug(orgSlug)
if (suggestion) {
repoDefaultBranch = suggestion.defaultBranch
repoName = suggestion.slug
}
updatedInput = true
}

// (Don't bother asking for the rest if we didn't get an org/repo above)
if (orgSlug && repoName && !branchName) {
const suggestion = await suggestBranchSlug(repoDefaultBranch)
if (suggestion) {
branchName = suggestion
}
updatedInput = true
}
}

if (updatedInput && repoName && branchName && orgSlug && targets?.length) {
if (updatedInput && orgSlug && targets?.length) {
logger.error(
'Note: You can invoke this command next time to skip the interactive questions:'
)
logger.error('```')
logger.error(
` socket scan create [other flags...] --repo ${repoName} --branch ${branchName} ${orgSlug} ${targets.join(' ')}`
` socket scan create [other flags...] ${defaultOrgSlug ? '' : orgSlug} ${targets.join(' ')}`
)
logger.error('```\n')
}
Expand All @@ -233,24 +241,19 @@ async function run(
pass: 'ok',
fail: 'missing'
},
{
test: repoName,
message: 'Repository name using --repo',
pass: 'ok',
fail: typeof repoName !== 'string' ? 'missing' : 'invalid'
},
{
test: branchName,
message: 'Repository name using --branch',
pass: 'ok',
fail: typeof repoName !== 'string' ? 'missing' : 'invalid'
},
{
test: targets.length,
message: 'At least one TARGET (e.g. `.` or `./package.json`)',
pass: 'ok',
fail: 'missing'
},
{
nook: true,
test: !json || !markdown,
message: 'The json and markdown flags cannot be both set, pick one',
pass: 'ok',
fail: 'omit one'
},
{
nook: true,
test: apiToken,
Expand All @@ -273,12 +276,14 @@ async function run(
branchName: branchName as string,
commitMessage: (cli.flags['commitMessage'] as string | undefined) ?? '',
cwd,
defaultBranch: Boolean(cli.flags['defaultBranch']),
defaultBranch: Boolean(defaultBranch),
orgSlug,
pendingHead: Boolean(cli.flags['pendingHead']),
readOnly: Boolean(cli.flags['readOnly']),
outputKind: json ? 'json' : markdown ? 'markdown' : 'text',
pendingHead: Boolean(pendingHead),
readOnly: Boolean(readOnly),
repoName: repoName,
report,
targets,
tmp: Boolean(cli.flags['tmp'])
tmp: Boolean(tmp)
})
}
25 changes: 24 additions & 1 deletion src/commands/scan/handle-create-new-scan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { logger } from '@socketsecurity/registry/lib/logger'

import { fetchCreateOrgFullScan } from './fetch-create-org-full-scan'
import { fetchSupportedScanFileNames } from './fetch-supported-scan-file-names'
import { handleScanReport } from './handle-scan-report'
import { outputCreateNewScan } from './output-create-new-scan'
import { handleBadInput } from '../../utils/handle-bad-input'
import { getPackageFilesForScan } from '../../utils/path-resolve'
Expand All @@ -12,9 +13,11 @@ export async function handleCreateNewScan({
cwd,
defaultBranch,
orgSlug,
outputKind,
pendingHead,
readOnly,
repoName,
report,
targets,
tmp
}: {
Expand All @@ -24,8 +27,10 @@ export async function handleCreateNewScan({
defaultBranch: boolean
orgSlug: string
pendingHead: boolean
outputKind: 'json' | 'markdown' | 'text'
readOnly: boolean
repoName: string
report: boolean
targets: string[]
tmp: boolean
}): Promise<void> {
Expand Down Expand Up @@ -68,5 +73,23 @@ export async function handleCreateNewScan({
return
}

await outputCreateNewScan(data)
if (report) {
if (data?.id) {
await handleScanReport({
filePath: '-',
fold: 'version',
includeLicensePolicy: true,
orgSlug,
outputKind,
reportLevel: 'error',
scanId: data.id,
short: false
})
} else {
logger.fail('Failure: Server did not respond with a scan ID')
process.exitCode = 1
}
} else {
await outputCreateNewScan(data, outputKind)
}
}
36 changes: 35 additions & 1 deletion src/commands/scan/output-create-new-scan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,42 @@ import { confirm } from '@socketsecurity/registry/lib/prompts'
import type { SocketSdkReturnType } from '@socketsecurity/sdk'

export async function outputCreateNewScan(
data: SocketSdkReturnType<'CreateOrgFullScan'>['data']
data: SocketSdkReturnType<'CreateOrgFullScan'>['data'],
outputKind: 'json' | 'markdown' | 'text'
) {
if (!data.id) {
logger.fail('Did not receive a scan ID from the API...')
process.exitCode = 1
}

if (outputKind === 'json') {
const json = data.id
? { success: true, data }
: { success: false, message: 'No scan ID received' }

logger.log(JSON.stringify(json, null, 2))
logger.log('')

return
}

if (outputKind === 'markdown') {
logger.log('# Create New Scan')
logger.log('')
if (data.id) {
logger.log(
`A [new Scan](${data.html_report_url}) was created with ID: ${data.id}`
)
logger.log('')
} else {
logger.log(
`The server did not return a Scan ID while trying to create a new Scan. This could be an indication something went wrong.`
)
}
logger.log('')
return
}

const link = colors.underline(colors.cyan(`${data.html_report_url}`))
logger.log(`Available at: ${link}`)

Expand Down