@aikidosec/ci-api-client 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.editorconfig +18 -18
- package/.env +1 -1
- package/.npmrc +0 -0
- package/.prettierrc +10 -10
- package/CONTRIBUTING.md +30 -30
- package/LICENSE +21 -21
- package/README.md +80 -78
- package/RELEASING.md +26 -26
- package/lib/aikidoApi.d.ts +60 -60
- package/lib/aikidoApi.js +52 -52
- package/lib/commands/apiKey.d.ts +8 -8
- package/lib/commands/apiKey.js +20 -18
- package/lib/commands/scan.d.ts +36 -36
- package/lib/commands/scan.js +191 -188
- package/lib/commands/upload.d.ts +23 -23
- package/lib/commands/upload.js +94 -94
- package/lib/configuration.d.ts +4 -4
- package/lib/configuration.js +13 -13
- package/lib/index.d.ts +12 -12
- package/lib/index.js +31 -31
- package/lib/output.d.ts +7 -7
- package/lib/output.js +53 -53
- package/package.json +48 -51
- package/src/aikidoApi.ts +148 -148
- package/src/commands/apiKey.ts +33 -30
- package/src/commands/scan.ts +373 -370
- package/src/commands/upload.ts +184 -184
- package/src/configuration.ts +21 -21
- package/src/index.ts +64 -64
- package/src/output.ts +87 -87
- package/tsconfig.json +27 -27
package/src/commands/upload.ts
CHANGED
|
@@ -1,184 +1,184 @@
|
|
|
1
|
-
import { Argument, Command, InvalidArgumentError, Option } from 'commander';
|
|
2
|
-
import {
|
|
3
|
-
TScanApiOptions,
|
|
4
|
-
TUploadApiOptions,
|
|
5
|
-
TUploadPayloadType,
|
|
6
|
-
TUploadResult,
|
|
7
|
-
pollScanStatus,
|
|
8
|
-
startScan,
|
|
9
|
-
uploadCustomScanResult,
|
|
10
|
-
} from '../aikidoApi.js';
|
|
11
|
-
import { getApiKey } from '../configuration.js';
|
|
12
|
-
import {
|
|
13
|
-
outputError,
|
|
14
|
-
outputHttpError,
|
|
15
|
-
outputLog,
|
|
16
|
-
startSpinner,
|
|
17
|
-
} from '../output.js';
|
|
18
|
-
import chalk from 'chalk';
|
|
19
|
-
import { Ora } from 'ora';
|
|
20
|
-
import { readFile } from 'fs';
|
|
21
|
-
import { promisify } from 'util';
|
|
22
|
-
|
|
23
|
-
type TUploadArguments = {
|
|
24
|
-
data: TUploadApiOptions;
|
|
25
|
-
onUploadComplete?: (startResult: TUploadResult) => void | null;
|
|
26
|
-
onUploadFail?: (error: any) => void | null;
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
type TUploadCliOptions = {
|
|
30
|
-
payloadFile?: string;
|
|
31
|
-
payload?: string;
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
type TUploadUserCliOptions = {
|
|
35
|
-
scanId?: string | number;
|
|
36
|
-
repositoryId: string | number;
|
|
37
|
-
containerImage?: string;
|
|
38
|
-
type: TUploadPayloadType;
|
|
39
|
-
file?: string;
|
|
40
|
-
payload?: string;
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
async function cli(options: TUploadUserCliOptions, command: string) {
|
|
44
|
-
const apiKey = getApiKey();
|
|
45
|
-
|
|
46
|
-
if (!apiKey) {
|
|
47
|
-
outputError('Please set an api key using: aikido-cli apikey <key>');
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Process command options and group them into apiOptions hash
|
|
51
|
-
const { apiOptions, cliOptions } = await parseCliOptions(options);
|
|
52
|
-
|
|
53
|
-
let loader: Ora | null = startSpinner('Uploading custom scan');
|
|
54
|
-
|
|
55
|
-
const onUploadComplete = (result: TUploadResult) => {
|
|
56
|
-
if (result.success === 1) {
|
|
57
|
-
loader?.succeed('Upload completed');
|
|
58
|
-
} else {
|
|
59
|
-
loader?.fail(
|
|
60
|
-
'Upload failed, please verify your payload data and try again'
|
|
61
|
-
);
|
|
62
|
-
process.exit(10);
|
|
63
|
-
}
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
const onUploadFail = (error: any) => {
|
|
67
|
-
loader?.fail();
|
|
68
|
-
outputHttpError(error);
|
|
69
|
-
|
|
70
|
-
process.exit(1);
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
await upload({
|
|
74
|
-
data: apiOptions,
|
|
75
|
-
onUploadComplete,
|
|
76
|
-
onUploadFail,
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export const upload = async ({
|
|
81
|
-
data,
|
|
82
|
-
onUploadComplete,
|
|
83
|
-
onUploadFail,
|
|
84
|
-
}: TUploadArguments): Promise<void> => {
|
|
85
|
-
try {
|
|
86
|
-
const result = await uploadCustomScanResult(data);
|
|
87
|
-
onUploadComplete?.(result);
|
|
88
|
-
} catch (error) {
|
|
89
|
-
onUploadFail?.(error);
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
type TParseCliResult = {
|
|
95
|
-
apiOptions: TUploadApiOptions;
|
|
96
|
-
cliOptions: TUploadCliOptions;
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
const parseCliOptions = async (
|
|
100
|
-
userCliOptions: TUploadUserCliOptions
|
|
101
|
-
): Promise<TParseCliResult> => {
|
|
102
|
-
const apiOptions: TUploadApiOptions = {
|
|
103
|
-
repository_id: userCliOptions.repositoryId,
|
|
104
|
-
container_image_name: userCliOptions.containerImage ?? undefined,
|
|
105
|
-
payload_type: userCliOptions.type,
|
|
106
|
-
payload: '',
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
const cliOptions: TUploadCliOptions = {
|
|
110
|
-
payloadFile: userCliOptions.file,
|
|
111
|
-
payload: userCliOptions.payload,
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
// Additional validation
|
|
115
|
-
if (userCliOptions.type == TUploadPayloadType.JsonSbom) {
|
|
116
|
-
if (
|
|
117
|
-
userCliOptions.containerImage === undefined ||
|
|
118
|
-
userCliOptions.containerImage.trim() === ''
|
|
119
|
-
) {
|
|
120
|
-
outputError(
|
|
121
|
-
'Please provide a valid container image name with --container-image'
|
|
122
|
-
);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
if (userCliOptions.file) {
|
|
127
|
-
// Read '--payloadFile' if available...
|
|
128
|
-
try {
|
|
129
|
-
const data: string = await promisify(readFile)(
|
|
130
|
-
userCliOptions.file,
|
|
131
|
-
'utf8'
|
|
132
|
-
);
|
|
133
|
-
apiOptions.payload = data;
|
|
134
|
-
} catch (error) {
|
|
135
|
-
outputError('Cannot read file provided with --payloadFile, aborting');
|
|
136
|
-
process.exit(1);
|
|
137
|
-
}
|
|
138
|
-
} else if (cliOptions.payload?.trim() != '') {
|
|
139
|
-
// ... no payloadFile provided, use the --payload information
|
|
140
|
-
apiOptions.payload = cliOptions.payload!;
|
|
141
|
-
} else {
|
|
142
|
-
// No payload available? Abort
|
|
143
|
-
outputError('No payload provided, aborting');
|
|
144
|
-
process.exit(1);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
return { apiOptions, cliOptions };
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
// Make an option required
|
|
151
|
-
const requiredOption = (option: Option): Option => {
|
|
152
|
-
option.required = true;
|
|
153
|
-
return option;
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
export const cliSetup = (program: Command) =>
|
|
157
|
-
program
|
|
158
|
-
.command('upload')
|
|
159
|
-
.option('-s, --scan-id <scanid>', 'Set the scan id')
|
|
160
|
-
.requiredOption(
|
|
161
|
-
'-r, --repository-id <repositoryid>',
|
|
162
|
-
'Set the repository id'
|
|
163
|
-
)
|
|
164
|
-
.option(
|
|
165
|
-
'-i, --container-image <container-image-name>',
|
|
166
|
-
'Set the container image name. '
|
|
167
|
-
)
|
|
168
|
-
.addOption(
|
|
169
|
-
requiredOption(
|
|
170
|
-
new Option(
|
|
171
|
-
'-t, --type <type>',
|
|
172
|
-
'Set the provided payload type. Available options are: checkov, json-sbom'
|
|
173
|
-
).choices(['checkov', 'json-sbom'])
|
|
174
|
-
)
|
|
175
|
-
)
|
|
176
|
-
.option(
|
|
177
|
-
'-f, --file <payloadFile>',
|
|
178
|
-
'Specify the payload file. The cli command wil read the file and use the contents as payload data.'
|
|
179
|
-
)
|
|
180
|
-
.option('-p, --payload <payload>', 'Set the payload')
|
|
181
|
-
.description('Upload a custom scan result.')
|
|
182
|
-
.action(cli);
|
|
183
|
-
|
|
184
|
-
export default { cli, cliSetup };
|
|
1
|
+
import { Argument, Command, InvalidArgumentError, Option } from 'commander';
|
|
2
|
+
import {
|
|
3
|
+
TScanApiOptions,
|
|
4
|
+
TUploadApiOptions,
|
|
5
|
+
TUploadPayloadType,
|
|
6
|
+
TUploadResult,
|
|
7
|
+
pollScanStatus,
|
|
8
|
+
startScan,
|
|
9
|
+
uploadCustomScanResult,
|
|
10
|
+
} from '../aikidoApi.js';
|
|
11
|
+
import { getApiKey } from '../configuration.js';
|
|
12
|
+
import {
|
|
13
|
+
outputError,
|
|
14
|
+
outputHttpError,
|
|
15
|
+
outputLog,
|
|
16
|
+
startSpinner,
|
|
17
|
+
} from '../output.js';
|
|
18
|
+
import chalk from 'chalk';
|
|
19
|
+
import { Ora } from 'ora';
|
|
20
|
+
import { readFile } from 'fs';
|
|
21
|
+
import { promisify } from 'util';
|
|
22
|
+
|
|
23
|
+
type TUploadArguments = {
|
|
24
|
+
data: TUploadApiOptions;
|
|
25
|
+
onUploadComplete?: (startResult: TUploadResult) => void | null;
|
|
26
|
+
onUploadFail?: (error: any) => void | null;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
type TUploadCliOptions = {
|
|
30
|
+
payloadFile?: string;
|
|
31
|
+
payload?: string;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
type TUploadUserCliOptions = {
|
|
35
|
+
scanId?: string | number;
|
|
36
|
+
repositoryId: string | number;
|
|
37
|
+
containerImage?: string;
|
|
38
|
+
type: TUploadPayloadType;
|
|
39
|
+
file?: string;
|
|
40
|
+
payload?: string;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
async function cli(options: TUploadUserCliOptions, command: string) {
|
|
44
|
+
const apiKey = getApiKey();
|
|
45
|
+
|
|
46
|
+
if (!apiKey) {
|
|
47
|
+
outputError('Please set an api key using: aikido-cli apikey <key>');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Process command options and group them into apiOptions hash
|
|
51
|
+
const { apiOptions, cliOptions } = await parseCliOptions(options);
|
|
52
|
+
|
|
53
|
+
let loader: Ora | null = startSpinner('Uploading custom scan');
|
|
54
|
+
|
|
55
|
+
const onUploadComplete = (result: TUploadResult) => {
|
|
56
|
+
if (result.success === 1) {
|
|
57
|
+
loader?.succeed('Upload completed');
|
|
58
|
+
} else {
|
|
59
|
+
loader?.fail(
|
|
60
|
+
'Upload failed, please verify your payload data and try again'
|
|
61
|
+
);
|
|
62
|
+
process.exit(10);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const onUploadFail = (error: any) => {
|
|
67
|
+
loader?.fail();
|
|
68
|
+
outputHttpError(error);
|
|
69
|
+
|
|
70
|
+
process.exit(1);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
await upload({
|
|
74
|
+
data: apiOptions,
|
|
75
|
+
onUploadComplete,
|
|
76
|
+
onUploadFail,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export const upload = async ({
|
|
81
|
+
data,
|
|
82
|
+
onUploadComplete,
|
|
83
|
+
onUploadFail,
|
|
84
|
+
}: TUploadArguments): Promise<void> => {
|
|
85
|
+
try {
|
|
86
|
+
const result = await uploadCustomScanResult(data);
|
|
87
|
+
onUploadComplete?.(result);
|
|
88
|
+
} catch (error) {
|
|
89
|
+
onUploadFail?.(error);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
type TParseCliResult = {
|
|
95
|
+
apiOptions: TUploadApiOptions;
|
|
96
|
+
cliOptions: TUploadCliOptions;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const parseCliOptions = async (
|
|
100
|
+
userCliOptions: TUploadUserCliOptions
|
|
101
|
+
): Promise<TParseCliResult> => {
|
|
102
|
+
const apiOptions: TUploadApiOptions = {
|
|
103
|
+
repository_id: userCliOptions.repositoryId,
|
|
104
|
+
container_image_name: userCliOptions.containerImage ?? undefined,
|
|
105
|
+
payload_type: userCliOptions.type,
|
|
106
|
+
payload: '',
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const cliOptions: TUploadCliOptions = {
|
|
110
|
+
payloadFile: userCliOptions.file,
|
|
111
|
+
payload: userCliOptions.payload,
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
// Additional validation
|
|
115
|
+
if (userCliOptions.type == TUploadPayloadType.JsonSbom) {
|
|
116
|
+
if (
|
|
117
|
+
userCliOptions.containerImage === undefined ||
|
|
118
|
+
userCliOptions.containerImage.trim() === ''
|
|
119
|
+
) {
|
|
120
|
+
outputError(
|
|
121
|
+
'Please provide a valid container image name with --container-image'
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (userCliOptions.file) {
|
|
127
|
+
// Read '--payloadFile' if available...
|
|
128
|
+
try {
|
|
129
|
+
const data: string = await promisify(readFile)(
|
|
130
|
+
userCliOptions.file,
|
|
131
|
+
'utf8'
|
|
132
|
+
);
|
|
133
|
+
apiOptions.payload = data;
|
|
134
|
+
} catch (error) {
|
|
135
|
+
outputError('Cannot read file provided with --payloadFile, aborting');
|
|
136
|
+
process.exit(1);
|
|
137
|
+
}
|
|
138
|
+
} else if (cliOptions.payload?.trim() != '') {
|
|
139
|
+
// ... no payloadFile provided, use the --payload information
|
|
140
|
+
apiOptions.payload = cliOptions.payload!;
|
|
141
|
+
} else {
|
|
142
|
+
// No payload available? Abort
|
|
143
|
+
outputError('No payload provided, aborting');
|
|
144
|
+
process.exit(1);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return { apiOptions, cliOptions };
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
// Make an option required
|
|
151
|
+
const requiredOption = (option: Option): Option => {
|
|
152
|
+
option.required = true;
|
|
153
|
+
return option;
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
export const cliSetup = (program: Command) =>
|
|
157
|
+
program
|
|
158
|
+
.command('upload')
|
|
159
|
+
.option('-s, --scan-id <scanid>', 'Set the scan id')
|
|
160
|
+
.requiredOption(
|
|
161
|
+
'-r, --repository-id <repositoryid>',
|
|
162
|
+
'Set the repository id'
|
|
163
|
+
)
|
|
164
|
+
.option(
|
|
165
|
+
'-i, --container-image <container-image-name>',
|
|
166
|
+
'Set the container image name. '
|
|
167
|
+
)
|
|
168
|
+
.addOption(
|
|
169
|
+
requiredOption(
|
|
170
|
+
new Option(
|
|
171
|
+
'-t, --type <type>',
|
|
172
|
+
'Set the provided payload type. Available options are: checkov, json-sbom'
|
|
173
|
+
).choices(['checkov', 'json-sbom'])
|
|
174
|
+
)
|
|
175
|
+
)
|
|
176
|
+
.option(
|
|
177
|
+
'-f, --file <payloadFile>',
|
|
178
|
+
'Specify the payload file. The cli command wil read the file and use the contents as payload data.'
|
|
179
|
+
)
|
|
180
|
+
.option('-p, --payload <payload>', 'Set the payload')
|
|
181
|
+
.description('Upload a custom scan result.')
|
|
182
|
+
.action(cli);
|
|
183
|
+
|
|
184
|
+
export default { cli, cliSetup };
|
package/src/configuration.ts
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import Configstore from 'configstore';
|
|
2
|
-
import { program } from './index.js';
|
|
3
|
-
|
|
4
|
-
// Load a new ConfigSture by using the commander program name, which is
|
|
5
|
-
// set in the main index.js file
|
|
6
|
-
export const getConfigStore = () => {
|
|
7
|
-
return new Configstore(program.name());
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
// Get the apikey set through the cli option or the
|
|
11
|
-
// one stored in the configuration
|
|
12
|
-
export const getApiKey = () => {
|
|
13
|
-
return program.getOptionValue('apikey')
|
|
14
|
-
? program.getOptionValue('apikey')
|
|
15
|
-
: getConfigStore().get('apikey');
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
// Set the global apiKey
|
|
19
|
-
export const setApiKey = (newApiKey: string) => {
|
|
20
|
-
return getConfigStore().set('apikey', newApiKey);
|
|
21
|
-
};
|
|
1
|
+
import Configstore from 'configstore';
|
|
2
|
+
import { program } from './index.js';
|
|
3
|
+
|
|
4
|
+
// Load a new ConfigSture by using the commander program name, which is
|
|
5
|
+
// set in the main index.js file
|
|
6
|
+
export const getConfigStore = () => {
|
|
7
|
+
return new Configstore(program.name());
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
// Get the apikey set through the cli option or the
|
|
11
|
+
// one stored in the configuration
|
|
12
|
+
export const getApiKey = () => {
|
|
13
|
+
return program.getOptionValue('apikey')
|
|
14
|
+
? program.getOptionValue('apikey')
|
|
15
|
+
: getConfigStore().get('apikey');
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
// Set the global apiKey
|
|
19
|
+
export const setApiKey = (newApiKey: string) => {
|
|
20
|
+
return getConfigStore().set('apikey', newApiKey);
|
|
21
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -1,64 +1,64 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import chalk from 'chalk';
|
|
3
|
-
import { Command } from 'commander';
|
|
4
|
-
import dotenv from 'dotenv';
|
|
5
|
-
import apiKey from './commands/apiKey.js';
|
|
6
|
-
import scan from './commands/scan.js';
|
|
7
|
-
import upload from './commands/upload.js';
|
|
8
|
-
|
|
9
|
-
// Load all .env configuration variables and auto-inject them into process.env
|
|
10
|
-
dotenv.config(
|
|
11
|
-
process.env.NODE_ENV ? { path: `.env.${process.env.NODE_ENV}` } : {}
|
|
12
|
-
);
|
|
13
|
-
|
|
14
|
-
// Start up commander.js Command instance
|
|
15
|
-
export const program = new Command();
|
|
16
|
-
|
|
17
|
-
program
|
|
18
|
-
.name('Aikido API Client')
|
|
19
|
-
.description(
|
|
20
|
-
'CLI api client to easily integrate the Aikido public CI API into custom deploy scripts'
|
|
21
|
-
)
|
|
22
|
-
.version('1.0.
|
|
23
|
-
|
|
24
|
-
// Load in all app commands and set them up in the `program` instance
|
|
25
|
-
apiKey.cliSetup(program);
|
|
26
|
-
scan.cliSetup(program);
|
|
27
|
-
upload.cliSetup(program);
|
|
28
|
-
|
|
29
|
-
// Override global process.env type
|
|
30
|
-
declare global {
|
|
31
|
-
namespace NodeJS {
|
|
32
|
-
interface ProcessEnv {
|
|
33
|
-
[key: string]: any; // used any here
|
|
34
|
-
QUIET?: boolean;
|
|
35
|
-
CLI_DEBUG?: boolean | string;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Add global option "--quiet"
|
|
41
|
-
program
|
|
42
|
-
.option('-q, --quiet', 'Disable console output when executing commands')
|
|
43
|
-
.on('option:quiet', function () {
|
|
44
|
-
process.env.QUIET = true;
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
// Add global option "--debug"
|
|
48
|
-
program
|
|
49
|
-
.option('--debug', 'Add additional debug information to command output')
|
|
50
|
-
.on('option:debug', function () {
|
|
51
|
-
process.env.CLI_DEBUG = true;
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
// Add global option "--apikey"
|
|
55
|
-
program.option(
|
|
56
|
-
'--apikey <apikey>',
|
|
57
|
-
'Use a cli apikey instead of reading the key from the configuration'
|
|
58
|
-
);
|
|
59
|
-
|
|
60
|
-
program.configureOutput({
|
|
61
|
-
outputError: (str, write) => write(chalk.red(str)),
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
program.parse();
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import dotenv from 'dotenv';
|
|
5
|
+
import apiKey from './commands/apiKey.js';
|
|
6
|
+
import scan from './commands/scan.js';
|
|
7
|
+
import upload from './commands/upload.js';
|
|
8
|
+
|
|
9
|
+
// Load all .env configuration variables and auto-inject them into process.env
|
|
10
|
+
dotenv.config(
|
|
11
|
+
process.env.NODE_ENV ? { path: `.env.${process.env.NODE_ENV}` } : {}
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
// Start up commander.js Command instance
|
|
15
|
+
export const program = new Command();
|
|
16
|
+
|
|
17
|
+
program
|
|
18
|
+
.name('Aikido API Client')
|
|
19
|
+
.description(
|
|
20
|
+
'CLI api client to easily integrate the Aikido public CI API into custom deploy scripts'
|
|
21
|
+
)
|
|
22
|
+
.version('1.0.3');
|
|
23
|
+
|
|
24
|
+
// Load in all app commands and set them up in the `program` instance
|
|
25
|
+
apiKey.cliSetup(program);
|
|
26
|
+
scan.cliSetup(program);
|
|
27
|
+
upload.cliSetup(program);
|
|
28
|
+
|
|
29
|
+
// Override global process.env type
|
|
30
|
+
declare global {
|
|
31
|
+
namespace NodeJS {
|
|
32
|
+
interface ProcessEnv {
|
|
33
|
+
[key: string]: any; // used any here
|
|
34
|
+
QUIET?: boolean;
|
|
35
|
+
CLI_DEBUG?: boolean | string;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Add global option "--quiet"
|
|
41
|
+
program
|
|
42
|
+
.option('-q, --quiet', 'Disable console output when executing commands')
|
|
43
|
+
.on('option:quiet', function () {
|
|
44
|
+
process.env.QUIET = true;
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// Add global option "--debug"
|
|
48
|
+
program
|
|
49
|
+
.option('--debug', 'Add additional debug information to command output')
|
|
50
|
+
.on('option:debug', function () {
|
|
51
|
+
process.env.CLI_DEBUG = true;
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// Add global option "--apikey"
|
|
55
|
+
program.option(
|
|
56
|
+
'--apikey <apikey>',
|
|
57
|
+
'Use a cli apikey instead of reading the key from the configuration'
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
program.configureOutput({
|
|
61
|
+
outputError: (str, write) => write(chalk.red(str)),
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
program.parse();
|