Skip to content

Commit

Permalink
fix(cli): init templates still assume the same versions (#33449)
Browse files Browse the repository at this point in the history
The init templates still have a single `%cdk-version%` placeholder for both the library and the CLI.

Introduce a new `%cdk-cli-version%` placeholder and fill it with the "current" version of the CLI used to create the template.

Turning `DISPLAY_VERSION` into a lazy function, because we added a dependency `init.ts -> version.ts`, and since `init.ts` is included in a pre-build script, we now include `version.ts` in that pre-build script which tries to read a file at load time that still needs to be generated.

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
rix0rrr authored Feb 14, 2025
1 parent e5e4f9b commit 523e0f0
Show file tree
Hide file tree
Showing 10 changed files with 72 additions and 49 deletions.
4 changes: 2 additions & 2 deletions packages/aws-cdk/lib/cli/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export async function exec(args: string[], synthesizer?: Synthesizer): Promise<n
debug(`Error while checking for platform warnings: ${e}`);
}

debug('CDK toolkit version:', version.DISPLAY_VERSION);
debug('CDK toolkit version:', version.displayVersion());
debug('Command line arguments:', argv);

const configuration = new Configuration({
Expand Down Expand Up @@ -494,7 +494,7 @@ export async function exec(args: string[], synthesizer?: Synthesizer): Promise<n
});
case 'version':
ioHost.currentAction = 'version';
return result(version.DISPLAY_VERSION);
return result(version.displayVersion());

default:
throw new ToolkitError('Unknown command: ' + command);
Expand Down
2 changes: 1 addition & 1 deletion packages/aws-cdk/lib/cli/util/yargs-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export function yargsNegativeAlias<T extends { [x in S | L]: boolean | undefined
* @returns the current version of the CLI
*/
export function cliVersion(): string {
return version.DISPLAY_VERSION;
return version.displayVersion();
}

/**
Expand Down
4 changes: 3 additions & 1 deletion packages/aws-cdk/lib/cli/version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ const UPGRADE_DOCUMENTATION_LINKS: Record<number, string> = {
1: 'https://docs.aws.amazon.com/cdk/v2/guide/migrating-v2.html',
};

export const DISPLAY_VERSION = `${versionNumber()} (build ${commit()})`;
export function displayVersion() {
return `${versionNumber()} (build ${commit()})`;
}

export function isDeveloperBuild(): boolean {
return versionNumber() === '0.0.0';
Expand Down
2 changes: 1 addition & 1 deletion packages/aws-cdk/lib/commands/doctor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const verifications: Array<() => boolean | Promise<boolean>> = [
// ### Verifications ###

function displayVersionInformation() {
info(`ℹ️ CDK Version: ${chalk.green(version.DISPLAY_VERSION)}`);
info(`ℹ️ CDK Version: ${chalk.green(version.displayVersion())}`);
return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"test": "jest"
},
"devDependencies": {
"aws-cdk": "%cdk-version%",
"aws-cdk": "%cdk-cli-version%",
"jest": "^29.7.0"
},
"dependencies": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"@types/node": "22.7.9",
"jest": "^29.7.0",
"ts-jest": "^29.2.5",
"aws-cdk": "%cdk-version%",
"aws-cdk": "%cdk-cli-version%",
"ts-node": "^10.9.2",
"typescript": "~5.6.3"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"test": "jest"
},
"devDependencies": {
"aws-cdk": "%cdk-version%",
"aws-cdk": "%cdk-cli-version%",
"jest": "^29.7.0"
},
"dependencies": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"@types/node": "22.7.9",
"jest": "^29.7.0",
"ts-jest": "^29.2.5",
"aws-cdk": "%cdk-version%",
"aws-cdk": "%cdk-cli-version%",
"ts-node": "^10.9.2",
"typescript": "~5.6.3"
},
Expand Down
84 changes: 45 additions & 39 deletions packages/aws-cdk/lib/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as childProcess from 'child_process';
import * as path from 'path';
import * as chalk from 'chalk';
import * as fs from 'fs-extra';
import { versionNumber } from './cli/version';
import { invokeBuiltinHooks } from './init-hooks';
import { error, info, warning } from './logging';
import { ToolkitError } from './toolkit/error';
Expand Down Expand Up @@ -141,18 +142,18 @@ export class InitTemplate {
for (const fileName of fileNames) {
const fullPath = path.join(targetDirectory, fileName);
const template = await fs.readFile(fullPath, { encoding: 'utf-8' });
await fs.writeFile(fullPath, this.expand(template, language, projectInfo));
await fs.writeFile(fullPath, expandPlaceholders(template, language, projectInfo));
}
},
placeholder: (ph: string) => this.expand(`%${ph}%`, language, projectInfo),
placeholder: (ph: string) => expandPlaceholders(`%${ph}%`, language, projectInfo),
},
);
}

private async installFiles(sourceDirectory: string, targetDirectory: string, language: string, project: ProjectInfo) {
for (const file of await fs.readdir(sourceDirectory)) {
const fromFile = path.join(sourceDirectory, file);
const toFile = path.join(targetDirectory, this.expand(file, language, project));
const toFile = path.join(targetDirectory, expandPlaceholders(file, language, project));
if ((await fs.stat(fromFile)).isDirectory()) {
await fs.mkdir(toFile);
await this.installFiles(fromFile, toFile, language, project);
Expand All @@ -171,42 +172,7 @@ export class InitTemplate {

private async installProcessed(templatePath: string, toFile: string, language: string, project: ProjectInfo) {
const template = await fs.readFile(templatePath, { encoding: 'utf-8' });
await fs.writeFile(toFile, this.expand(template, language, project));
}

private expand(template: string, language: string, project: ProjectInfo) {
const cdkVersion = project.versions['aws-cdk-lib'];
let constructsVersion = project.versions.constructs;

switch (language) {
case 'java':
case 'csharp':
case 'fsharp':
constructsVersion = rangeFromSemver(constructsVersion, 'bracket');
break;
case 'python':
constructsVersion = rangeFromSemver(constructsVersion, 'pep');
break;
}
return template
.replace(/%name%/g, project.name)
.replace(/%stackname%/, project.stackName ?? '%name.PascalCased%Stack')
.replace(
/%PascalNameSpace%/,
project.stackName ? camelCase(project.stackName + 'Stack', { pascalCase: true }) : '%name.PascalCased%',
)
.replace(
/%PascalStackProps%/,
project.stackName ? camelCase(project.stackName, { pascalCase: true }) + 'StackProps' : 'StackProps',
)
.replace(/%name\.camelCased%/g, camelCase(project.name))
.replace(/%name\.PascalCased%/g, camelCase(project.name, { pascalCase: true }))
.replace(/%cdk-version%/g, cdkVersion)
.replace(/%constructs-version%/g, constructsVersion)
.replace(/%cdk-home%/g, cdkHomeDir())
.replace(/%name\.PythonModule%/g, project.name.replace(/-/g, '_'))
.replace(/%python-executable%/g, pythonExecutable())
.replace(/%name\.StackName%/g, project.name.replace(/[^A-Za-z0-9-]/g, '-'));
await fs.writeFile(toFile, expandPlaceholders(template, language, project));
}

/**
Expand Down Expand Up @@ -244,6 +210,43 @@ export class InitTemplate {
}
}

export function expandPlaceholders(template: string, language: string, project: ProjectInfo) {
const cdkVersion = project.versions['aws-cdk-lib'];
const cdkCliVersion = project.versions['aws-cdk'];
let constructsVersion = project.versions.constructs;

switch (language) {
case 'java':
case 'csharp':
case 'fsharp':
constructsVersion = rangeFromSemver(constructsVersion, 'bracket');
break;
case 'python':
constructsVersion = rangeFromSemver(constructsVersion, 'pep');
break;
}
return template
.replace(/%name%/g, project.name)
.replace(/%stackname%/, project.stackName ?? '%name.PascalCased%Stack')
.replace(
/%PascalNameSpace%/,
project.stackName ? camelCase(project.stackName + 'Stack', { pascalCase: true }) : '%name.PascalCased%',
)
.replace(
/%PascalStackProps%/,
project.stackName ? camelCase(project.stackName, { pascalCase: true }) + 'StackProps' : 'StackProps',
)
.replace(/%name\.camelCased%/g, camelCase(project.name))
.replace(/%name\.PascalCased%/g, camelCase(project.name, { pascalCase: true }))
.replace(/%cdk-version%/g, cdkVersion)
.replace(/%cdk-cli-version%/g, cdkCliVersion)
.replace(/%constructs-version%/g, constructsVersion)
.replace(/%cdk-home%/g, cdkHomeDir())
.replace(/%name\.PythonModule%/g, project.name.replace(/-/g, '_'))
.replace(/%python-executable%/g, pythonExecutable())
.replace(/%name\.StackName%/g, project.name.replace(/[^A-Za-z0-9-]/g, '-'));
}

interface ProjectInfo {
/** The value used for %name% */
readonly name: string;
Expand All @@ -267,6 +270,7 @@ export async function availableInitTemplates(): Promise<InitTemplate[]> {
}
});
}

export async function availableInitLanguages(): Promise<string[]> {
return new Promise(async (resolve) => {
const templates = await availableInitTemplates();
Expand Down Expand Up @@ -475,6 +479,7 @@ async function execute(cmd: string, args: string[], { cwd }: { cwd: string }) {
}

interface Versions {
['aws-cdk']: string;
['aws-cdk-lib']: string;
constructs: string;
}
Expand All @@ -491,6 +496,7 @@ async function loadInitVersions(): Promise<Versions> {
const ret = {
'aws-cdk-lib': contents['aws-cdk-lib'],
'constructs': contents.constructs,
'aws-cdk': versionNumber(),
};
for (const [key, value] of Object.entries(ret)) {
/* istanbul ignore next */
Expand Down
17 changes: 16 additions & 1 deletion packages/aws-cdk/test/init.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as os from 'os';
import * as path from 'path';
import * as cxapi from '@aws-cdk/cx-api';
import * as fs from 'fs-extra';
import { availableInitLanguages, availableInitTemplates, cliInit, currentlyRecommendedAwsCdkLibFlags, printAvailableTemplates } from '../lib/init';
import { availableInitLanguages, availableInitTemplates, cliInit, currentlyRecommendedAwsCdkLibFlags, expandPlaceholders, printAvailableTemplates } from '../lib/init';

describe('constructs version', () => {
cliTest('create a TypeScript library project', async (workDir) => {
Expand Down Expand Up @@ -291,6 +291,21 @@ test('exercise printing available templates', async () => {
await printAvailableTemplates();
});

describe('expandPlaceholders', () => {
test('distinguish library and CLI version', () => {
const translated = expandPlaceholders('%cdk-version% and %cdk-cli-version%', 'javascript', {
name: 'test',
versions: {
'aws-cdk': '1',
'aws-cdk-lib': '2',
'constructs': '3',
},
});

expect(translated).toEqual('2 and 1');
});
});

function cliTest(name: string, handler: (dir: string) => void | Promise<any>): void {
test(name, () => withTempDir(handler));
}
Expand Down

0 comments on commit 523e0f0

Please sign in to comment.