From 1b6a5635746989dc0c058e8f9adc8c0ed189f81a Mon Sep 17 00:00:00 2001 From: Kaizen Conroy Date: Thu, 19 Dec 2024 16:46:52 -0500 Subject: [PATCH 01/11] explicit default --- .../lib/parse-command-line-arguments.ts | 198 ++++++++++++------ tools/@aws-cdk/cli-args-gen/lib/yargs-gen.ts | 5 +- .../cli-args-gen/test/yargs-gen.test.ts | 158 +++++++------- 3 files changed, 216 insertions(+), 145 deletions(-) diff --git a/packages/aws-cdk/lib/parse-command-line-arguments.ts b/packages/aws-cdk/lib/parse-command-line-arguments.ts index 2432fa23ba3c8..96b4bf81285b0 100644 --- a/packages/aws-cdk/lib/parse-command-line-arguments.ts +++ b/packages/aws-cdk/lib/parse-command-line-arguments.ts @@ -12,16 +12,19 @@ export function parseCommandLineArguments(args: Array): any { .env('CDK') .usage('Usage: cdk -a COMMAND') .option('app', { + default: undefined, type: 'string', alias: 'a', desc: 'REQUIRED WHEN RUNNING APP: command-line for executing your app or a cloud assembly directory (e.g. "node bin/my-app.js"). Can also be specified in cdk.json or ~/.cdk.json', requiresArg: true, }) .option('build', { + default: undefined, type: 'string', desc: 'Command-line for a pre-synth build', }) .option('context', { + default: undefined, type: 'array', alias: 'c', desc: 'Add contextual string parameter (KEY=VALUE)', @@ -29,6 +32,7 @@ export function parseCommandLineArguments(args: Array): any { requiresArg: true, }) .option('plugin', { + default: undefined, type: 'array', alias: 'p', desc: 'Name or path of a node package that extend the CDK features. Can be specified multiple times', @@ -36,127 +40,134 @@ export function parseCommandLineArguments(args: Array): any { requiresArg: true, }) .option('trace', { + default: undefined, type: 'boolean', desc: 'Print trace for stack warnings', }) .option('strict', { + default: undefined, type: 'boolean', desc: 'Do not construct stacks with warnings', }) .option('lookups', { + default: true, type: 'boolean', desc: 'Perform context lookups (synthesis fails if this is disabled and context lookups need to be performed)', - default: true, }) .option('ignore-errors', { - type: 'boolean', default: false, + type: 'boolean', desc: 'Ignores synthesis errors, which will likely produce an invalid output', }) .option('json', { + default: false, type: 'boolean', alias: 'j', desc: 'Use JSON output instead of YAML when templates are printed to STDOUT', - default: false, }) .option('verbose', { + default: false, type: 'boolean', alias: 'v', desc: 'Show debug logs (specify multiple times to increase verbosity)', - default: false, count: true, }) .option('debug', { + default: false, type: 'boolean', desc: 'Debug the CDK app. Log additional information during synthesis, such as creation stack traces of tokens (sets CDK_DEBUG, will slow down synthesis)', - default: false, }) .option('profile', { + default: undefined, type: 'string', desc: 'Use the indicated AWS profile as the default environment', requiresArg: true, }) .option('proxy', { + default: undefined, type: 'string', desc: 'Use the indicated proxy. Will read from HTTPS_PROXY environment variable if not specified', requiresArg: true, }) .option('ca-bundle-path', { + default: undefined, type: 'string', desc: 'Path to CA certificate to use when validating HTTPS requests. Will read from AWS_CA_BUNDLE environment variable if not specified', requiresArg: true, }) .option('ec2creds', { + default: undefined, type: 'boolean', alias: 'i', - default: undefined, desc: 'Force trying to fetch EC2 instance credentials. Default: guess EC2 instance status', }) .option('version-reporting', { + default: undefined, type: 'boolean', desc: 'Include the "AWS::CDK::Metadata" resource in synthesized templates (enabled by default)', - default: undefined, }) .option('path-metadata', { + default: undefined, type: 'boolean', desc: 'Include "aws:cdk:path" CloudFormation metadata for each resource (enabled by default)', - default: undefined, }) .option('asset-metadata', { + default: undefined, type: 'boolean', desc: 'Include "aws:asset:*" CloudFormation metadata for resources that uses assets (enabled by default)', - default: undefined, }) .option('role-arn', { + default: undefined, type: 'string', alias: 'r', desc: 'ARN of Role to use when invoking CloudFormation', - default: undefined, requiresArg: true, }) .option('staging', { + default: true, type: 'boolean', desc: 'Copy assets to the output directory (use --no-staging to disable the copy of assets which allows local debugging via the SAM CLI to reference the original source files)', - default: true, }) .option('output', { + default: undefined, type: 'string', alias: 'o', desc: 'Emits the synthesized cloud assembly into a directory (default: cdk.out)', requiresArg: true, }) .option('notices', { + default: undefined, type: 'boolean', desc: 'Show relevant notices', }) .option('no-color', { + default: false, type: 'boolean', desc: 'Removes colors and other style from console output', - default: false, }) .option('ci', { + default: helpers.isCI(), type: 'boolean', desc: 'Force CI detection. If CI=true then logs will be sent to stdout instead of stderr', - default: helpers.isCI(), }) .option('unstable', { + default: [], type: 'array', desc: 'Opt in to unstable features. The flag indicates that the scope and API of a feature might still change. Otherwise the feature is generally production ready and fully supported. Can be specified multiple times.', - default: [], nargs: 1, requiresArg: true, }) .command(['list [STACKS..]', 'ls [STACKS..]'], 'Lists all stacks in the app', (yargs: Argv) => yargs .option('long', { - type: 'boolean', default: false, + type: 'boolean', alias: 'l', desc: 'Display environment information for each stack', }) .option('show-dependencies', { - type: 'boolean', default: false, + type: 'boolean', alias: 'd', desc: 'Display stack dependency information for each stack', }) @@ -164,129 +175,132 @@ export function parseCommandLineArguments(args: Array): any { .command(['synthesize [STACKS..]', 'synth [STACKS..]'], 'Synthesizes and prints the CloudFormation template for this stack', (yargs: Argv) => yargs .option('exclusively', { + default: undefined, type: 'boolean', alias: 'e', desc: "Only synthesize requested stacks, don't include dependencies", }) .option('validation', { + default: true, type: 'boolean', desc: 'After synthesis, validate stacks with the "validateOnSynth" attribute set (can also be controlled with CDK_VALIDATION)', - default: true, }) .option('quiet', { + default: false, type: 'boolean', alias: 'q', desc: 'Do not output CloudFormation Template to stdout', - default: false, }) ) .command('bootstrap [ENVIRONMENTS..]', 'Deploys the CDK toolkit stack into an AWS environment', (yargs: Argv) => yargs .option('bootstrap-bucket-name', { + default: undefined, type: 'string', alias: ['b', 'toolkit-bucket-name'], desc: 'The name of the CDK toolkit bucket; bucket will be created and must not exist', - default: undefined, }) .option('bootstrap-kms-key-id', { + default: undefined, type: 'string', desc: 'AWS KMS master key ID used for the SSE-KMS encryption', - default: undefined, conflicts: 'bootstrap-customer-key', }) .option('example-permissions-boundary', { + default: undefined, type: 'boolean', alias: 'epb', desc: 'Use the example permissions boundary.', - default: undefined, conflicts: 'custom-permissions-boundary', }) .option('custom-permissions-boundary', { + default: undefined, type: 'string', alias: 'cpb', desc: 'Use the permissions boundary specified by name.', - default: undefined, conflicts: 'example-permissions-boundary', }) .option('bootstrap-customer-key', { + default: undefined, type: 'boolean', desc: 'Create a Customer Master Key (CMK) for the bootstrap bucket (you will be charged but can customize permissions, modern bootstrapping only)', - default: undefined, conflicts: 'bootstrap-kms-key-id', }) .option('qualifier', { + default: undefined, type: 'string', desc: 'String which must be unique for each bootstrap stack. You must configure it on your CDK app if you change this from the default.', - default: undefined, }) .option('public-access-block-configuration', { + default: undefined, type: 'boolean', desc: 'Block public access configuration on CDK toolkit bucket (enabled by default) ', - default: undefined, }) .option('tags', { + default: [], type: 'array', alias: 't', desc: 'Tags to add for the stack (KEY=VALUE)', - default: [], nargs: 1, requiresArg: true, }) .option('execute', { + default: true, type: 'boolean', desc: 'Whether to execute ChangeSet (--no-execute will NOT execute the ChangeSet)', - default: true, }) .option('trust', { + default: [], type: 'array', desc: 'The AWS account IDs that should be trusted to perform deployments into this environment (may be repeated, modern bootstrapping only)', - default: [], nargs: 1, requiresArg: true, }) .option('trust-for-lookup', { + default: [], type: 'array', desc: 'The AWS account IDs that should be trusted to look up values in this environment (may be repeated, modern bootstrapping only)', - default: [], nargs: 1, requiresArg: true, }) .option('cloudformation-execution-policies', { + default: [], type: 'array', desc: 'The Managed Policy ARNs that should be attached to the role performing deployments into this environment (may be repeated, modern bootstrapping only)', - default: [], nargs: 1, requiresArg: true, }) .option('force', { + default: false, alias: 'f', type: 'boolean', desc: 'Always bootstrap even if it would downgrade template version', - default: false, }) .option('termination-protection', { - type: 'boolean', default: undefined, + type: 'boolean', desc: 'Toggle CloudFormation termination protection on the bootstrap stacks', }) .option('show-template', { + default: false, type: 'boolean', desc: "Instead of actual bootstrapping, print the current CLI's bootstrapping template to stdout for customization", - default: false, }) .option('toolkit-stack-name', { + default: undefined, type: 'string', desc: 'The name of the CDK toolkit stack to create', requiresArg: true, }) .option('template', { + default: undefined, type: 'string', requiresArg: true, desc: 'Use the template from the given file instead of the built-in one (use --show-template to obtain an example)', }) .option('previous-parameters', { - type: 'boolean', default: true, + type: 'boolean', desc: 'Use previous values for existing parameters (you must specify all parameters on every deployment if this is disabled)', }) ) @@ -296,31 +310,32 @@ export function parseCommandLineArguments(args: Array): any { (yargs: Argv) => yargs .option('action', { + default: 'full', type: 'string', desc: 'The action (or sub-action) you want to perform. Valid entires are "print", "tag", "delete-tagged", "full".', - default: 'full', }) .option('type', { + default: 'all', type: 'string', desc: 'Specify either ecr, s3, or all', - default: 'all', }) .option('rollback-buffer-days', { + default: 0, type: 'number', desc: 'Delete assets that have been marked as isolated for this many days', - default: 0, }) .option('created-buffer-days', { + default: 1, type: 'number', desc: 'Never delete assets younger than this (in days)', - default: 1, }) .option('confirm', { + default: true, type: 'boolean', desc: 'Confirm via manual prompt before deletion', - default: true, }) .option('bootstrap-stack-name', { + default: undefined, type: 'string', desc: 'The name of the CDK toolkit stack, if different from the default "CDKToolkit"', requiresArg: true, @@ -329,35 +344,39 @@ export function parseCommandLineArguments(args: Array): any { .command('deploy [STACKS..]', 'Deploys the stack(s) named STACKS into your AWS account', (yargs: Argv) => yargs .option('all', { + default: false, type: 'boolean', desc: 'Deploy all available stacks', - default: false, }) .option('build-exclude', { + default: [], type: 'array', alias: 'E', desc: 'Do not rebuild asset with the given ID. Can be specified multiple times', - default: [], nargs: 1, requiresArg: true, }) .option('exclusively', { + default: undefined, type: 'boolean', alias: 'e', desc: "Only deploy requested stacks, don't include dependencies", }) .option('require-approval', { + default: undefined, type: 'string', choices: ['never', 'any-change', 'broadening'], desc: 'What security-sensitive changes need manual approval', }) .option('notification-arns', { + default: undefined, type: 'array', desc: "ARNs of SNS topics that CloudFormation will notify with stack related events. These will be added to ARNs specified with the 'notificationArns' stack property.", nargs: 1, requiresArg: true, }) .option('tags', { + default: undefined, type: 'array', alias: 't', desc: 'Tags to add to the stack (KEY=VALUE), overrides tags from Cloud Assembly (deprecated)', @@ -365,15 +384,18 @@ export function parseCommandLineArguments(args: Array): any { requiresArg: true, }) .option('execute', { + default: undefined, type: 'boolean', desc: 'Whether to execute ChangeSet (--no-execute will NOT execute the ChangeSet) (deprecated)', deprecated: true, }) .option('change-set-name', { + default: undefined, type: 'string', desc: 'Name of the CloudFormation change set to create (only if method is not direct)', }) .option('method', { + default: undefined, alias: 'm', type: 'string', choices: ['direct', 'change-set', 'prepare-change-set'], @@ -381,108 +403,119 @@ export function parseCommandLineArguments(args: Array): any { desc: 'How to perform the deployment. Direct is a bit faster but lacks progress information', }) .option('force', { + default: false, alias: 'f', type: 'boolean', desc: 'Always deploy stack even if templates are identical', - default: false, }) .option('parameters', { + default: {}, type: 'array', desc: 'Additional parameters passed to CloudFormation at deploy time (STACK:KEY=VALUE)', - default: {}, nargs: 1, requiresArg: true, }) .option('outputs-file', { + default: undefined, type: 'string', alias: 'O', desc: 'Path to file where stack outputs will be written as JSON', requiresArg: true, }) .option('previous-parameters', { - type: 'boolean', default: true, + type: 'boolean', desc: 'Use previous values for existing parameters (you must specify all parameters on every deployment if this is disabled)', }) .option('toolkit-stack-name', { + default: undefined, type: 'string', desc: 'The name of the existing CDK toolkit stack (only used for app using legacy synthesis)', requiresArg: true, }) .option('progress', { + default: undefined, type: 'string', choices: ['bar', 'events'], desc: 'Display mode for stack activity events', }) .option('rollback', { + default: undefined, type: 'boolean', desc: "Rollback stack to stable state on failure. Defaults to 'true', iterate more rapidly with --no-rollback or -R. Note: do **not** disable this flag for deployments with resource replacements, as that will always fail", }) .option('R', { type: 'boolean', hidden: true }) .middleware(helpers.yargsNegativeAlias('R', 'rollback'), true) .option('hotswap', { + default: undefined, type: 'boolean', desc: "Attempts to perform a 'hotswap' deployment, but does not fall back to a full deployment if that is not possible. Instead, changes to any non-hotswappable properties are ignored.Do not use this in production environments", }) .option('hotswap-fallback', { + default: undefined, type: 'boolean', desc: "Attempts to perform a 'hotswap' deployment, which skips CloudFormation and updates the resources directly, and falls back to a full deployment if that is not possible. Do not use this in production environments", }) .option('watch', { + default: undefined, type: 'boolean', desc: 'Continuously observe the project files, and deploy the given stack(s) automatically when changes are detected. Implies --hotswap by default', }) .option('logs', { - type: 'boolean', default: true, + type: 'boolean', desc: "Show CloudWatch log events from all resources in the selected Stacks in the terminal. 'true' by default, use --no-logs to turn off. Only in effect if specified alongside the '--watch' option", }) .option('concurrency', { + default: 1, type: 'number', desc: 'Maximum number of simultaneous deployments (dependency permitting) to execute.', - default: 1, requiresArg: true, }) .option('asset-parallelism', { + default: undefined, type: 'boolean', desc: 'Whether to build/publish assets in parallel', }) .option('asset-prebuild', { + default: true, type: 'boolean', desc: 'Whether to build all assets before deploying the first stack (useful for failing Docker builds)', - default: true, }) .option('ignore-no-stacks', { + default: false, type: 'boolean', desc: 'Whether to deploy if the app contains no stacks', - default: false, }) ) .command('rollback [STACKS..]', 'Rolls back the stack(s) named STACKS to their last stable state', (yargs: Argv) => yargs .option('all', { - type: 'boolean', default: false, + type: 'boolean', desc: 'Roll back all available stacks', }) .option('toolkit-stack-name', { + default: undefined, type: 'string', desc: 'The name of the CDK toolkit stack the environment is bootstrapped with', requiresArg: true, }) .option('force', { + default: undefined, alias: 'f', type: 'boolean', desc: 'Orphan all resources for which the rollback operation fails.', }) .option('validate-bootstrap-version', { + default: undefined, type: 'boolean', desc: "Whether to validate the bootstrap stack version. Defaults to 'true', disable with --no-validate-bootstrap-version.", }) .option('orphan', { + default: [], type: 'array', desc: 'Orphan the given resources, identified by their logical ID (can be specified multiple times)', - default: [], nargs: 1, requiresArg: true, }) @@ -490,35 +523,41 @@ export function parseCommandLineArguments(args: Array): any { .command('import [STACK]', 'Import existing resource(s) into the given STACK', (yargs: Argv) => yargs .option('execute', { + default: true, type: 'boolean', desc: 'Whether to execute ChangeSet (--no-execute will NOT execute the ChangeSet)', - default: true, }) .option('change-set-name', { + default: undefined, type: 'string', desc: 'Name of the CloudFormation change set to create', }) .option('toolkit-stack-name', { + default: undefined, type: 'string', desc: 'The name of the CDK toolkit stack to create', requiresArg: true, }) .option('rollback', { + default: undefined, type: 'boolean', desc: "Rollback stack to stable state on failure. Defaults to 'true', iterate more rapidly with --no-rollback or -R. Note: do **not** disable this flag for deployments with resource replacements, as that will always fail", }) .option('force', { + default: undefined, alias: 'f', type: 'boolean', desc: "Do not abort if the template diff includes updates or deletes. This is probably safe but we're not sure, let us know how it goes.", }) .option('record-resource-mapping', { + default: undefined, type: 'string', alias: 'r', requiresArg: true, desc: 'If specified, CDK will generate a mapping of existing physical resources to CDK resources to be imported as. The mapping will be written in the given file path. No actual import operation will be performed', }) .option('resource-mapping', { + default: undefined, type: 'string', alias: 'm', requiresArg: true, @@ -528,77 +567,86 @@ export function parseCommandLineArguments(args: Array): any { .command('watch [STACKS..]', "Shortcut for 'deploy --watch'", (yargs: Argv) => yargs .option('build-exclude', { + default: [], type: 'array', alias: 'E', desc: 'Do not rebuild asset with the given ID. Can be specified multiple times', - default: [], nargs: 1, requiresArg: true, }) .option('exclusively', { + default: undefined, type: 'boolean', alias: 'e', desc: "Only deploy requested stacks, don't include dependencies", }) .option('change-set-name', { + default: undefined, type: 'string', desc: 'Name of the CloudFormation change set to create', }) .option('force', { + default: false, alias: 'f', type: 'boolean', desc: 'Always deploy stack even if templates are identical', - default: false, }) .option('toolkit-stack-name', { + default: undefined, type: 'string', desc: 'The name of the existing CDK toolkit stack (only used for app using legacy synthesis)', requiresArg: true, }) .option('progress', { + default: undefined, type: 'string', choices: ['bar', 'events'], desc: 'Display mode for stack activity events', }) .option('rollback', { + default: undefined, type: 'boolean', desc: "Rollback stack to stable state on failure. Defaults to 'true', iterate more rapidly with --no-rollback or -R. Note: do **not** disable this flag for deployments with resource replacements, as that will always fail", }) .option('R', { type: 'boolean', hidden: true }) .middleware(helpers.yargsNegativeAlias('R', 'rollback'), true) .option('hotswap', { + default: undefined, type: 'boolean', desc: "Attempts to perform a 'hotswap' deployment, but does not fall back to a full deployment if that is not possible. Instead, changes to any non-hotswappable properties are ignored.'true' by default, use --no-hotswap to turn off", }) .option('hotswap-fallback', { + default: undefined, type: 'boolean', desc: "Attempts to perform a 'hotswap' deployment, which skips CloudFormation and updates the resources directly, and falls back to a full deployment if that is not possible.", }) .option('logs', { - type: 'boolean', default: true, + type: 'boolean', desc: "Show CloudWatch log events from all resources in the selected Stacks in the terminal. 'true' by default, use --no-logs to turn off", }) .option('concurrency', { + default: 1, type: 'number', desc: 'Maximum number of simultaneous deployments (dependency permitting) to execute.', - default: 1, requiresArg: true, }) ) .command('destroy [STACKS..]', 'Destroy the stack(s) named STACKS', (yargs: Argv) => yargs .option('all', { - type: 'boolean', default: false, + type: 'boolean', desc: 'Destroy all available stacks', }) .option('exclusively', { + default: undefined, type: 'boolean', alias: 'e', desc: "Only destroy requested stacks, don't include dependees", }) .option('force', { + default: undefined, type: 'boolean', alias: 'f', desc: 'Do not ask for confirmation before destroying the stacks', @@ -610,127 +658,141 @@ export function parseCommandLineArguments(args: Array): any { (yargs: Argv) => yargs .option('exclusively', { + default: undefined, type: 'boolean', alias: 'e', desc: "Only diff requested stacks, don't include dependencies", }) .option('context-lines', { + default: 3, type: 'number', desc: 'Number of context lines to include in arbitrary JSON diff rendering', - default: 3, requiresArg: true, }) .option('template', { + default: undefined, type: 'string', desc: 'The path to the CloudFormation template to compare with', requiresArg: true, }) .option('strict', { + default: false, type: 'boolean', desc: 'Do not filter out AWS::CDK::Metadata resources, mangled non-ASCII characters, or the CheckBootstrapVersionRule', - default: false, }) .option('security-only', { + default: false, type: 'boolean', desc: 'Only diff for broadened security changes', - default: false, }) .option('fail', { + default: undefined, type: 'boolean', desc: 'Fail with exit code 1 in case of diff', }) .option('processed', { + default: false, type: 'boolean', desc: 'Whether to compare against the template with Transforms already processed', - default: false, }) .option('quiet', { + default: false, type: 'boolean', alias: 'q', desc: 'Do not print stack name and default message when there is no diff to stdout', - default: false, }) .option('change-set', { + default: true, type: 'boolean', alias: 'changeset', desc: 'Whether to create a changeset to analyze resource replacements. In this mode, diff will use the deploy role instead of the lookup role.', - default: true, }) ) .command('metadata [STACK]', 'Returns all metadata associated with this stack') .command(['acknowledge [ID]', 'ack [ID]'], 'Acknowledge a notice so that it does not show up anymore') .command('notices', 'Returns a list of relevant notices', (yargs: Argv) => yargs.option('unacknowledged', { + default: false, type: 'boolean', alias: 'u', - default: false, desc: 'Returns a list of unacknowledged notices', }) ) .command('init [TEMPLATE]', 'Create a new, empty CDK project from a template.', (yargs: Argv) => yargs .option('language', { + default: undefined, type: 'string', alias: 'l', desc: 'The language to be used for the new project (default can be configured in ~/.cdk.json)', choices: ['csharp', 'fsharp', 'go', 'java', 'javascript', 'python', 'typescript'], }) .option('list', { + default: undefined, type: 'boolean', desc: 'List the available templates', }) .option('generate-only', { - type: 'boolean', default: false, + type: 'boolean', desc: 'If true, only generates project files, without executing additional operations such as setting up a git repo, installing dependencies or compiling the project', }) ) .command('migrate', 'Migrate existing AWS resources into a CDK app', (yargs: Argv) => yargs .option('stack-name', { + default: undefined, type: 'string', alias: 'n', desc: 'The name assigned to the stack created in the new project. The name of the app will be based off this name as well.', requiresArg: true, }) .option('language', { - type: 'string', default: 'typescript', + type: 'string', alias: 'l', desc: 'The language to be used for the new project', choices: ['typescript', 'go', 'java', 'python', 'csharp'], }) .option('account', { + default: undefined, type: 'string', desc: 'The account to retrieve the CloudFormation stack template from', }) .option('region', { + default: undefined, type: 'string', desc: 'The region to retrieve the CloudFormation stack template from', }) .option('from-path', { + default: undefined, type: 'string', desc: 'The path to the CloudFormation template to migrate. Use this for locally stored templates', }) .option('from-stack', { + default: undefined, type: 'boolean', desc: 'Use this flag to retrieve the template for an existing CloudFormation stack', }) .option('output-path', { + default: undefined, type: 'string', desc: 'The output path for the migrated CDK app', }) .option('from-scan', { + default: undefined, type: 'string', desc: 'Determines if a new scan should be created, or the last successful existing scan should be used \n options are "new" or "most-recent"', }) .option('filter', { + default: undefined, type: 'array', desc: 'Filters the resource scan based on the provided criteria in the following format: "key1=value1,key2=value2"\n This field can be passed multiple times for OR style filtering: \n filtering options: \n resource-identifier: A key-value pair that identifies the target resource. i.e. {"ClusterName", "myCluster"}\n resource-type-prefix: A string that represents a type-name prefix. i.e. "AWS::DynamoDB::"\n tag-key: a string that matches resources with at least one tag with the provided key. i.e. "myTagKey"\n tag-value: a string that matches resources with at least one tag with the provided value. i.e. "myTagValue"', nargs: 1, requiresArg: true, }) .option('compress', { + default: undefined, type: 'boolean', desc: 'Use this flag to zip the generated CDK app', }) @@ -738,28 +800,30 @@ export function parseCommandLineArguments(args: Array): any { .command('context', 'Manage cached context values', (yargs: Argv) => yargs .option('reset', { + default: undefined, alias: 'e', desc: 'The context key (or its index) to reset', type: 'string', requiresArg: true, }) .option('force', { + default: false, alias: 'f', desc: 'Ignore missing key error', type: 'boolean', - default: false, }) .option('clear', { + default: undefined, desc: 'Clear all context', type: 'boolean', }) ) .command(['docs', 'doc'], 'Opens the reference documentation in a browser', (yargs: Argv) => yargs.option('browser', { + default: helpers.browserForPlatform(), alias: 'b', desc: 'the command to use to open the browser, using %u as a placeholder for the path of the file to open', type: 'string', - default: helpers.browserForPlatform(), }) ) .command('doctor', 'Check your set-up for potential problems') diff --git a/tools/@aws-cdk/cli-args-gen/lib/yargs-gen.ts b/tools/@aws-cdk/cli-args-gen/lib/yargs-gen.ts index ff7ab0efc3973..fe2f4fdbff746 100644 --- a/tools/@aws-cdk/cli-args-gen/lib/yargs-gen.ts +++ b/tools/@aws-cdk/cli-args-gen/lib/yargs-gen.ts @@ -116,7 +116,10 @@ function makeYargs(config: CliConfig, helpers: CliHelpers): Statement { function makeOptions(prefix: Expression, options: { [optionName: string]: CliOption }, helpers: CliHelpers) { let optionsExpr = prefix; for (const option of Object.keys(options)) { - const theOption: CliOption = options[option]; + const theOption: CliOption = { + default: undefined, // make the default explicit (overridden if the option includes an actual default) + ...options[option], + }; const optionProps: YargsOption = cloneDeep(theOption); const optionArgs: { [key: string]: Expression } = {}; diff --git a/tools/@aws-cdk/cli-args-gen/test/yargs-gen.test.ts b/tools/@aws-cdk/cli-args-gen/test/yargs-gen.test.ts index 45820f41aeff1..4357ca365c713 100644 --- a/tools/@aws-cdk/cli-args-gen/test/yargs-gen.test.ts +++ b/tools/@aws-cdk/cli-args-gen/test/yargs-gen.test.ts @@ -24,49 +24,52 @@ describe('render', () => { }; expect(await renderYargs(config, YARGS_HELPERS)).toMatchInlineSnapshot(` - "// ------------------------------------------------------------------------------------------- - // 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/comma-dangle, @stylistic/comma-spacing, @stylistic/max-len, @stylistic/quotes, @stylistic/quote-props */ - import { Argv } from 'yargs'; - import * as helpers from './util/yargs-helpers'; +"// ------------------------------------------------------------------------------------------- +// 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/comma-dangle, @stylistic/comma-spacing, @stylistic/max-len, @stylistic/quotes, @stylistic/quote-props */ +import { Argv } from 'yargs'; +import * as helpers from './util/yargs-helpers'; - // @ts-ignore TS6133 - export function parseCommandLineArguments(args: Array): any { - return yargs - .env('CDK') - .usage('Usage: cdk -a COMMAND') - .option('one', { - type: 'string', - alias: 'o', - desc: 'text for one', - requiresArg: true, - }) - .option('two', { - type: 'number', - desc: 'text for two', - }) - .option('three', { - type: 'array', - alias: 't', - desc: 'text for three', - nargs: 1, - requiresArg: true, - }) - .version(helpers.cliVersion()) - .demandCommand(1, '') - .recommendCommands() - .help() - .alias('h', 'help') - .epilogue( - 'If your app has a single stack, there is no need to specify the stack name\\n\\nIf one of cdk.json or ~/.cdk.json exists, options specified there will be used as defaults. Settings in cdk.json take precedence.' - ) - .parse(args); - } // eslint-disable-next-line @typescript-eslint/no-require-imports - const yargs = require('yargs'); - " - `); +// @ts-ignore TS6133 +export function parseCommandLineArguments(args: Array): any { + return yargs + .env('CDK') + .usage('Usage: cdk -a COMMAND') + .option('one', { + default: undefined, + type: 'string', + alias: 'o', + desc: 'text for one', + requiresArg: true, + }) + .option('two', { + default: undefined, + type: 'number', + desc: 'text for two', + }) + .option('three', { + default: undefined, + type: 'array', + alias: 't', + desc: 'text for three', + nargs: 1, + requiresArg: true, + }) + .version(helpers.cliVersion()) + .demandCommand(1, '') + .recommendCommands() + .help() + .alias('h', 'help') + .epilogue( + 'If your app has a single stack, there is no need to specify the stack name\\n\\nIf one of cdk.json or ~/.cdk.json exists, options specified there will be used as defaults. Settings in cdk.json take precedence.' + ) + .parse(args); +} // eslint-disable-next-line @typescript-eslint/no-require-imports +const yargs = require('yargs'); +" +`); }); test('can generate negativeAlias', async () => { @@ -88,42 +91,43 @@ describe('render', () => { }; expect(await renderYargs(config, YARGS_HELPERS)).toMatchInlineSnapshot(` - "// ------------------------------------------------------------------------------------------- - // 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/comma-dangle, @stylistic/comma-spacing, @stylistic/max-len, @stylistic/quotes, @stylistic/quote-props */ - import { Argv } from 'yargs'; - import * as helpers from './util/yargs-helpers'; +"// ------------------------------------------------------------------------------------------- +// 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/comma-dangle, @stylistic/comma-spacing, @stylistic/max-len, @stylistic/quotes, @stylistic/quote-props */ +import { Argv } from 'yargs'; +import * as helpers from './util/yargs-helpers'; - // @ts-ignore TS6133 - export function parseCommandLineArguments(args: Array): any { - return yargs - .env('CDK') - .usage('Usage: cdk -a COMMAND') - .command('test', 'the action under test', (yargs: Argv) => - yargs - .option('one', { - type: 'boolean', - alias: 'o', - desc: 'text for one', - }) - .option('O', { type: 'boolean', hidden: true }) - .middleware(helpers.yargsNegativeAlias('O', 'one'), true) - ) - .version(helpers.cliVersion()) - .demandCommand(1, '') - .recommendCommands() - .help() - .alias('h', 'help') - .epilogue( - 'If your app has a single stack, there is no need to specify the stack name\\n\\nIf one of cdk.json or ~/.cdk.json exists, options specified there will be used as defaults. Settings in cdk.json take precedence.' - ) - .parse(args); - } // eslint-disable-next-line @typescript-eslint/no-require-imports - const yargs = require('yargs'); - " - `); +// @ts-ignore TS6133 +export function parseCommandLineArguments(args: Array): any { + return yargs + .env('CDK') + .usage('Usage: cdk -a COMMAND') + .command('test', 'the action under test', (yargs: Argv) => + yargs + .option('one', { + default: undefined, + type: 'boolean', + alias: 'o', + desc: 'text for one', + }) + .option('O', { type: 'boolean', hidden: true }) + .middleware(helpers.yargsNegativeAlias('O', 'one'), true) + ) + .version(helpers.cliVersion()) + .demandCommand(1, '') + .recommendCommands() + .help() + .alias('h', 'help') + .epilogue( + 'If your app has a single stack, there is no need to specify the stack name\\n\\nIf one of cdk.json or ~/.cdk.json exists, options specified there will be used as defaults. Settings in cdk.json take precedence.' + ) + .parse(args); +} // eslint-disable-next-line @typescript-eslint/no-require-imports +const yargs = require('yargs'); +" +`); }); test('can pass-through expression unchanged', async () => { From ec4358c0601534be1109531d5da2fa7e720976e8 Mon Sep 17 00:00:00 2001 From: Kaizen Conroy Date: Fri, 20 Dec 2024 13:38:37 -0500 Subject: [PATCH 02/11] formatting --- .../cli-args-gen/test/yargs-gen.test.ts | 158 +++++++++--------- 1 file changed, 79 insertions(+), 79 deletions(-) diff --git a/tools/@aws-cdk/cli-args-gen/test/yargs-gen.test.ts b/tools/@aws-cdk/cli-args-gen/test/yargs-gen.test.ts index 4357ca365c713..d946030297a91 100644 --- a/tools/@aws-cdk/cli-args-gen/test/yargs-gen.test.ts +++ b/tools/@aws-cdk/cli-args-gen/test/yargs-gen.test.ts @@ -24,51 +24,51 @@ describe('render', () => { }; expect(await renderYargs(config, YARGS_HELPERS)).toMatchInlineSnapshot(` -"// ------------------------------------------------------------------------------------------- -// 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/comma-dangle, @stylistic/comma-spacing, @stylistic/max-len, @stylistic/quotes, @stylistic/quote-props */ -import { Argv } from 'yargs'; -import * as helpers from './util/yargs-helpers'; + "// ------------------------------------------------------------------------------------------- + // 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/comma-dangle, @stylistic/comma-spacing, @stylistic/max-len, @stylistic/quotes, @stylistic/quote-props */ + import { Argv } from 'yargs'; + import * as helpers from './util/yargs-helpers'; -// @ts-ignore TS6133 -export function parseCommandLineArguments(args: Array): any { - return yargs - .env('CDK') - .usage('Usage: cdk -a COMMAND') - .option('one', { - default: undefined, - type: 'string', - alias: 'o', - desc: 'text for one', - requiresArg: true, - }) - .option('two', { - default: undefined, - type: 'number', - desc: 'text for two', - }) - .option('three', { - default: undefined, - type: 'array', - alias: 't', - desc: 'text for three', - nargs: 1, - requiresArg: true, - }) - .version(helpers.cliVersion()) - .demandCommand(1, '') - .recommendCommands() - .help() - .alias('h', 'help') - .epilogue( - 'If your app has a single stack, there is no need to specify the stack name\\n\\nIf one of cdk.json or ~/.cdk.json exists, options specified there will be used as defaults. Settings in cdk.json take precedence.' - ) - .parse(args); -} // eslint-disable-next-line @typescript-eslint/no-require-imports -const yargs = require('yargs'); -" + // @ts-ignore TS6133 + export function parseCommandLineArguments(args: Array): any { + return yargs + .env('CDK') + .usage('Usage: cdk -a COMMAND') + .option('one', { + default: undefined, + type: 'string', + alias: 'o', + desc: 'text for one', + requiresArg: true, + }) + .option('two', { + default: undefined, + type: 'number', + desc: 'text for two', + }) + .option('three', { + default: undefined, + type: 'array', + alias: 't', + desc: 'text for three', + nargs: 1, + requiresArg: true, + }) + .version(helpers.cliVersion()) + .demandCommand(1, '') + .recommendCommands() + .help() + .alias('h', 'help') + .epilogue( + 'If your app has a single stack, there is no need to specify the stack name\\n\\nIf one of cdk.json or ~/.cdk.json exists, options specified there will be used as defaults. Settings in cdk.json take precedence.' + ) + .parse(args); + } // eslint-disable-next-line @typescript-eslint/no-require-imports + const yargs = require('yargs'); + " `); }); @@ -91,42 +91,42 @@ const yargs = require('yargs'); }; expect(await renderYargs(config, YARGS_HELPERS)).toMatchInlineSnapshot(` -"// ------------------------------------------------------------------------------------------- -// 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/comma-dangle, @stylistic/comma-spacing, @stylistic/max-len, @stylistic/quotes, @stylistic/quote-props */ -import { Argv } from 'yargs'; -import * as helpers from './util/yargs-helpers'; + "// ------------------------------------------------------------------------------------------- + // 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/comma-dangle, @stylistic/comma-spacing, @stylistic/max-len, @stylistic/quotes, @stylistic/quote-props */ + import { Argv } from 'yargs'; + import * as helpers from './util/yargs-helpers'; -// @ts-ignore TS6133 -export function parseCommandLineArguments(args: Array): any { - return yargs - .env('CDK') - .usage('Usage: cdk -a COMMAND') - .command('test', 'the action under test', (yargs: Argv) => - yargs - .option('one', { - default: undefined, - type: 'boolean', - alias: 'o', - desc: 'text for one', - }) - .option('O', { type: 'boolean', hidden: true }) - .middleware(helpers.yargsNegativeAlias('O', 'one'), true) - ) - .version(helpers.cliVersion()) - .demandCommand(1, '') - .recommendCommands() - .help() - .alias('h', 'help') - .epilogue( - 'If your app has a single stack, there is no need to specify the stack name\\n\\nIf one of cdk.json or ~/.cdk.json exists, options specified there will be used as defaults. Settings in cdk.json take precedence.' - ) - .parse(args); -} // eslint-disable-next-line @typescript-eslint/no-require-imports -const yargs = require('yargs'); -" + // @ts-ignore TS6133 + export function parseCommandLineArguments(args: Array): any { + return yargs + .env('CDK') + .usage('Usage: cdk -a COMMAND') + .command('test', 'the action under test', (yargs: Argv) => + yargs + .option('one', { + default: undefined, + type: 'boolean', + alias: 'o', + desc: 'text for one', + }) + .option('O', { type: 'boolean', hidden: true }) + .middleware(helpers.yargsNegativeAlias('O', 'one'), true) + ) + .version(helpers.cliVersion()) + .demandCommand(1, '') + .recommendCommands() + .help() + .alias('h', 'help') + .epilogue( + 'If your app has a single stack, there is no need to specify the stack name\\n\\nIf one of cdk.json or ~/.cdk.json exists, options specified there will be used as defaults. Settings in cdk.json take precedence.' + ) + .parse(args); + } // eslint-disable-next-line @typescript-eslint/no-require-imports + const yargs = require('yargs'); + " `); }); From 2a6c63788bea8a9ed07c8abc19815bf60ae8e838 Mon Sep 17 00:00:00 2001 From: Kaizen Conroy Date: Mon, 23 Dec 2024 15:52:07 -0500 Subject: [PATCH 03/11] fix defaults --- packages/aws-cdk/lib/cli-arguments.ts | 34 ++++----- .../lib/parse-command-line-arguments.ts | 44 +++++------ .../@aws-cdk/cli-args-gen/lib/cli-type-gen.ts | 9 ++- tools/@aws-cdk/cli-args-gen/lib/yargs-gen.ts | 12 +-- .../cli-args-gen/test/cli-type-gen.test.ts | 75 +++++++++++-------- .../cli-args-gen/test/yargs-gen.test.ts | 12 +-- 6 files changed, 100 insertions(+), 86 deletions(-) diff --git a/packages/aws-cdk/lib/cli-arguments.ts b/packages/aws-cdk/lib/cli-arguments.ts index 4a475017ca8b9..1c3a1ab0bbef7 100644 --- a/packages/aws-cdk/lib/cli-arguments.ts +++ b/packages/aws-cdk/lib/cli-arguments.ts @@ -297,7 +297,7 @@ export interface GlobalOptions { /** * Opt in to unstable features. The flag indicates that the scope and API of a feature might still change. Otherwise the feature is generally production ready and fully supported. Can be specified multiple times. * - * @default - undefined + * @default - [] */ readonly unstable?: Array; } @@ -429,7 +429,7 @@ export interface BootstrapOptions { * * aliases: t * - * @default - undefined + * @default - [] */ readonly tags?: Array; @@ -443,21 +443,21 @@ export interface BootstrapOptions { /** * The AWS account IDs that should be trusted to perform deployments into this environment (may be repeated, modern bootstrapping only) * - * @default - undefined + * @default - [] */ readonly trust?: Array; /** * The AWS account IDs that should be trusted to look up values in this environment (may be repeated, modern bootstrapping only) * - * @default - undefined + * @default - [] */ readonly 'trust-for-lookup'?: Array; /** * The Managed Policy ARNs that should be attached to the role performing deployments into this environment (may be repeated, modern bootstrapping only) * - * @default - undefined + * @default - [] */ readonly 'cloudformation-execution-policies'?: Array; @@ -515,28 +515,28 @@ export interface GcOptions { /** * The action (or sub-action) you want to perform. Valid entires are "print", "tag", "delete-tagged", "full". * - * @default - full + * @default - "full" */ readonly action?: string; /** * Specify either ecr, s3, or all * - * @default - all + * @default - "all" */ readonly type?: string; /** * Delete assets that have been marked as isolated for this many days * - * @default - undefined + * @default - 0 */ readonly 'rollback-buffer-days'?: number; /** * Never delete assets younger than this (in days) * - * @default - undefined + * @default - 1 */ readonly 'created-buffer-days'?: number; @@ -573,7 +573,7 @@ export interface DeployOptions { * * aliases: E * - * @default - undefined + * @default - [] */ readonly 'build-exclude'?: Array; @@ -645,7 +645,7 @@ export interface DeployOptions { /** * Additional parameters passed to CloudFormation at deploy time (STACK:KEY=VALUE) * - * @default - undefined + * @default - {} */ readonly parameters?: Array; @@ -717,7 +717,7 @@ export interface DeployOptions { /** * Maximum number of simultaneous deployments (dependency permitting) to execute. * - * @default - undefined + * @default - 1 */ readonly concurrency?: number; @@ -782,7 +782,7 @@ export interface RollbackOptions { /** * Orphan the given resources, identified by their logical ID (can be specified multiple times) * - * @default - undefined + * @default - [] */ readonly orphan?: Array; } @@ -860,7 +860,7 @@ export interface WatchOptions { * * aliases: E * - * @default - undefined + * @default - [] */ readonly 'build-exclude'?: Array; @@ -934,7 +934,7 @@ export interface WatchOptions { /** * Maximum number of simultaneous deployments (dependency permitting) to execute. * - * @default - undefined + * @default - 1 */ readonly concurrency?: number; } @@ -989,7 +989,7 @@ export interface DiffOptions { /** * Number of context lines to include in arbitrary JSON diff rendering * - * @default - undefined + * @default - 3 */ readonly 'context-lines'?: number; @@ -1129,7 +1129,7 @@ export interface MigrateOptions { * * aliases: l * - * @default - typescript + * @default - "typescript" */ readonly language?: string; diff --git a/packages/aws-cdk/lib/parse-command-line-arguments.ts b/packages/aws-cdk/lib/parse-command-line-arguments.ts index 96b4bf81285b0..d0b8d70c0fdfe 100644 --- a/packages/aws-cdk/lib/parse-command-line-arguments.ts +++ b/packages/aws-cdk/lib/parse-command-line-arguments.ts @@ -2,7 +2,7 @@ // 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/comma-dangle, @stylistic/comma-spacing, @stylistic/max-len, @stylistic/quotes, @stylistic/quote-props */ +/* eslint-disable max-len */ import { Argv } from 'yargs'; import * as helpers from './util/yargs-helpers'; @@ -24,7 +24,7 @@ export function parseCommandLineArguments(args: Array): any { desc: 'Command-line for a pre-synth build', }) .option('context', { - default: undefined, + default: [], type: 'array', alias: 'c', desc: 'Add contextual string parameter (KEY=VALUE)', @@ -32,7 +32,7 @@ export function parseCommandLineArguments(args: Array): any { requiresArg: true, }) .option('plugin', { - default: undefined, + default: [], type: 'array', alias: 'p', desc: 'Name or path of a node package that extend the CDK features. Can be specified multiple times', @@ -170,7 +170,7 @@ export function parseCommandLineArguments(args: Array): any { type: 'boolean', alias: 'd', desc: 'Display stack dependency information for each stack', - }) + }), ) .command(['synthesize [STACKS..]', 'synth [STACKS..]'], 'Synthesizes and prints the CloudFormation template for this stack', (yargs: Argv) => yargs @@ -190,7 +190,7 @@ export function parseCommandLineArguments(args: Array): any { type: 'boolean', alias: 'q', desc: 'Do not output CloudFormation Template to stdout', - }) + }), ) .command('bootstrap [ENVIRONMENTS..]', 'Deploys the CDK toolkit stack into an AWS environment', (yargs: Argv) => yargs @@ -302,7 +302,7 @@ export function parseCommandLineArguments(args: Array): any { default: true, type: 'boolean', desc: 'Use previous values for existing parameters (you must specify all parameters on every deployment if this is disabled)', - }) + }), ) .command( 'gc [ENVIRONMENTS..]', @@ -339,7 +339,7 @@ export function parseCommandLineArguments(args: Array): any { type: 'string', desc: 'The name of the CDK toolkit stack, if different from the default "CDKToolkit"', requiresArg: true, - }) + }), ) .command('deploy [STACKS..]', 'Deploys the stack(s) named STACKS into your AWS account', (yargs: Argv) => yargs @@ -369,14 +369,14 @@ export function parseCommandLineArguments(args: Array): any { desc: 'What security-sensitive changes need manual approval', }) .option('notification-arns', { - default: undefined, + default: [], type: 'array', desc: "ARNs of SNS topics that CloudFormation will notify with stack related events. These will be added to ARNs specified with the 'notificationArns' stack property.", nargs: 1, requiresArg: true, }) .option('tags', { - default: undefined, + default: [], type: 'array', alias: 't', desc: 'Tags to add to the stack (KEY=VALUE), overrides tags from Cloud Assembly (deprecated)', @@ -486,7 +486,7 @@ export function parseCommandLineArguments(args: Array): any { default: false, type: 'boolean', desc: 'Whether to deploy if the app contains no stacks', - }) + }), ) .command('rollback [STACKS..]', 'Rolls back the stack(s) named STACKS to their last stable state', (yargs: Argv) => yargs @@ -518,7 +518,7 @@ export function parseCommandLineArguments(args: Array): any { desc: 'Orphan the given resources, identified by their logical ID (can be specified multiple times)', nargs: 1, requiresArg: true, - }) + }), ) .command('import [STACK]', 'Import existing resource(s) into the given STACK', (yargs: Argv) => yargs @@ -562,7 +562,7 @@ export function parseCommandLineArguments(args: Array): any { alias: 'm', requiresArg: true, desc: 'If specified, CDK will use the given file to map physical resources to CDK resources for import, instead of interactively asking the user. Can be run from scripts', - }) + }), ) .command('watch [STACKS..]', "Shortcut for 'deploy --watch'", (yargs: Argv) => yargs @@ -630,7 +630,7 @@ export function parseCommandLineArguments(args: Array): any { type: 'number', desc: 'Maximum number of simultaneous deployments (dependency permitting) to execute.', requiresArg: true, - }) + }), ) .command('destroy [STACKS..]', 'Destroy the stack(s) named STACKS', (yargs: Argv) => yargs @@ -650,7 +650,7 @@ export function parseCommandLineArguments(args: Array): any { type: 'boolean', alias: 'f', desc: 'Do not ask for confirmation before destroying the stacks', - }) + }), ) .command( 'diff [STACKS..]', @@ -706,7 +706,7 @@ export function parseCommandLineArguments(args: Array): any { type: 'boolean', alias: 'changeset', desc: 'Whether to create a changeset to analyze resource replacements. In this mode, diff will use the deploy role instead of the lookup role.', - }) + }), ) .command('metadata [STACK]', 'Returns all metadata associated with this stack') .command(['acknowledge [ID]', 'ack [ID]'], 'Acknowledge a notice so that it does not show up anymore') @@ -716,7 +716,7 @@ export function parseCommandLineArguments(args: Array): any { type: 'boolean', alias: 'u', desc: 'Returns a list of unacknowledged notices', - }) + }), ) .command('init [TEMPLATE]', 'Create a new, empty CDK project from a template.', (yargs: Argv) => yargs @@ -736,7 +736,7 @@ export function parseCommandLineArguments(args: Array): any { default: false, type: 'boolean', desc: 'If true, only generates project files, without executing additional operations such as setting up a git repo, installing dependencies or compiling the project', - }) + }), ) .command('migrate', 'Migrate existing AWS resources into a CDK app', (yargs: Argv) => yargs @@ -785,7 +785,7 @@ export function parseCommandLineArguments(args: Array): any { desc: 'Determines if a new scan should be created, or the last successful existing scan should be used \n options are "new" or "most-recent"', }) .option('filter', { - default: undefined, + default: [], type: 'array', desc: 'Filters the resource scan based on the provided criteria in the following format: "key1=value1,key2=value2"\n This field can be passed multiple times for OR style filtering: \n filtering options: \n resource-identifier: A key-value pair that identifies the target resource. i.e. {"ClusterName", "myCluster"}\n resource-type-prefix: A string that represents a type-name prefix. i.e. "AWS::DynamoDB::"\n tag-key: a string that matches resources with at least one tag with the provided key. i.e. "myTagKey"\n tag-value: a string that matches resources with at least one tag with the provided value. i.e. "myTagValue"', nargs: 1, @@ -795,7 +795,7 @@ export function parseCommandLineArguments(args: Array): any { default: undefined, type: 'boolean', desc: 'Use this flag to zip the generated CDK app', - }) + }), ) .command('context', 'Manage cached context values', (yargs: Argv) => yargs @@ -816,7 +816,7 @@ export function parseCommandLineArguments(args: Array): any { default: undefined, desc: 'Clear all context', type: 'boolean', - }) + }), ) .command(['docs', 'doc'], 'Opens the reference documentation in a browser', (yargs: Argv) => yargs.option('browser', { @@ -824,7 +824,7 @@ export function parseCommandLineArguments(args: Array): any { alias: 'b', desc: 'the command to use to open the browser, using %u as a placeholder for the path of the file to open', type: 'string', - }) + }), ) .command('doctor', 'Check your set-up for potential problems') .version(helpers.cliVersion()) @@ -833,7 +833,7 @@ export function parseCommandLineArguments(args: Array): any { .help() .alias('h', 'help') .epilogue( - 'If your app has a single stack, there is no need to specify the stack name\n\nIf one of cdk.json or ~/.cdk.json exists, options specified there will be used as defaults. Settings in cdk.json take precedence.' + 'If your app has a single stack, there is no need to specify the stack name\n\nIf one of cdk.json or ~/.cdk.json exists, options specified there will be used as defaults. Settings in cdk.json take precedence.', ) .parse(args); } // eslint-disable-next-line @typescript-eslint/no-require-imports diff --git a/tools/@aws-cdk/cli-args-gen/lib/cli-type-gen.ts b/tools/@aws-cdk/cli-args-gen/lib/cli-type-gen.ts index 7c92fd8c65fd4..923d01bd09128 100644 --- a/tools/@aws-cdk/cli-args-gen/lib/cli-type-gen.ts +++ b/tools/@aws-cdk/cli-args-gen/lib/cli-type-gen.ts @@ -130,8 +130,13 @@ function kebabToPascal(str: string): string { } function normalizeDefault(defaultValue: any): string { - if (typeof defaultValue === 'boolean' || typeof defaultValue === 'string') { - return String(defaultValue); + // eslint-disable-next-line no-console + console.log(defaultValue, typeof defaultValue); + const validDefaults = ['boolean', 'string', 'number', 'object']; + if (validDefaults.includes(typeof defaultValue)) { + return JSON.stringify(defaultValue); } + + // We don't know what this default is, but it's likely one of these: 'YARGS_HELPERS.isCI()' return 'undefined'; } diff --git a/tools/@aws-cdk/cli-args-gen/lib/yargs-gen.ts b/tools/@aws-cdk/cli-args-gen/lib/yargs-gen.ts index fe2f4fdbff746..9560a20c6aee8 100644 --- a/tools/@aws-cdk/cli-args-gen/lib/yargs-gen.ts +++ b/tools/@aws-cdk/cli-args-gen/lib/yargs-gen.ts @@ -1,4 +1,5 @@ import { $E, Expression, ExternalModule, FreeFunction, IScope, Module, SelectiveModuleImport, Statement, ThingSymbol, Type, TypeScriptRenderer, code, expr } from '@cdklabs/typewriter'; +import { EsLintRules } from '@cdklabs/typewriter/lib/eslint-rules'; import * as prettier from 'prettier'; import { CliConfig, CliOption, YargsOption } from './yargs-types'; @@ -45,19 +46,14 @@ export async function renderYargs(config: CliConfig, helpers: CliHelpers): Promi parseCommandLineArguments.addBody(makeYargs(config, helpers)); const ts = new TypeScriptRenderer({ - disabledEsLintRules: [ - '@stylistic/comma-dangle', - '@stylistic/comma-spacing', - '@stylistic/max-len', - '@stylistic/quotes', - '@stylistic/quote-props', - ] as any, // Force our string[] into EsLintRules[], it will work out at runtime + disabledEsLintRules: [EsLintRules.MAX_LEN], // the default disabled rules result in 'Definition for rule 'prettier/prettier' was not found' }).render(scope); return prettier.format(ts, { parser: 'typescript', printWidth: 150, singleQuote: true, + trailingComma: 'all', }); } @@ -117,7 +113,7 @@ function makeOptions(prefix: Expression, options: { [optionName: string]: CliOpt let optionsExpr = prefix; for (const option of Object.keys(options)) { const theOption: CliOption = { - default: undefined, // make the default explicit (overridden if the option includes an actual default) + default: options[option].type === 'array' ? [] : undefined, // make the default explicit (overridden if the option includes an actual default) ...options[option], }; const optionProps: YargsOption = cloneDeep(theOption); diff --git a/tools/@aws-cdk/cli-args-gen/test/cli-type-gen.test.ts b/tools/@aws-cdk/cli-args-gen/test/cli-type-gen.test.ts index c3719aa4b9149..ca339d205943a 100644 --- a/tools/@aws-cdk/cli-args-gen/test/cli-type-gen.test.ts +++ b/tools/@aws-cdk/cli-args-gen/test/cli-type-gen.test.ts @@ -13,6 +13,12 @@ describe('render', () => { desc: 'Enable debug logging', default: false, }, + context: { + default: [], + type: 'array', + alias: 'c', + desc: 'context values', + }, }, commands: { deploy: { @@ -37,62 +43,69 @@ describe('render', () => { import { Command } from './settings'; /** - * The structure of the CLI configuration, generated from packages/aws-cdk/lib/config.ts - * - * @struct - */ + * The structure of the CLI configuration, generated from packages/aws-cdk/lib/config.ts + * + * @struct + */ export interface CliArguments { /** - * The CLI command name followed by any properties of the command - */ + * The CLI command name followed by any properties of the command + */ readonly _: [Command, ...string[]]; /** - * Global options available to all CLI commands - */ + * Global options available to all CLI commands + */ readonly globalOptions?: GlobalOptions; /** - * Deploy a stack - */ + * Deploy a stack + */ readonly deploy?: DeployOptions; } /** - * Global options available to all CLI commands - * - * @struct - */ + * Global options available to all CLI commands + * + * @struct + */ export interface GlobalOptions { /** - * REQUIRED: Command-line for executing your app - * - * @default - undefined - */ + * REQUIRED: Command-line for executing your app + * + * @default - undefined + */ readonly app?: string; /** - * Enable debug logging - * - * @default - false - */ + * Enable debug logging + * + * @default - false + */ readonly debug?: boolean; + + /** + * context values + * + * @default - [] + */ + readonly context?: Array; } /** - * Deploy a stack - * - * @struct - */ + * Deploy a stack + * + * @struct + */ export interface DeployOptions { /** - * Deploy all stacks - * - * @default - false - */ + * Deploy all stacks + * + * @default - false + */ readonly all?: boolean; } " - `); +`); }); }); diff --git a/tools/@aws-cdk/cli-args-gen/test/yargs-gen.test.ts b/tools/@aws-cdk/cli-args-gen/test/yargs-gen.test.ts index d946030297a91..e423ecc703ca2 100644 --- a/tools/@aws-cdk/cli-args-gen/test/yargs-gen.test.ts +++ b/tools/@aws-cdk/cli-args-gen/test/yargs-gen.test.ts @@ -28,7 +28,7 @@ describe('render', () => { // 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/comma-dangle, @stylistic/comma-spacing, @stylistic/max-len, @stylistic/quotes, @stylistic/quote-props */ + /* eslint-disable max-len */ import { Argv } from 'yargs'; import * as helpers from './util/yargs-helpers'; @@ -50,7 +50,7 @@ describe('render', () => { desc: 'text for two', }) .option('three', { - default: undefined, + default: [], type: 'array', alias: 't', desc: 'text for three', @@ -63,7 +63,7 @@ describe('render', () => { .help() .alias('h', 'help') .epilogue( - 'If your app has a single stack, there is no need to specify the stack name\\n\\nIf one of cdk.json or ~/.cdk.json exists, options specified there will be used as defaults. Settings in cdk.json take precedence.' + 'If your app has a single stack, there is no need to specify the stack name\\n\\nIf one of cdk.json or ~/.cdk.json exists, options specified there will be used as defaults. Settings in cdk.json take precedence.', ) .parse(args); } // eslint-disable-next-line @typescript-eslint/no-require-imports @@ -95,7 +95,7 @@ describe('render', () => { // 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/comma-dangle, @stylistic/comma-spacing, @stylistic/max-len, @stylistic/quotes, @stylistic/quote-props */ + /* eslint-disable max-len */ import { Argv } from 'yargs'; import * as helpers from './util/yargs-helpers'; @@ -113,7 +113,7 @@ describe('render', () => { desc: 'text for one', }) .option('O', { type: 'boolean', hidden: true }) - .middleware(helpers.yargsNegativeAlias('O', 'one'), true) + .middleware(helpers.yargsNegativeAlias('O', 'one'), true), ) .version(helpers.cliVersion()) .demandCommand(1, '') @@ -121,7 +121,7 @@ describe('render', () => { .help() .alias('h', 'help') .epilogue( - 'If your app has a single stack, there is no need to specify the stack name\\n\\nIf one of cdk.json or ~/.cdk.json exists, options specified there will be used as defaults. Settings in cdk.json take precedence.' + 'If your app has a single stack, there is no need to specify the stack name\\n\\nIf one of cdk.json or ~/.cdk.json exists, options specified there will be used as defaults. Settings in cdk.json take precedence.', ) .parse(args); } // eslint-disable-next-line @typescript-eslint/no-require-imports From dc6f1f9a3abb14d44a9af280404d5c19045e5b4d Mon Sep 17 00:00:00 2001 From: Kaizen Conroy Date: Mon, 23 Dec 2024 15:55:47 -0500 Subject: [PATCH 04/11] remove prints --- tools/@aws-cdk/cli-args-gen/lib/cli-type-gen.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/@aws-cdk/cli-args-gen/lib/cli-type-gen.ts b/tools/@aws-cdk/cli-args-gen/lib/cli-type-gen.ts index 923d01bd09128..120b047ff8058 100644 --- a/tools/@aws-cdk/cli-args-gen/lib/cli-type-gen.ts +++ b/tools/@aws-cdk/cli-args-gen/lib/cli-type-gen.ts @@ -130,8 +130,6 @@ function kebabToPascal(str: string): string { } function normalizeDefault(defaultValue: any): string { - // eslint-disable-next-line no-console - console.log(defaultValue, typeof defaultValue); const validDefaults = ['boolean', 'string', 'number', 'object']; if (validDefaults.includes(typeof defaultValue)) { return JSON.stringify(defaultValue); From 66cfea0dfd4ebf7f5a7c4303b727a59c162ff993 Mon Sep 17 00:00:00 2001 From: Kaizen Conroy Date: Mon, 23 Dec 2024 16:03:04 -0500 Subject: [PATCH 05/11] fix cli-args-gen defaults --- packages/aws-cdk/lib/cli-arguments.ts | 10 +-- .../@aws-cdk/cli-args-gen/lib/cli-type-gen.ts | 10 +-- .../cli-args-gen/test/cli-type-gen.test.ts | 79 +++++++++++-------- 3 files changed, 55 insertions(+), 44 deletions(-) diff --git a/packages/aws-cdk/lib/cli-arguments.ts b/packages/aws-cdk/lib/cli-arguments.ts index 1c3a1ab0bbef7..ae9f4bc1c658b 100644 --- a/packages/aws-cdk/lib/cli-arguments.ts +++ b/packages/aws-cdk/lib/cli-arguments.ts @@ -143,14 +143,14 @@ export interface GlobalOptions { /** * Add contextual string parameter (KEY=VALUE) * - * @default - undefined + * @default - [] */ readonly context?: Array; /** * Name or path of a node package that extend the CDK features. Can be specified multiple times * - * @default - undefined + * @default - [] */ readonly plugin?: Array; @@ -596,7 +596,7 @@ export interface DeployOptions { /** * ARNs of SNS topics that CloudFormation will notify with stack related events. These will be added to ARNs specified with the 'notificationArns' stack property. * - * @default - undefined + * @default - [] */ readonly 'notification-arns'?: Array; @@ -605,7 +605,7 @@ export interface DeployOptions { * * aliases: t * - * @default - undefined + * @default - [] */ readonly tags?: Array; @@ -1185,7 +1185,7 @@ export interface MigrateOptions { * tag-key: a string that matches resources with at least one tag with the provided key. i.e. "myTagKey" * tag-value: a string that matches resources with at least one tag with the provided value. i.e. "myTagValue" * - * @default - undefined + * @default - [] */ readonly filter?: Array; diff --git a/tools/@aws-cdk/cli-args-gen/lib/cli-type-gen.ts b/tools/@aws-cdk/cli-args-gen/lib/cli-type-gen.ts index 120b047ff8058..9579d3cda581f 100644 --- a/tools/@aws-cdk/cli-args-gen/lib/cli-type-gen.ts +++ b/tools/@aws-cdk/cli-args-gen/lib/cli-type-gen.ts @@ -44,7 +44,7 @@ export async function renderCliType(config: CliConfig): Promise { name: optionName, type: convertType(option.type), docs: { - default: normalizeDefault(option.default), + default: normalizeDefault(option.default, option.type), summary: option.desc, deprecated: option.deprecated ? String(option.deprecated) : undefined, }, @@ -76,7 +76,7 @@ export async function renderCliType(config: CliConfig): Promise { name: optionName, type: convertType(option.type), docs: { - default: normalizeDefault(option.default), + default: normalizeDefault(option.default, option.type), summary: option.desc, deprecated: option.deprecated ? String(option.deprecated) : undefined, remarks: option.alias ? `aliases: ${Array.isArray(option.alias) ? option.alias.join(' ') : option.alias}` : undefined, @@ -129,12 +129,12 @@ function kebabToPascal(str: string): string { .join(''); } -function normalizeDefault(defaultValue: any): string { +function normalizeDefault(defaultValue: any, type: string): string { const validDefaults = ['boolean', 'string', 'number', 'object']; if (validDefaults.includes(typeof defaultValue)) { return JSON.stringify(defaultValue); } - // We don't know what this default is, but it's likely one of these: 'YARGS_HELPERS.isCI()' - return 'undefined'; + // We don't know what the default is, and only arrays get a special default + return type === 'array' ? '[]' : 'undefined'; } diff --git a/tools/@aws-cdk/cli-args-gen/test/cli-type-gen.test.ts b/tools/@aws-cdk/cli-args-gen/test/cli-type-gen.test.ts index ca339d205943a..d4a016fc811d3 100644 --- a/tools/@aws-cdk/cli-args-gen/test/cli-type-gen.test.ts +++ b/tools/@aws-cdk/cli-args-gen/test/cli-type-gen.test.ts @@ -19,6 +19,10 @@ describe('render', () => { alias: 'c', desc: 'context values', }, + plugin: { + type: 'array', + desc: 'plugins to load', + }, }, commands: { deploy: { @@ -43,66 +47,73 @@ describe('render', () => { import { Command } from './settings'; /** - * The structure of the CLI configuration, generated from packages/aws-cdk/lib/config.ts - * - * @struct - */ + * The structure of the CLI configuration, generated from packages/aws-cdk/lib/config.ts + * + * @struct + */ export interface CliArguments { /** - * The CLI command name followed by any properties of the command - */ + * The CLI command name followed by any properties of the command + */ readonly _: [Command, ...string[]]; /** - * Global options available to all CLI commands - */ + * Global options available to all CLI commands + */ readonly globalOptions?: GlobalOptions; /** - * Deploy a stack - */ + * Deploy a stack + */ readonly deploy?: DeployOptions; } /** - * Global options available to all CLI commands - * - * @struct - */ + * Global options available to all CLI commands + * + * @struct + */ export interface GlobalOptions { /** - * REQUIRED: Command-line for executing your app - * - * @default - undefined - */ + * REQUIRED: Command-line for executing your app + * + * @default - undefined + */ readonly app?: string; /** - * Enable debug logging - * - * @default - false - */ + * Enable debug logging + * + * @default - false + */ readonly debug?: boolean; /** - * context values - * - * @default - [] - */ + * context values + * + * @default - [] + */ readonly context?: Array; + + /** + * plugins to load + * + * @default - [] + */ + readonly plugin?: Array; } /** - * Deploy a stack - * - * @struct - */ + * Deploy a stack + * + * @struct + */ export interface DeployOptions { /** - * Deploy all stacks - * - * @default - false - */ + * Deploy all stacks + * + * @default - false + */ readonly all?: boolean; } " From 339abe1afb842227ba229cb407e041f030343b1d Mon Sep 17 00:00:00 2001 From: Kaizen Conroy Date: Mon, 23 Dec 2024 16:13:02 -0500 Subject: [PATCH 06/11] refactor --- tools/@aws-cdk/cli-args-gen/lib/cli-type-gen.ts | 4 +++- tools/@aws-cdk/cli-args-gen/lib/util.ts | 3 +++ tools/@aws-cdk/cli-args-gen/lib/yargs-gen.ts | 3 ++- 3 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 tools/@aws-cdk/cli-args-gen/lib/util.ts diff --git a/tools/@aws-cdk/cli-args-gen/lib/cli-type-gen.ts b/tools/@aws-cdk/cli-args-gen/lib/cli-type-gen.ts index 9579d3cda581f..f0527fad55483 100644 --- a/tools/@aws-cdk/cli-args-gen/lib/cli-type-gen.ts +++ b/tools/@aws-cdk/cli-args-gen/lib/cli-type-gen.ts @@ -1,6 +1,7 @@ import { Module, SelectiveModuleImport, StructType, Type, TypeScriptRenderer } from '@cdklabs/typewriter'; import { EsLintRules } from '@cdklabs/typewriter/lib/eslint-rules'; import * as prettier from 'prettier'; +import { generateDefault } from './util'; import { CliConfig } from './yargs-types'; export async function renderCliType(config: CliConfig): Promise { @@ -136,5 +137,6 @@ function normalizeDefault(defaultValue: any, type: string): string { } // We don't know what the default is, and only arrays get a special default - return type === 'array' ? '[]' : 'undefined'; + const generatedDefault = generateDefault(type); + return generatedDefault ? JSON.stringify(generatedDefault) : 'undefined'; } diff --git a/tools/@aws-cdk/cli-args-gen/lib/util.ts b/tools/@aws-cdk/cli-args-gen/lib/util.ts new file mode 100644 index 0000000000000..047c2498283c6 --- /dev/null +++ b/tools/@aws-cdk/cli-args-gen/lib/util.ts @@ -0,0 +1,3 @@ +export function generateDefault(type: string) { + return type === 'array' ? [] : undefined; +} diff --git a/tools/@aws-cdk/cli-args-gen/lib/yargs-gen.ts b/tools/@aws-cdk/cli-args-gen/lib/yargs-gen.ts index 9560a20c6aee8..9f3929200f939 100644 --- a/tools/@aws-cdk/cli-args-gen/lib/yargs-gen.ts +++ b/tools/@aws-cdk/cli-args-gen/lib/yargs-gen.ts @@ -1,6 +1,7 @@ import { $E, Expression, ExternalModule, FreeFunction, IScope, Module, SelectiveModuleImport, Statement, ThingSymbol, Type, TypeScriptRenderer, code, expr } from '@cdklabs/typewriter'; import { EsLintRules } from '@cdklabs/typewriter/lib/eslint-rules'; import * as prettier from 'prettier'; +import { generateDefault } from './util'; import { CliConfig, CliOption, YargsOption } from './yargs-types'; // to import lodash.clonedeep properly, we would need to set esModuleInterop: true @@ -113,7 +114,7 @@ function makeOptions(prefix: Expression, options: { [optionName: string]: CliOpt let optionsExpr = prefix; for (const option of Object.keys(options)) { const theOption: CliOption = { - default: options[option].type === 'array' ? [] : undefined, // make the default explicit (overridden if the option includes an actual default) + default: generateDefault(options[option].type), // make the default explicit (overridden if the option includes an actual default) ...options[option], }; const optionProps: YargsOption = cloneDeep(theOption); From 7deb21720a694d3a0ea3d0a5e62e4df5bfc57db5 Mon Sep 17 00:00:00 2001 From: Kaizen Conroy Date: Tue, 24 Dec 2024 15:33:04 -0500 Subject: [PATCH 07/11] finally the right config --- packages/aws-cdk/lib/parse-command-line-arguments.ts | 2 -- tools/@aws-cdk/cli-args-gen/lib/yargs-gen.ts | 5 ++++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/aws-cdk/lib/parse-command-line-arguments.ts b/packages/aws-cdk/lib/parse-command-line-arguments.ts index e09f5c674f7dd..37443fc6a713b 100644 --- a/packages/aws-cdk/lib/parse-command-line-arguments.ts +++ b/packages/aws-cdk/lib/parse-command-line-arguments.ts @@ -369,7 +369,6 @@ export function parseCommandLineArguments(args: Array): any { desc: 'What security-sensitive changes need manual approval', }) .option('notification-arns', { - default: [], type: 'array', desc: "ARNs of SNS topics that CloudFormation will notify with stack related events. These will be added to ARNs specified with the 'notificationArns' stack property.", nargs: 1, @@ -805,7 +804,6 @@ export function parseCommandLineArguments(args: Array): any { desc: 'The context key (or its index) to reset', type: 'string', requiresArg: true, - default: undefined, }) .option('force', { default: false, diff --git a/tools/@aws-cdk/cli-args-gen/lib/yargs-gen.ts b/tools/@aws-cdk/cli-args-gen/lib/yargs-gen.ts index 9f3929200f939..fee7fdaa61e3d 100644 --- a/tools/@aws-cdk/cli-args-gen/lib/yargs-gen.ts +++ b/tools/@aws-cdk/cli-args-gen/lib/yargs-gen.ts @@ -114,7 +114,10 @@ function makeOptions(prefix: Expression, options: { [optionName: string]: CliOpt let optionsExpr = prefix; for (const option of Object.keys(options)) { const theOption: CliOption = { - default: generateDefault(options[option].type), // make the default explicit (overridden if the option includes an actual default) + // Make the default explicit (overridden if the option includes an actual default) + // 'notification-arns' is a special snowflake that should be defaulted to 'undefined', but https://github.com/yargs/yargs/issues/2443 + // prevents us from doing so. This should be changed if the issue is resolved. + ...(option === 'notification-arns' ? {} : { default: generateDefault(options[option].type) }), ...options[option], }; const optionProps: YargsOption = cloneDeep(theOption); From 499f3da060b97847f68958f0b220800fa1db83d2 Mon Sep 17 00:00:00 2001 From: Kaizen Conroy Date: Tue, 24 Dec 2024 16:23:53 -0500 Subject: [PATCH 08/11] special cli-argument too --- packages/aws-cdk/lib/cli-arguments.ts | 2 +- .../@aws-cdk/cli-args-gen/lib/cli-type-gen.ts | 20 +++++++++++-------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/packages/aws-cdk/lib/cli-arguments.ts b/packages/aws-cdk/lib/cli-arguments.ts index 97990b1c773a1..410a5f6876bdb 100644 --- a/packages/aws-cdk/lib/cli-arguments.ts +++ b/packages/aws-cdk/lib/cli-arguments.ts @@ -596,7 +596,7 @@ export interface DeployOptions { /** * ARNs of SNS topics that CloudFormation will notify with stack related events. These will be added to ARNs specified with the 'notificationArns' stack property. * - * @default - [] + * @default - undefined */ readonly 'notification-arns'?: Array; diff --git a/tools/@aws-cdk/cli-args-gen/lib/cli-type-gen.ts b/tools/@aws-cdk/cli-args-gen/lib/cli-type-gen.ts index f0527fad55483..3ddb66569c4c2 100644 --- a/tools/@aws-cdk/cli-args-gen/lib/cli-type-gen.ts +++ b/tools/@aws-cdk/cli-args-gen/lib/cli-type-gen.ts @@ -77,7 +77,8 @@ export async function renderCliType(config: CliConfig): Promise { name: optionName, type: convertType(option.type), docs: { - default: normalizeDefault(option.default, option.type), + // Notification Arns is a special property where undefined and [] mean different things + default: optionName === 'notification-arns' ? 'undefined' : normalizeDefault(option.default, option.type), summary: option.desc, deprecated: option.deprecated ? String(option.deprecated) : undefined, remarks: option.alias ? `aliases: ${Array.isArray(option.alias) ? option.alias.join(' ') : option.alias}` : undefined, @@ -131,12 +132,15 @@ function kebabToPascal(str: string): string { } function normalizeDefault(defaultValue: any, type: string): string { - const validDefaults = ['boolean', 'string', 'number', 'object']; - if (validDefaults.includes(typeof defaultValue)) { - return JSON.stringify(defaultValue); - } + switch (typeof defaultValue) { + case 'boolean': + case 'string': + case 'number': + case 'object': + return JSON.stringify(defaultValue); - // We don't know what the default is, and only arrays get a special default - const generatedDefault = generateDefault(type); - return generatedDefault ? JSON.stringify(generatedDefault) : 'undefined'; + default: + const generatedDefault = generateDefault(type); + return generatedDefault ? JSON.stringify(generatedDefault) : 'undefined'; + } } From 1c6d25aad6f808bdfda0b21bd2a05e860fa97ba9 Mon Sep 17 00:00:00 2001 From: Kaizen Conroy Date: Tue, 24 Dec 2024 16:38:12 -0500 Subject: [PATCH 09/11] update cli-type-gen --- .../@aws-cdk/cli-args-gen/lib/cli-type-gen.ts | 4 + .../cli-args-gen/test/cli-type-gen.test.ts | 81 +++++++++++++++++++ .../cli-args-gen/test/yargs-gen.test.ts | 65 +++++++++++++++ 3 files changed, 150 insertions(+) diff --git a/tools/@aws-cdk/cli-args-gen/lib/cli-type-gen.ts b/tools/@aws-cdk/cli-args-gen/lib/cli-type-gen.ts index 3ddb66569c4c2..a250415035cd7 100644 --- a/tools/@aws-cdk/cli-args-gen/lib/cli-type-gen.ts +++ b/tools/@aws-cdk/cli-args-gen/lib/cli-type-gen.ts @@ -139,6 +139,10 @@ function normalizeDefault(defaultValue: any, type: string): string { case 'object': return JSON.stringify(defaultValue); + // In these cases we cannot use the given defaultValue, so we then check the type + // of the option to determine the default value + case 'undefined': + case 'function': default: const generatedDefault = generateDefault(type); return generatedDefault ? JSON.stringify(generatedDefault) : 'undefined'; diff --git a/tools/@aws-cdk/cli-args-gen/test/cli-type-gen.test.ts b/tools/@aws-cdk/cli-args-gen/test/cli-type-gen.test.ts index d4a016fc811d3..d20af27379728 100644 --- a/tools/@aws-cdk/cli-args-gen/test/cli-type-gen.test.ts +++ b/tools/@aws-cdk/cli-args-gen/test/cli-type-gen.test.ts @@ -117,6 +117,87 @@ describe('render', () => { readonly all?: boolean; } " +`); + }); + + test('special notification-arn option gets undefined default', async () => { + const config: CliConfig = { + commands: { + deploy: { + description: 'Notification Arns', + options: { + ['notification-arns']: { + type: 'array', + desc: 'Deploy all stacks', + }, + ['other-array']: { + type: 'array', + desc: 'Other array', + }, + }, + }, + }, + globalOptions: {}, + }; + + expect(await renderCliType(config)).toMatchInlineSnapshot(` + "// ------------------------------------------------------------------------------------------- + // 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 max-len */ + import { Command } from './settings'; + + /** + * The structure of the CLI configuration, generated from packages/aws-cdk/lib/config.ts + * + * @struct + */ + export interface CliArguments { + /** + * The CLI command name followed by any properties of the command + */ + readonly _: [Command, ...string[]]; + + /** + * Global options available to all CLI commands + */ + readonly globalOptions?: GlobalOptions; + + /** + * Notification Arns + */ + readonly deploy?: DeployOptions; + } + + /** + * Global options available to all CLI commands + * + * @struct + */ + export interface GlobalOptions {} + + /** + * Notification Arns + * + * @struct + */ + export interface DeployOptions { + /** + * Deploy all stacks + * + * @default - undefined + */ + readonly 'notification-arns'?: Array; + + /** + * Other array + * + * @default - [] + */ + readonly 'other-array'?: Array; + } + " `); }); }); diff --git a/tools/@aws-cdk/cli-args-gen/test/yargs-gen.test.ts b/tools/@aws-cdk/cli-args-gen/test/yargs-gen.test.ts index e423ecc703ca2..e72c5a0328349 100644 --- a/tools/@aws-cdk/cli-args-gen/test/yargs-gen.test.ts +++ b/tools/@aws-cdk/cli-args-gen/test/yargs-gen.test.ts @@ -154,4 +154,69 @@ describe('render', () => { 'default: helpers.banana(1, 2, 3)', ); }); + + test('special notification-arn option gets NO default value', async () => { + const config: CliConfig = { + commands: { + deploy: { + description: 'Notification Arns', + options: { + ['notification-arns']: { + type: 'array', + desc: 'Deploy all stacks', + }, + ['other-array']: { + type: 'array', + desc: 'Other array', + }, + }, + }, + }, + globalOptions: {}, + }; + + expect(await renderYargs(config, YARGS_HELPERS)).toMatchInlineSnapshot(` + "// ------------------------------------------------------------------------------------------- + // 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 max-len */ + import { Argv } from 'yargs'; + import * as helpers from './util/yargs-helpers'; + + // @ts-ignore TS6133 + export function parseCommandLineArguments(args: Array): any { + return yargs + .env('CDK') + .usage('Usage: cdk -a COMMAND') + .command('deploy', 'Notification Arns', (yargs: Argv) => + yargs + .option('notification-arns', { + type: 'array', + desc: 'Deploy all stacks', + nargs: 1, + requiresArg: true, + }) + .option('other-array', { + default: [], + type: 'array', + desc: 'Other array', + nargs: 1, + requiresArg: true, + }), + ) + .version(helpers.cliVersion()) + .demandCommand(1, '') + .recommendCommands() + .help() + .alias('h', 'help') + .epilogue( + 'If your app has a single stack, there is no need to specify the stack name\\n\\nIf one of cdk.json or ~/.cdk.json exists, options specified there will be used as defaults. Settings in cdk.json take precedence.', + ) + .parse(args); + } // eslint-disable-next-line @typescript-eslint/no-require-imports + const yargs = require('yargs'); + " +`); + }); }); From bb976ee05a5bce656edb7ac6fd62fd85db1a6194 Mon Sep 17 00:00:00 2001 From: Kaizen Conroy Date: Tue, 24 Dec 2024 16:47:33 -0500 Subject: [PATCH 10/11] spacing --- tools/@aws-cdk/cli-args-gen/test/cli-type-gen.test.ts | 4 ++-- tools/@aws-cdk/cli-args-gen/test/yargs-gen.test.ts | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/@aws-cdk/cli-args-gen/test/cli-type-gen.test.ts b/tools/@aws-cdk/cli-args-gen/test/cli-type-gen.test.ts index d20af27379728..f17301d8fed2f 100644 --- a/tools/@aws-cdk/cli-args-gen/test/cli-type-gen.test.ts +++ b/tools/@aws-cdk/cli-args-gen/test/cli-type-gen.test.ts @@ -117,7 +117,7 @@ describe('render', () => { readonly all?: boolean; } " -`); + `); }); test('special notification-arn option gets undefined default', async () => { @@ -198,6 +198,6 @@ describe('render', () => { readonly 'other-array'?: Array; } " -`); + `); }); }); diff --git a/tools/@aws-cdk/cli-args-gen/test/yargs-gen.test.ts b/tools/@aws-cdk/cli-args-gen/test/yargs-gen.test.ts index e72c5a0328349..60ffeec39e2e2 100644 --- a/tools/@aws-cdk/cli-args-gen/test/yargs-gen.test.ts +++ b/tools/@aws-cdk/cli-args-gen/test/yargs-gen.test.ts @@ -69,7 +69,7 @@ describe('render', () => { } // eslint-disable-next-line @typescript-eslint/no-require-imports const yargs = require('yargs'); " -`); + `); }); test('can generate negativeAlias', async () => { @@ -127,7 +127,7 @@ describe('render', () => { } // eslint-disable-next-line @typescript-eslint/no-require-imports const yargs = require('yargs'); " -`); + `); }); test('can pass-through expression unchanged', async () => { @@ -217,6 +217,6 @@ describe('render', () => { } // eslint-disable-next-line @typescript-eslint/no-require-imports const yargs = require('yargs'); " -`); + `); }); }); From 270232610c6b9d1491c527c343a62f4b1cdb34cc Mon Sep 17 00:00:00 2001 From: Kaizen Conroy Date: Tue, 24 Dec 2024 16:48:22 -0500 Subject: [PATCH 11/11] spacing --- tools/@aws-cdk/cli-args-gen/test/cli-type-gen.test.ts | 4 ++-- tools/@aws-cdk/cli-args-gen/test/yargs-gen.test.ts | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/@aws-cdk/cli-args-gen/test/cli-type-gen.test.ts b/tools/@aws-cdk/cli-args-gen/test/cli-type-gen.test.ts index f17301d8fed2f..74d21f47ecb43 100644 --- a/tools/@aws-cdk/cli-args-gen/test/cli-type-gen.test.ts +++ b/tools/@aws-cdk/cli-args-gen/test/cli-type-gen.test.ts @@ -117,7 +117,7 @@ describe('render', () => { readonly all?: boolean; } " - `); + `); }); test('special notification-arn option gets undefined default', async () => { @@ -198,6 +198,6 @@ describe('render', () => { readonly 'other-array'?: Array; } " - `); + `); }); }); diff --git a/tools/@aws-cdk/cli-args-gen/test/yargs-gen.test.ts b/tools/@aws-cdk/cli-args-gen/test/yargs-gen.test.ts index 60ffeec39e2e2..722d7d7807225 100644 --- a/tools/@aws-cdk/cli-args-gen/test/yargs-gen.test.ts +++ b/tools/@aws-cdk/cli-args-gen/test/yargs-gen.test.ts @@ -69,7 +69,7 @@ describe('render', () => { } // eslint-disable-next-line @typescript-eslint/no-require-imports const yargs = require('yargs'); " - `); + `); }); test('can generate negativeAlias', async () => { @@ -127,7 +127,7 @@ describe('render', () => { } // eslint-disable-next-line @typescript-eslint/no-require-imports const yargs = require('yargs'); " - `); + `); }); test('can pass-through expression unchanged', async () => { @@ -217,6 +217,6 @@ describe('render', () => { } // eslint-disable-next-line @typescript-eslint/no-require-imports const yargs = require('yargs'); " - `); + `); }); });