in packages/@aws-cdk/integ-runner/lib/cli.ts [18:99]
export function parseCliArgs(args: string[] = []) {
const argv = yargs
.usage('Usage: integ-runner [TEST...]')
.option('config', {
config: true,
configParser: configFromFile,
default: 'integ.config.json',
desc: 'Load options from a JSON config file. Options provided as CLI arguments take precedent.',
})
.option('watch', { type: 'boolean', default: false, desc: 'Perform integ tests in watch mode' })
.option('list', { type: 'boolean', default: false, desc: 'List tests instead of running them' })
.option('clean', { type: 'boolean', default: true, desc: 'Skips stack clean up after test is completed (use --no-clean to negate)' })
.option('verbose', { type: 'boolean', default: false, alias: 'v', count: true, desc: 'Verbose logs and metrics on integration tests durations (specify multiple times to increase verbosity)' })
.option('dry-run', { type: 'boolean', default: false, desc: 'do not actually deploy the stack. just update the snapshot (not recommended!)' })
.option('update-on-failed', { type: 'boolean', default: false, desc: 'rerun integration tests and update snapshots for failed tests.' })
.option('force', { type: 'boolean', default: false, desc: 'Rerun all integration tests even if tests are passing' })
.option('parallel-regions', { type: 'array', desc: 'Tests are run in parallel across these regions. To prevent tests from running in parallel, provide only a single region', default: [] })
.options('directory', { type: 'string', default: 'test', desc: 'starting directory to discover integration tests. Tests will be discovered recursively from this directory' })
.options('profiles', { type: 'array', desc: 'list of AWS profiles to use. Tests will be run in parallel across each profile+regions', default: [] })
.options('max-workers', { type: 'number', desc: 'The max number of workerpool workers to use when running integration tests in parallel', default: 16 })
.options('exclude', { type: 'boolean', desc: 'Run all tests in the directory, except the specified TESTs', default: false })
.options('from-file', { type: 'string', desc: 'Read TEST names from a file (one TEST per line)' })
.option('inspect-failures', { type: 'boolean', desc: 'Keep the integ test cloud assembly if a failure occurs for inspection', default: false })
.option('disable-update-workflow', { type: 'boolean', default: false, desc: 'If this is "true" then the stack update workflow will be disabled' })
.option('language', {
alias: 'l',
default: ['javascript', 'typescript', 'python', 'go'],
choices: ['javascript', 'typescript', 'python', 'go'],
type: 'array',
nargs: 1,
desc: 'Use these presets to run integration tests for the selected languages',
})
.option('app', { type: 'string', default: undefined, desc: 'The custom CLI command that will be used to run the test files. You can include {filePath} to specify where in the command the test file path should be inserted. Example: --app="python3.8 {filePath}".' })
.option('test-regex', { type: 'array', desc: 'Detect integration test files matching this JavaScript regex pattern. If used multiple times, all files matching any one of the patterns are detected.', default: [] })
.strict()
.parse(args);
const tests: string[] = argv._;
const parallelRegions = arrayFromYargs(argv['parallel-regions']);
const testRegions: string[] = parallelRegions ?? ['us-east-1', 'us-east-2', 'us-west-2'];
const profiles = arrayFromYargs(argv.profiles);
const fromFile: string | undefined = argv['from-file'];
const maxWorkers: number = argv['max-workers'];
const verbosity: number = argv.verbose;
const verbose: boolean = verbosity >= 1;
const numTests = testRegions.length * (profiles ?? [1]).length;
if (maxWorkers < numTests) {
logger.warning('You are attempting to run %s tests in parallel, but only have %s workers. Not all of your profiles+regions will be utilized', numTests, maxWorkers);
}
if (tests.length > 0 && fromFile) {
throw new Error('A list of tests cannot be provided if "--from-file" is provided');
}
const requestedTests = fromFile
? (fs.readFileSync(fromFile, { encoding: 'utf8' })).split('\n').filter(x => x)
: (tests.length > 0 ? tests : undefined); // 'undefined' means no request
return {
tests: requestedTests,
app: argv.app as (string | undefined),
testRegex: arrayFromYargs(argv['test-regex']),
testRegions,
originalRegions: parallelRegions,
profiles,
runUpdateOnFailed: (argv['update-on-failed'] ?? false) as boolean,
fromFile,
exclude: argv.exclude as boolean,
maxWorkers,
list: argv.list as boolean,
directory: argv.directory as string,
inspectFailures: argv['inspect-failures'] as boolean,
verbosity,
verbose,
clean: argv.clean as boolean,
force: argv.force as boolean,
dryRun: argv['dry-run'] as boolean,
disableUpdateWorkflow: argv['disable-update-workflow'] as boolean,
language: arrayFromYargs(argv.language),
watch: argv.watch as boolean,
};
}