-
Notifications
You must be signed in to change notification settings - Fork 41
Expand file tree
/
Copy pathcmd-scan-create.ts
More file actions
289 lines (263 loc) · 7.93 KB
/
cmd-scan-create.ts
File metadata and controls
289 lines (263 loc) · 7.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
import { logger } from '@socketsecurity/registry/lib/logger'
import { handleCreateNewScan } from './handle-create-new-scan'
import { suggestOrgSlug } from './suggest-org-slug'
import { suggestTarget } from './suggest_target'
import constants from '../../constants'
import { commonFlags, outputFlags } from '../../flags'
import { getConfigValue } from '../../utils/config'
import { handleBadInput } from '../../utils/handle-bad-input'
import { meowOrExit } from '../../utils/meow-with-subcommands'
import { getFlagListOutput } from '../../utils/output-formatting'
import { getDefaultToken } from '../../utils/sdk'
import type { CliCommandConfig } from '../../utils/meow-with-subcommands'
const { DRY_RUN_BAIL_TEXT } = constants
const config: CliCommandConfig = {
commandName: 'create',
description: 'Create a scan',
hidden: false,
flags: {
...commonFlags,
...outputFlags,
repo: {
type: 'string',
shortFlag: 'r',
default: 'socket-default-repository',
description: 'Repository name'
},
branch: {
type: 'string',
shortFlag: 'b',
default: 'socket-default-branch',
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()'
},
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:
'run input validation part of command without any concrete side effects'
},
pullRequest: {
type: 'number',
shortFlag: 'pr',
description: 'Commit hash'
},
committers: {
type: 'string',
shortFlag: 'c',
default: '',
description: 'Committers'
},
readOnly: {
type: 'boolean',
default: false,
description:
'Similar to --dry-run except it can read from remote, stops before it would create an actual report'
},
report: {
type: 'boolean',
default: false,
description:
'Wait for the scan creation to complete, then basically run `socket scan report` on it'
},
tmp: {
type: 'boolean',
shortFlag: 't',
default: false,
description:
'Set the visibility (true/false) of the scan in your dashboard'
},
view: {
type: 'boolean',
shortFlag: 'v',
default: true,
description:
'Will wait for and return the created scan details. Use --no-view to disable.'
}
},
// TODO: your project's "socket.yml" file's "projectIgnorePaths"
help: (command, config) => `
Usage
$ ${command} [...options] <org> <TARGET> [TARGET...]
API Token Requirements
- Quota: 1 unit
- Permissions: full-scans:create
Uploads the specified "package.json" and lock files for JavaScript, Python,
Go, Scala, Gradle, and Kotlin dependency manifests.
If any folder is specified, the ones found in there recursively are uploaded.
Supports globbing such as "**/package.json", "**/requirements.txt", etc.
Ignores any file specified in your project's ".gitignore" and also has a
sensible set of default ignores from the "ignore-by-default" module.
TARGET should be 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.
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)}
Examples
$ ${command} --repo=test-repo --branch=main FakeOrg ./package.json
`
}
export const cmdScanCreate = {
description: config.description,
hidden: config.hidden,
run
}
async function run(
argv: string[] | readonly string[],
importMeta: ImportMeta,
{ parentName }: { parentName: string }
): Promise<void> {
const cli = meowOrExit({
argv,
config,
importMeta,
parentName
})
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] || ''
let targets = cli.input.slice(defaultOrgSlug ? 0 : 1)
const cwd =
cwdOverride && cwdOverride !== 'process.cwd()'
? String(cwdOverride)
: process.cwd()
const { branch: branchName = '', repo: repoName = '' } = cli.flags as {
branch: string
repo: string
}
// We're going to need an api token to suggest data because those suggestions
// must come from data we already know. Don't error on missing api token yet.
// If the api-token is not set, ignore it for the sake of suggestions.
const apiToken = getDefaultToken()
// If we updated any inputs then we should print the command line to repeat
// the command without requiring user input, as a suggestion.
let updatedInput = false
if (!targets.length && !dryRun) {
const received = await suggestTarget()
targets = received ?? []
updatedInput = true
}
// 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.
// Only do suggestions with an apiToken and when not in dryRun mode
if (apiToken && !dryRun) {
if (!orgSlug) {
const suggestion = await suggestOrgSlug()
if (suggestion) {
orgSlug = suggestion
}
updatedInput = true
}
}
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...] ${defaultOrgSlug ? '' : orgSlug} ${targets.join(' ')}`
)
logger.error('```\n')
}
const wasBadInput = handleBadInput(
{
nook: true,
test: orgSlug,
message: 'Org name as the first argument',
pass: 'ok',
fail: 'missing'
},
{
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,
message: 'This command requires an API token for access`)',
pass: 'ok',
fail: 'missing'
}
)
if (wasBadInput) {
return
}
// Note exiting earlier to skirt a hidden auth requirement
if (dryRun) {
logger.log(DRY_RUN_BAIL_TEXT)
return
}
await handleCreateNewScan({
branchName: branchName as string,
commitMessage: (cli.flags['commitMessage'] as string | undefined) ?? '',
cwd,
defaultBranch: Boolean(defaultBranch),
orgSlug,
outputKind: json ? 'json' : markdown ? 'markdown' : 'text',
pendingHead: Boolean(pendingHead),
readOnly: Boolean(readOnly),
repoName: repoName,
report,
targets,
tmp: Boolean(tmp)
})
}