Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(cli): function to turn yargs output to cliArguments #32696

Merged
merged 14 commits into from
Jan 2, 2025
Merged
4 changes: 3 additions & 1 deletion codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,7 @@ component_management:

# https://docs.codecov.com/docs/ignoring-paths
ignore:
- packages/aws-cdk/lib/parse-command-line-arguments.ts # this file is generated and some lines cannot be tested
- packages/aws-cdk/lib/parse-command-line-arguments.ts # we generate this file and the generation is tested.
- packages/aws-cdk/lib/cli-arguments.ts # we generate this file and the generation is tested.
- packages/aws-cdk/lib/convert-to-cli-args.ts # we generate this file and the generation is tested.
kaizencc marked this conversation as resolved.
Show resolved Hide resolved
- packages/aws-cdk/lib/cli.ts # we integ test this file
240 changes: 240 additions & 0 deletions packages/aws-cdk/lib/convert-to-cli-args.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
// -------------------------------------------------------------------------------------------
// GENERATED FROM packages/aws-cdk/lib/config.ts.
// Do not edit by hand; all changes will be overwritten at build time from the config file.
// -------------------------------------------------------------------------------------------
/* eslint-disable @stylistic/max-len */
import { CliArguments, GlobalOptions } from './cli-arguments';
import { Command } from './settings';

// @ts-ignore TS6133
export function convertToCliArgs(args: any): CliArguments {
const globalOptions: GlobalOptions = {
app: args.app,
build: args.build,
context: args.context,
plugin: args.plugin,
trace: args.trace,
strict: args.strict,
lookups: args.lookups,
ignoreErrors: args.ignoreErrors,
json: args.json,
verbose: args.verbose,
debug: args.debug,
profile: args.profile,
proxy: args.proxy,
caBundlePath: args.caBundlePath,
ec2creds: args.ec2creds,
versionReporting: args.versionReporting,
pathMetadata: args.pathMetadata,
assetMetadata: args.assetMetadata,
roleArn: args.roleArn,
staging: args.staging,
output: args.output,
notices: args.notices,
noColor: args.noColor,
ci: args.ci,
unstable: args.unstable,
};
let commandOptions;
switch (args._[0] as Command) {
case 'list':
commandOptions = {
long: args.long,
showDependencies: args.showDependencies,
};
break;

case 'synthesize':
commandOptions = {
exclusively: args.exclusively,
validation: args.validation,
quiet: args.quiet,
};
break;

case 'bootstrap':
commandOptions = {
bootstrapBucketName: args.bootstrapBucketName,
bootstrapKmsKeyId: args.bootstrapKmsKeyId,
examplePermissionsBoundary: args.examplePermissionsBoundary,
customPermissionsBoundary: args.customPermissionsBoundary,
bootstrapCustomerKey: args.bootstrapCustomerKey,
qualifier: args.qualifier,
publicAccessBlockConfiguration: args.publicAccessBlockConfiguration,
tags: args.tags,
execute: args.execute,
trust: args.trust,
trustForLookup: args.trustForLookup,
cloudformationExecutionPolicies: args.cloudformationExecutionPolicies,
force: args.force,
terminationProtection: args.terminationProtection,
showTemplate: args.showTemplate,
toolkitStackName: args.toolkitStackName,
template: args.template,
previousParameters: args.previousParameters,
};
break;

case 'gc':
commandOptions = {
action: args.action,
type: args.type,
rollbackBufferDays: args.rollbackBufferDays,
createdBufferDays: args.createdBufferDays,
confirm: args.confirm,
bootstrapStackName: args.bootstrapStackName,
};
break;

case 'deploy':
commandOptions = {
all: args.all,
buildExclude: args.buildExclude,
exclusively: args.exclusively,
requireApproval: args.requireApproval,
notificationArns: args.notificationArns,
tags: args.tags,
execute: args.execute,
changeSetName: args.changeSetName,
method: args.method,
force: args.force,
parameters: args.parameters,
outputsFile: args.outputsFile,
previousParameters: args.previousParameters,
toolkitStackName: args.toolkitStackName,
progress: args.progress,
rollback: args.rollback,
hotswap: args.hotswap,
hotswapFallback: args.hotswapFallback,
watch: args.watch,
logs: args.logs,
concurrency: args.concurrency,
assetParallelism: args.assetParallelism,
assetPrebuild: args.assetPrebuild,
ignoreNoStacks: args.ignoreNoStacks,
};
break;

case 'rollback':
commandOptions = {
all: args.all,
toolkitStackName: args.toolkitStackName,
force: args.force,
validateBootstrapVersion: args.validateBootstrapVersion,
orphan: args.orphan,
};
break;

case 'import':
commandOptions = {
execute: args.execute,
changeSetName: args.changeSetName,
toolkitStackName: args.toolkitStackName,
rollback: args.rollback,
force: args.force,
recordResourceMapping: args.recordResourceMapping,
resourceMapping: args.resourceMapping,
};
break;

case 'watch':
commandOptions = {
buildExclude: args.buildExclude,
exclusively: args.exclusively,
changeSetName: args.changeSetName,
force: args.force,
toolkitStackName: args.toolkitStackName,
progress: args.progress,
rollback: args.rollback,
hotswap: args.hotswap,
hotswapFallback: args.hotswapFallback,
logs: args.logs,
concurrency: args.concurrency,
};
break;

case 'destroy':
commandOptions = {
all: args.all,
exclusively: args.exclusively,
force: args.force,
};
break;

case 'diff':
commandOptions = {
exclusively: args.exclusively,
contextLines: args.contextLines,
template: args.template,
strict: args.strict,
securityOnly: args.securityOnly,
fail: args.fail,
processed: args.processed,
quiet: args.quiet,
changeSet: args.changeSet,
};
break;

case 'metadata':
commandOptions = {};
break;

case 'acknowledge':
commandOptions = {};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at our current for this command I see:

case 'ack':
return cli.acknowledge(args.ID);

Should this PR also handle positional arguments? I would expect we have a strongly typed args.acknowledge.id or something.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. A big part of my refactor is to make sure we don't have to use args, argv, and configuration.settings everywhere and instead just have 1 object with arguments.

Currently those positional arguments are found in index 1 and beyond on argv._: argv._: [Command, ...string]

It will be a bit awkward to figure out the right way to deal with that, which I would like to do in a separate PR.

break;

case 'notices':
commandOptions = {
unacknowledged: args.unacknowledged,
};
break;

case 'init':
commandOptions = {
language: args.language,
list: args.list,
generateOnly: args.generateOnly,
};
break;

case 'migrate':
commandOptions = {
stackName: args.stackName,
language: args.language,
account: args.account,
region: args.region,
fromPath: args.fromPath,
fromStack: args.fromStack,
outputPath: args.outputPath,
fromScan: args.fromScan,
filter: args.filter,
compress: args.compress,
};
break;

case 'context':
commandOptions = {
reset: args.reset,
force: args.force,
clear: args.clear,
};
break;

case 'docs':
commandOptions = {
browser: args.browser,
};
break;

case 'doctor':
commandOptions = {};
break;
}
const cliArguments: CliArguments = {
_: args._,
globalOptions,
[args._[0]]: commandOptions,
};

return cliArguments;
}
5 changes: 3 additions & 2 deletions packages/aws-cdk/scripts/cli-args-gen.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import * as fs from 'fs';
// eslint-disable-next-line import/no-extraneous-dependencies
import { renderYargs, renderCliType } from '@aws-cdk/cli-args-gen';
import { renderYargs, renderCliArgsType, renderCliArgsFunc } from '@aws-cdk/cli-args-gen';
import { makeConfig, YARGS_HELPERS } from '../lib/config';

async function main() {
fs.writeFileSync('./lib/parse-command-line-arguments.ts', await renderYargs(await makeConfig(), YARGS_HELPERS));
fs.writeFileSync('./lib/cli-arguments.ts', await renderCliType(await makeConfig()));
fs.writeFileSync('./lib/cli-arguments.ts', await renderCliArgsType(await makeConfig()));
kaizencc marked this conversation as resolved.
Show resolved Hide resolved
fs.writeFileSync('./lib/convert-to-cli-args.ts', await renderCliArgsFunc(await makeConfig()));
}

main().then(() => {
Expand Down
113 changes: 100 additions & 13 deletions packages/aws-cdk/test/cli-arguments.test.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,106 @@
import { CliArguments } from '../lib/cli-arguments';
import { Command } from '../lib/settings';
import { convertToCliArgs } from '../lib/convert-to-cli-args';

// CliArguments is not being used right now, so the testing suite is rather redundant.
// This file is meant to be populated when CliArguments is used.
test('cli arguments can be used as a type', async () => {
const argv: CliArguments = {
_: [Command.DEPLOY],
test('yargs object can be converted to cli arguments', async () => {
// This input represents what would come out of yargs, i.e.
// await parseCommandLineArguments(args);
const input = {
kaizencc marked this conversation as resolved.
Show resolved Hide resolved
'_': ['deploy'],
'notification-arns': ['[]'],
'notificationArns': ['[]'],
'v': 1,
'verbose': 1,
'lookups': true,
'ignore-errors': false,
'ignoreErrors': false,
'json': false,
'j': false,
'debug': false,
'ec2creds': undefined,
'i': undefined,
'version-reporting': undefined,
'versionReporting': undefined,
'path-metadata': undefined,
'pathMetadata': undefined,
'asset-metadata': undefined,
'assetMetadata': undefined,
'role-arn': undefined,
'r': undefined,
'roleArn': undefined,
'staging': true,
'no-color': false,
'noColor': false,
'ci': false,
'unstable': [],
'all': false,
'build-exclude': [],
'E': [],
'buildExclude': [],
'force': false,
'f': false,
'parameters': [{}],
'previous-parameters': true,
'previousParameters': true,
'logs': true,
'concurrency': 1,
'asset-prebuild': true,
'assetPrebuild': true,
'ignore-no-stacks': false,
'ignoreNoStacks': false,
};

const result = convertToCliArgs(input);

expect(result).toEqual({
_: ['deploy'],
globalOptions: {
lookups: true,
app: undefined,
assetMetadata: undefined,
build: undefined,
caBundlePath: undefined,
context: undefined,
ignoreErrors: false,
noColor: false,
pathMetadata: undefined,
proxy: undefined,
roleArn: undefined,
staging: true,
strict: undefined,
verbose: 1,
versionReporting: undefined,
ci: false,
debug: false,
ec2creds: undefined,
json: false,
verbose: false,
lookups: true,
unstable: [],
notices: undefined,
output: undefined,
},
};

expect(argv._[0]).toBe('deploy');
expect(argv.globalOptions?.lookups).toBeTruthy();
deploy: {
all: false,
assetParallelism: undefined,
assetPrebuild: true,
buildExclude: [],
changeSetName: undefined,
concurrency: 1,
execute: undefined,
exclusively: undefined,
force: false,
hotswap: undefined,
hotswapFallback: undefined,
ignoreNoStacks: false,
logs: true,
method: undefined,
notificationArns: ['[]'],
outputsFile: undefined,
parameters: [{}],
previousParameters: true,
progress: undefined,
requireApproval: undefined,
rollback: undefined,
tags: undefined,
toolkitStackName: undefined,
watch: undefined,
},
});
});
7 changes: 5 additions & 2 deletions tools/@aws-cdk/cli-args-gen/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
# cli-args-gen

Generates CDK CLI configurations from the source of truth in `packages/aws-cdk/lib/config.ts`.
Currently generates `yargs` config into `packages/aws-cdk/lib/parse-command-line-arguments.ts` and
strongly-typed CLI arguments interface into `packages/aws-cdk-lib/cli-arguments.ts`.
Currently generates the following files:

- `packages/aws-cdk/lib/parse-command-line-arguments.ts`: `yargs` config.
- `packages/aws-cdk-lib/cli-arguments.ts`: strongly typed `CliArguments` interface.
- `packages/aws-cdk-lib/convert-to-cli-args.ts`: converts the `any` returned by `yargs` to `CliArguments`.

## Usage

Expand Down
Loading
Loading