Skip to content

Commit caf2415

Browse files
authored
chore(cli): model positional arguments in CliArguments (#32718)
**This PR does not change CLI functionality (yet)** This PR models positional arguments in `CliArguments`. Currently they are supposed to be modeled as part of the the default property `_: [Command, ...string]`. This means that in `cli.ts` we mean to use it as so: `args._[1]` instead of `args.ID`. This is a downgrade, so I've updated the following: Positional arguments are now modeled in `CliArguments` so if the `deploy` command has `STACKS` argument, it shows up as part of its `DeployOptions`. With this model we will replace `args.ID` with` args.acknowledge.ID` which I believe to be acceptable. Now, the default property is modeled as `_: Command` so that we don't duplicate information. ### Checklist - [d] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent dd6a2f4 commit caf2415

File tree

7 files changed

+241
-16
lines changed

7 files changed

+241
-16
lines changed

packages/aws-cdk/lib/cli-arguments.ts

+69-4
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ import { Command } from './settings';
1212
*/
1313
export interface CliArguments {
1414
/**
15-
* The CLI command name followed by any properties of the command
15+
* The CLI command name
1616
*/
17-
readonly _: [Command, ...string[]];
17+
readonly _: Command;
1818

1919
/**
2020
* Global options available to all CLI commands
@@ -327,6 +327,11 @@ export interface ListOptions {
327327
* @default - false
328328
*/
329329
readonly showDependencies?: boolean;
330+
331+
/**
332+
* Positional argument for list
333+
*/
334+
readonly STACKS?: Array<string>;
330335
}
331336

332337
/**
@@ -361,6 +366,11 @@ export interface SynthesizeOptions {
361366
* @default - false
362367
*/
363368
readonly quiet?: boolean;
369+
370+
/**
371+
* Positional argument for synthesize
372+
*/
373+
readonly STACKS?: Array<string>;
364374
}
365375

366376
/**
@@ -504,6 +514,11 @@ export interface BootstrapOptions {
504514
* @default - true
505515
*/
506516
readonly previousParameters?: boolean;
517+
518+
/**
519+
* Positional argument for bootstrap
520+
*/
521+
readonly ENVIRONMENTS?: Array<string>;
507522
}
508523

509524
/**
@@ -553,6 +568,11 @@ export interface GcOptions {
553568
* @default - undefined
554569
*/
555570
readonly bootstrapStackName?: string;
571+
572+
/**
573+
* Positional argument for gc
574+
*/
575+
readonly ENVIRONMENTS?: Array<string>;
556576
}
557577

558578
/**
@@ -748,6 +768,11 @@ export interface DeployOptions {
748768
* @default - false
749769
*/
750770
readonly ignoreNoStacks?: boolean;
771+
772+
/**
773+
* Positional argument for deploy
774+
*/
775+
readonly STACKS?: Array<string>;
751776
}
752777

753778
/**
@@ -792,6 +817,11 @@ export interface RollbackOptions {
792817
* @default - []
793818
*/
794819
readonly orphan?: Array<string>;
820+
821+
/**
822+
* Positional argument for rollback
823+
*/
824+
readonly STACKS?: Array<string>;
795825
}
796826

797827
/**
@@ -854,6 +884,11 @@ export interface ImportOptions {
854884
* @default - undefined
855885
*/
856886
readonly resourceMapping?: string;
887+
888+
/**
889+
* Positional argument for import
890+
*/
891+
readonly STACK?: string;
857892
}
858893

859894
/**
@@ -944,6 +979,11 @@ export interface WatchOptions {
944979
* @default - 1
945980
*/
946981
readonly concurrency?: number;
982+
983+
/**
984+
* Positional argument for watch
985+
*/
986+
readonly STACKS?: Array<string>;
947987
}
948988

949989
/**
@@ -976,6 +1016,11 @@ export interface DestroyOptions {
9761016
* @default - undefined
9771017
*/
9781018
readonly force?: boolean;
1019+
1020+
/**
1021+
* Positional argument for destroy
1022+
*/
1023+
readonly STACKS?: Array<string>;
9791024
}
9801025

9811026
/**
@@ -1052,14 +1097,24 @@ export interface DiffOptions {
10521097
* @default - true
10531098
*/
10541099
readonly changeSet?: boolean;
1100+
1101+
/**
1102+
* Positional argument for diff
1103+
*/
1104+
readonly STACKS?: Array<string>;
10551105
}
10561106

10571107
/**
10581108
* Returns all metadata associated with this stack
10591109
*
10601110
* @struct
10611111
*/
1062-
export interface MetadataOptions {}
1112+
export interface MetadataOptions {
1113+
/**
1114+
* Positional argument for metadata
1115+
*/
1116+
readonly STACK?: string;
1117+
}
10631118

10641119
/**
10651120
* Acknowledge a notice so that it does not show up anymore
@@ -1068,7 +1123,12 @@ export interface MetadataOptions {}
10681123
*
10691124
* @struct
10701125
*/
1071-
export interface AcknowledgeOptions {}
1126+
export interface AcknowledgeOptions {
1127+
/**
1128+
* Positional argument for acknowledge
1129+
*/
1130+
readonly ID?: string;
1131+
}
10721132

10731133
/**
10741134
* Returns a list of relevant notices
@@ -1114,6 +1174,11 @@ export interface InitOptions {
11141174
* @default - false
11151175
*/
11161176
readonly generateOnly?: boolean;
1177+
1178+
/**
1179+
* Positional argument for init
1180+
*/
1181+
readonly TEMPLATE?: string;
11171182
}
11181183

11191184
/**

packages/aws-cdk/lib/convert-to-cli-args.ts

+18-3
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export function convertToCliArgs(args: any): CliArguments {
4141
commandOptions = {
4242
long: args.long,
4343
showDependencies: args.showDependencies,
44+
STACKS: args.STACKS,
4445
};
4546
break;
4647

@@ -49,6 +50,7 @@ export function convertToCliArgs(args: any): CliArguments {
4950
exclusively: args.exclusively,
5051
validation: args.validation,
5152
quiet: args.quiet,
53+
STACKS: args.STACKS,
5254
};
5355
break;
5456

@@ -72,6 +74,7 @@ export function convertToCliArgs(args: any): CliArguments {
7274
toolkitStackName: args.toolkitStackName,
7375
template: args.template,
7476
previousParameters: args.previousParameters,
77+
ENVIRONMENTS: args.ENVIRONMENTS,
7578
};
7679
break;
7780

@@ -83,6 +86,7 @@ export function convertToCliArgs(args: any): CliArguments {
8386
createdBufferDays: args.createdBufferDays,
8487
confirm: args.confirm,
8588
bootstrapStackName: args.bootstrapStackName,
89+
ENVIRONMENTS: args.ENVIRONMENTS,
8690
};
8791
break;
8892

@@ -113,6 +117,7 @@ export function convertToCliArgs(args: any): CliArguments {
113117
assetParallelism: args.assetParallelism,
114118
assetPrebuild: args.assetPrebuild,
115119
ignoreNoStacks: args.ignoreNoStacks,
120+
STACKS: args.STACKS,
116121
};
117122
break;
118123

@@ -123,6 +128,7 @@ export function convertToCliArgs(args: any): CliArguments {
123128
force: args.force,
124129
validateBootstrapVersion: args.validateBootstrapVersion,
125130
orphan: args.orphan,
131+
STACKS: args.STACKS,
126132
};
127133
break;
128134

@@ -135,6 +141,7 @@ export function convertToCliArgs(args: any): CliArguments {
135141
force: args.force,
136142
recordResourceMapping: args.recordResourceMapping,
137143
resourceMapping: args.resourceMapping,
144+
STACK: args.STACK,
138145
};
139146
break;
140147

@@ -151,6 +158,7 @@ export function convertToCliArgs(args: any): CliArguments {
151158
hotswapFallback: args.hotswapFallback,
152159
logs: args.logs,
153160
concurrency: args.concurrency,
161+
STACKS: args.STACKS,
154162
};
155163
break;
156164

@@ -159,6 +167,7 @@ export function convertToCliArgs(args: any): CliArguments {
159167
all: args.all,
160168
exclusively: args.exclusively,
161169
force: args.force,
170+
STACKS: args.STACKS,
162171
};
163172
break;
164173

@@ -173,15 +182,20 @@ export function convertToCliArgs(args: any): CliArguments {
173182
processed: args.processed,
174183
quiet: args.quiet,
175184
changeSet: args.changeSet,
185+
STACKS: args.STACKS,
176186
};
177187
break;
178188

179189
case 'metadata':
180-
commandOptions = {};
190+
commandOptions = {
191+
STACK: args.STACK,
192+
};
181193
break;
182194

183195
case 'acknowledge':
184-
commandOptions = {};
196+
commandOptions = {
197+
ID: args.ID,
198+
};
185199
break;
186200

187201
case 'notices':
@@ -195,6 +209,7 @@ export function convertToCliArgs(args: any): CliArguments {
195209
language: args.language,
196210
list: args.list,
197211
generateOnly: args.generateOnly,
212+
TEMPLATE: args.TEMPLATE,
198213
};
199214
break;
200215

@@ -232,7 +247,7 @@ export function convertToCliArgs(args: any): CliArguments {
232247
break;
233248
}
234249
const cliArguments: CliArguments = {
235-
_: args._,
250+
_: args._[0],
236251
globalOptions,
237252
[args._[0]]: commandOptions,
238253
};

packages/aws-cdk/test/cli-arguments.test.ts

+30-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ test('yargs object can be converted to cli arguments', async () => {
77
const result = convertToCliArgs(input);
88

99
expect(result).toEqual({
10-
_: ['deploy'],
10+
_: 'deploy',
1111
globalOptions: {
1212
app: undefined,
1313
assetMetadata: undefined,
@@ -36,6 +36,7 @@ test('yargs object can be converted to cli arguments', async () => {
3636
output: undefined,
3737
},
3838
deploy: {
39+
STACKS: undefined,
3940
all: false,
4041
assetParallelism: undefined,
4142
assetPrebuild: true,
@@ -64,3 +65,31 @@ test('yargs object can be converted to cli arguments', async () => {
6465
},
6566
});
6667
});
68+
69+
test('positional argument is correctly passed through -- variadic', async () => {
70+
const input = await parseCommandLineArguments(['deploy', 'stack1', 'stack2', '-R', '-v', '--ci']);
71+
72+
const result = convertToCliArgs(input);
73+
74+
expect(result).toEqual({
75+
_: 'deploy',
76+
deploy: expect.objectContaining({
77+
STACKS: ['stack1', 'stack2'],
78+
}),
79+
globalOptions: expect.anything(),
80+
});
81+
});
82+
83+
test('positional argument is correctly passed through -- single', async () => {
84+
const input = await parseCommandLineArguments(['acknowledge', 'id1', '-v', '--ci']);
85+
86+
const result = convertToCliArgs(input);
87+
88+
expect(result).toEqual({
89+
_: 'acknowledge',
90+
acknowledge: expect.objectContaining({
91+
ID: 'id1',
92+
}),
93+
globalOptions: expect.anything(),
94+
});
95+
});

tools/@aws-cdk/cli-args-gen/lib/cli-args-function-gen.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ function buildCommandSwitch(config: CliConfig): string {
6767
`case '${commandName}':`,
6868
'commandOptions = {',
6969
...buildCommandOptions(config.commands[commandName]),
70+
...(config.commands[commandName].arg ? [buildPositionalArguments(config.commands[commandName].arg)] : []),
7071
'};',
7172
`break;
7273
`);
@@ -84,10 +85,17 @@ function buildCommandOptions(options: CliAction): string[] {
8485
return commandOptions;
8586
}
8687

88+
function buildPositionalArguments(arg: { name: string; variadic: boolean }): string {
89+
if (arg.variadic) {
90+
return `${arg.name}: args.${arg.name}`;
91+
}
92+
return `${arg.name}: args.${arg.name}`;
93+
}
94+
8795
function buildCliArgs(): string {
8896
return [
8997
'const cliArguments: CliArguments = {',
90-
'_: args._,',
98+
'_: args._[0],',
9199
'globalOptions,',
92100
'[args._[0]]: commandOptions',
93101
'}',

tools/@aws-cdk/cli-args-gen/lib/cli-args-gen.ts

+15-2
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ export async function renderCliArgsType(config: CliConfig): Promise<string> {
2626

2727
cliArgType.addProperty({
2828
name: '_',
29-
type: Type.ambient(`[${commandEnum}, ...string[]]`),
29+
type: commandEnum,
3030
docs: {
31-
summary: 'The CLI command name followed by any properties of the command',
31+
summary: 'The CLI command name',
3232
},
3333
});
3434

@@ -73,6 +73,7 @@ export async function renderCliArgsType(config: CliConfig): Promise<string> {
7373
},
7474
});
7575

76+
// add command level options
7677
for (const [optionName, option] of Object.entries(command.options ?? {})) {
7778
commandType.addProperty({
7879
name: kebabToCamelCase(optionName),
@@ -88,6 +89,18 @@ export async function renderCliArgsType(config: CliConfig): Promise<string> {
8889
});
8990
}
9091

92+
// add positional argument associated with the command
93+
if (command.arg) {
94+
commandType.addProperty({
95+
name: command.arg.name,
96+
type: command.arg.variadic ? Type.arrayOf(Type.STRING) : Type.STRING,
97+
docs: {
98+
summary: `Positional argument for ${commandName}`,
99+
},
100+
optional: true,
101+
});
102+
}
103+
91104
cliArgType.addProperty({
92105
name: kebabToCamelCase(commandName),
93106
type: Type.fromName(scope, commandType.name),

0 commit comments

Comments
 (0)