Skip to content

Commit 5437650

Browse files
committed
chore: add CLI-level validation for template-path parameter
1 parent c02abcb commit 5437650

File tree

5 files changed

+34
-21
lines changed

5 files changed

+34
-21
lines changed

packages/@aws-cdk/user-input-gen/lib/yargs-gen.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,17 +105,22 @@ function makeYargs(config: CliConfig, helpers: CliHelpers): Statement {
105105
}
106106
commandCallArgs.push(lit(commandFacts.description));
107107

108-
if (commandFacts.options) {
109-
commandCallArgs.push(optionsExpr);
110-
}
111-
112108
// Add implies calls if present
113109
if (commandFacts.implies) {
114110
for (const [key, value] of Object.entries(commandFacts.implies)) {
115111
optionsExpr = optionsExpr.callMethod('implies', lit(key), lit(value));
116112
}
117113
}
118114

115+
// Add check function if present
116+
if (commandFacts.check) {
117+
optionsExpr = optionsExpr.callMethod('check', code.expr.directCode(commandFacts.check.toString()));
118+
}
119+
120+
if (commandFacts.options || commandFacts.check) {
121+
commandCallArgs.push(optionsExpr);
122+
}
123+
119124
yargsExpr = yargsExpr.callMethod('command', ...commandCallArgs);
120125
}
121126

packages/@aws-cdk/user-input-gen/lib/yargs-types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ interface YargsCommand {
88
export interface CliAction extends YargsCommand {
99
options?: { [optionName: string]: CliOption };
1010
implies?: { [key: string]: string };
11-
// check?: string;
11+
check?: (argv: any) => boolean | Promise<boolean>;
1212
}
1313

1414
interface YargsArg {

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,14 @@ export async function makeConfig(): Promise<CliConfig> {
405405
'from-git-url': { type: 'string', desc: 'Git repository URL to clone custom template from', requiresArg: true, conflicts: ['lib-version', 'from-path'] },
406406
'template-path': { type: 'string', desc: 'Path to a specific template within a multi-template repository', requiresArg: true },
407407
},
408-
408+
check: (argv: any) => {
409+
if (argv['template-path'] && !argv['from-path'] && !argv['from-git-url']) {
410+
const error = new Error('--template-path can only be used with --from-path or --from-git-url');
411+
error.name = 'ValidationError';
412+
throw error;
413+
}
414+
return true;
415+
},
409416
},
410417
'migrate': {
411418
description: 'Migrate existing AWS resources into a CDK app',

packages/aws-cdk/lib/commands/init/init.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,6 @@ export async function cliInit(options: CliInitOptions) {
9191
const generateOnly = options.generateOnly ?? false;
9292
const workDir = options.workDir ?? process.cwd();
9393

94-
// Validate that if template-path is provided, exactly one custom template source must be provided
95-
if (options.templatePath && !options.fromPath && !options.fromGitUrl) {
96-
throw new ToolkitError('--template-path can only be used with --from-path or --from-git-url');
97-
}
98-
9994
// Show available templates if no type and no language provided (main branch logic)
10095
if (!options.fromPath && !options.fromGitUrl && !options.type && !options.language) {
10196
await printAvailableTemplates(ioHelper);

packages/aws-cdk/test/commands/init.test.ts

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -607,18 +607,24 @@ describe('constructs version', () => {
607607
});
608608

609609
cliTest('template-path validation requires from-path or from-git-url', async (workDir) => {
610-
const projectDir = path.join(workDir, 'my-project');
611-
await fs.mkdirp(projectDir);
610+
const { exec } = await import('child_process');
611+
const { promisify } = await import('util');
612+
const execAsync = promisify(exec);
613+
const cdkBin = path.join(__dirname, '..', '..', 'bin', 'cdk');
614+
615+
const emptyDir = path.join(workDir, 'empty-project');
616+
await fs.mkdirp(emptyDir);
612617

613618
// Test that template-path fails when used without from-path or from-git-url
614-
await expect(cliInit({
615-
ioHelper,
616-
templatePath: 'some-template',
617-
language: 'typescript',
618-
canUseNetwork: false,
619-
generateOnly: true,
620-
workDir: projectDir,
621-
})).rejects.toThrow('--template-path can only be used with --from-path or --from-git-url');
619+
try {
620+
await execAsync(`node ${cdkBin} init --template-path some-template --language typescript --generate-only`, {
621+
cwd: emptyDir,
622+
env: { ...process.env, CDK_DISABLE_VERSION_CHECK: '1' },
623+
});
624+
throw new Error('Expected command to fail but it succeeded');
625+
} catch (error: any) {
626+
expect(error.stderr || error.message).toContain('--template-path can only be used with --from-path or --from-git-url');
627+
}
622628
});
623629

624630
cliTest('hook files are ignored during template copy', async (workDir) => {

0 commit comments

Comments
 (0)