Skip to content

Commit 0499641

Browse files
authored
chore(ubergen): create missing L1 READMEs and strip stability banners (#16692)
This change bundles together two changes for how ubergen handles package READMEs. The first is to generate a base README for experimental/alpha modules where only the L1s are included. The second is to strip out the stability banners from *all* READMEs; this is because, by definition, everything included in aws-cdk-lib is stable, so the banners are now redundant/misleading. fixes #16567
1 parent fdd157d commit 0499641

File tree

7 files changed

+176
-64
lines changed

7 files changed

+176
-64
lines changed

Diff for: packages/@aws-cdk/cfnspec/build-tools/create-missing-libraries.ts

+21-62
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,9 @@ async function main() {
2424

2525
// iterate over all cloudformation namespaces
2626
for (const namespace of cfnspec.namespaces()) {
27-
const [moduleFamily, moduleBaseName] = (namespace === 'AWS::Serverless' ? 'AWS::SAM' : namespace).split('::');
28-
29-
const moduleName = `${moduleFamily}-${moduleBaseName.replace(/V\d+$/, '')}`.toLocaleLowerCase();
30-
const packagePath = path.join(root, moduleName);
31-
32-
const lowcaseModuleName = moduleBaseName.toLocaleLowerCase();
33-
const packageName = `@aws-cdk/${moduleName}`;
27+
const module = cfnspec.createModuleDefinitionFromCfnNamespace(namespace);
28+
const lowcaseModuleName = module.moduleName.toLocaleLowerCase();
29+
const packagePath = path.join(root, module.moduleName);
3430

3531
// we already have a module for this namesapce, move on.
3632
if (await fs.pathExists(packagePath)) {
@@ -42,12 +38,12 @@ async function main() {
4238
if (scopes.indexOf(namespace) !== -1) {
4339
// V2-style module is already modeled in the root package, nothing to be done!
4440
continue;
45-
} else if (await fs.pathExists(path.join(root, `${moduleFamily}-${moduleBaseName}`.toLocaleLowerCase()))) {
41+
} else if (await fs.pathExists(path.join(root, `${module.moduleFamily}-${module.moduleBaseName}`.toLocaleLowerCase()))) {
4642
// V2-style package already has it's own package (legacy behavior), nothing to be done!
4743
continue;
4844
} else {
4945
// V2-style package needs to be added to it's "V1" package... Get down to business!
50-
console.error(`Adding ${namespace} to ${packageName}`);
46+
console.error(`Adding ${namespace} to ${module.packageName}`);
5147
scopes.push(namespace);
5248
packageJson['cdk-build'].cloudformation = scopes;
5349
await fs.writeJson(packageJsonPath, packageJson, { encoding: 'utf-8', spaces: 2 });
@@ -62,22 +58,6 @@ async function main() {
6258
}
6359
}
6460

65-
// dotnet names
66-
const dotnetPackage = `Amazon.CDK.${moduleFamily}.${moduleBaseName}`;
67-
68-
// java names
69-
const javaGroupId = 'software.amazon.awscdk';
70-
const javaPackage = moduleFamily === 'AWS'
71-
? `services.${lowcaseModuleName}`
72-
: `${moduleFamily.toLocaleLowerCase()}.${lowcaseModuleName}`;
73-
const javaArtifactId = moduleFamily === 'AWS'
74-
? lowcaseModuleName
75-
: `${moduleFamily.toLocaleLowerCase()}-${lowcaseModuleName}`;
76-
77-
// python names
78-
const pythonDistName = `aws-cdk.${moduleName}`;
79-
const pythonModuleName = pythonDistName.replace(/-/g, '_');
80-
8161
async function write(relativePath: string, contents: string[] | string | object) {
8262
const fullPath = path.join(packagePath, relativePath);
8363
const dir = path.dirname(fullPath);
@@ -97,10 +77,10 @@ async function main() {
9777
await fs.writeFile(fullPath, data + '\n');
9878
}
9979

100-
console.log(`generating module for ${packageName}...`);
80+
console.log(`generating module for ${module.packageName}...`);
10181

10282
await write('package.json', {
103-
name: packageName,
83+
name: module.packageName,
10484
version,
10585
description: `The CDK Construct Library for ${namespace}`,
10686
main: 'lib/index.js',
@@ -110,33 +90,33 @@ async function main() {
11090
projectReferences: true,
11191
targets: {
11292
dotnet: {
113-
namespace: dotnetPackage,
114-
packageId: dotnetPackage,
93+
namespace: module.dotnetPackage,
94+
packageId: module.dotnetPackage,
11595
signAssembly: true,
11696
assemblyOriginatorKeyFile: '../../key.snk',
11797
iconUrl: 'https://raw.githubusercontent.com/aws/aws-cdk/master/logo/default-256-dark.png',
11898
},
11999
java: {
120-
package: `${javaGroupId}.${javaPackage}`,
100+
package: `${module.javaGroupId}.${module.javaPackage}`,
121101
maven: {
122-
groupId: javaGroupId,
123-
artifactId: javaArtifactId,
102+
groupId: module.javaGroupId,
103+
artifactId: module.javaArtifactId,
124104
},
125105
},
126106
python: {
127107
classifiers: [
128108
'Framework :: AWS CDK',
129109
'Framework :: AWS CDK :: 1',
130110
],
131-
distName: pythonDistName,
132-
module: pythonModuleName,
111+
distName: module.pythonDistName,
112+
module: module.pythonModuleName,
133113
},
134114
},
135115
},
136116
repository: {
137117
type: 'git',
138118
url: 'https://github.com/aws/aws-cdk.git',
139-
directory: `packages/${packageName}`,
119+
directory: `packages/${module.packageName}`,
140120
},
141121
homepage: 'https://github.com/aws/aws-cdk',
142122
scripts: {
@@ -169,7 +149,7 @@ async function main() {
169149
'cdk',
170150
'constructs',
171151
namespace,
172-
moduleName,
152+
module.moduleName,
173153
],
174154
author: {
175155
name: 'Amazon Web Services',
@@ -271,28 +251,7 @@ async function main() {
271251
'});',
272252
]);
273253

274-
await write('README.md', [
275-
`# ${namespace} Construct Library`,
276-
'<!--BEGIN STABILITY BANNER-->',
277-
'',
278-
'---',
279-
'',
280-
'![cfn-resources: Stable](https://img.shields.io/badge/cfn--resources-stable-success.svg?style=for-the-badge)',
281-
'',
282-
'> All classes with the `Cfn` prefix in this module ([CFN Resources]) are always stable and safe to use.',
283-
'>',
284-
'> [CFN Resources]: https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib',
285-
'',
286-
'---',
287-
'',
288-
'<!--END STABILITY BANNER-->',
289-
'',
290-
'This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project.',
291-
'',
292-
'```ts',
293-
`import ${lowcaseModuleName} = require('${packageName}');`,
294-
'```',
295-
]);
254+
await cfnspec.createLibraryReadme(namespace, path.join(packagePath, 'README.md'));
296255

297256
await write('.eslintrc.js', [
298257
"const baseConfig = require('@aws-cdk/cdk-build-tools/config/eslintrc');",
@@ -310,10 +269,10 @@ async function main() {
310269
await fs.copy(path.join(templateDir, file), path.join(packagePath, file));
311270
}
312271

313-
await addDependencyToMegaPackage(path.join('@aws-cdk', 'cloudformation-include'), packageName, version, ['dependencies', 'peerDependencies']);
314-
await addDependencyToMegaPackage('aws-cdk-lib', packageName, version, ['devDependencies']);
315-
await addDependencyToMegaPackage('monocdk', packageName, version, ['devDependencies']);
316-
await addDependencyToMegaPackage('decdk', packageName, version, ['dependencies']);
272+
await addDependencyToMegaPackage(path.join('@aws-cdk', 'cloudformation-include'), module.packageName, version, ['dependencies', 'peerDependencies']);
273+
await addDependencyToMegaPackage('aws-cdk-lib', module.packageName, version, ['devDependencies']);
274+
await addDependencyToMegaPackage('monocdk', module.packageName, version, ['devDependencies']);
275+
await addDependencyToMegaPackage('decdk', module.packageName, version, ['dependencies']);
317276
}
318277
}
319278

Diff for: packages/@aws-cdk/cfnspec/lib/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { CfnLintFileSchema } from './_private_schema/cfn-lint';
33
import * as schema from './schema';
44
export { schema };
55
export * from './canned-metrics';
6+
export * from './library-creation';
67

78
/**
89
* The complete AWS CloudFormation Resource specification, having any CDK patches and enhancements included in it.

Diff for: packages/@aws-cdk/cfnspec/lib/library-creation.ts

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import * as fs from 'fs-extra';
2+
3+
export interface ModuleDefinition {
4+
readonly namespace: string;
5+
readonly moduleName: string;
6+
readonly moduleFamily: string;
7+
readonly moduleBaseName: string;
8+
readonly packageName: string;
9+
10+
readonly dotnetPackage: string;
11+
readonly javaGroupId: string;
12+
readonly javaPackage: string;
13+
readonly javaArtifactId: string;
14+
15+
readonly pythonDistName: string;
16+
readonly pythonModuleName: string;
17+
}
18+
19+
export function createModuleDefinitionFromCfnNamespace(namespace: string): ModuleDefinition {
20+
const [moduleFamily, moduleBaseName] = (namespace === 'AWS::Serverless' ? 'AWS::SAM' : namespace).split('::');
21+
const moduleName = `${moduleFamily}-${moduleBaseName.replace(/V\d+$/, '')}`.toLocaleLowerCase();
22+
23+
const lowcaseModuleName = moduleBaseName.toLocaleLowerCase();
24+
const packageName = `@aws-cdk/${moduleName}`;
25+
26+
// dotnet names
27+
const dotnetPackage = `Amazon.CDK.${moduleFamily}.${moduleBaseName}`;
28+
29+
// java names
30+
const javaGroupId = 'software.amazon.awscdk';
31+
const javaPackage = moduleFamily === 'AWS'
32+
? `services.${lowcaseModuleName}`
33+
: `${moduleFamily.toLocaleLowerCase()}.${lowcaseModuleName}`;
34+
const javaArtifactId = moduleFamily === 'AWS'
35+
? lowcaseModuleName
36+
: `${moduleFamily.toLocaleLowerCase()}-${lowcaseModuleName}`;
37+
38+
// python names
39+
const pythonDistName = `aws-cdk.${moduleName}`;
40+
const pythonModuleName = pythonDistName.replace(/-/g, '_');
41+
42+
return {
43+
namespace,
44+
moduleName,
45+
moduleFamily,
46+
moduleBaseName,
47+
packageName,
48+
dotnetPackage,
49+
javaGroupId,
50+
javaPackage,
51+
javaArtifactId,
52+
pythonDistName,
53+
pythonModuleName,
54+
};
55+
}
56+
57+
export async function createLibraryReadme(namespace: string, readmePath: string) {
58+
const module = createModuleDefinitionFromCfnNamespace(namespace);
59+
60+
await fs.writeFile(readmePath, [
61+
`# ${namespace} Construct Library`,
62+
'<!--BEGIN STABILITY BANNER-->',
63+
'',
64+
'---',
65+
'',
66+
'![cfn-resources: Stable](https://img.shields.io/badge/cfn--resources-stable-success.svg?style=for-the-badge)',
67+
'',
68+
'> All classes with the `Cfn` prefix in this module ([CFN Resources]) are always stable and safe to use.',
69+
'>',
70+
'> [CFN Resources]: https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib',
71+
'',
72+
'---',
73+
'',
74+
'<!--END STABILITY BANNER-->',
75+
'',
76+
'This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project.',
77+
'',
78+
'```ts',
79+
`import ${module.moduleName.toLocaleLowerCase()} = require('${module.packageName}');`,
80+
'```',
81+
'',
82+
].join('\n'), 'utf8');
83+
}

Diff for: packages/@aws-cdk/cfnspec/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@
3535
"@types/jest": "^26.0.24",
3636
"@types/md5": "^2.3.1",
3737
"fast-json-patch": "^2.2.1",
38-
"fs-extra": "^9.1.0",
3938
"jest": "^26.6.3",
4039
"json-diff": "^0.5.4",
4140
"sort-json": "^2.0.0"
4241
},
4342
"dependencies": {
43+
"fs-extra": "^9.1.0",
4444
"md5": "^2.3.0"
4545
},
4646
"repository": {
+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { createModuleDefinitionFromCfnNamespace } from '../lib';
2+
3+
describe('createModuleDefinitionFromCfnNamespace', () => {
4+
5+
test('base case', () => {
6+
const module = createModuleDefinitionFromCfnNamespace('AWS::EC2');
7+
8+
expect(module).toEqual({
9+
namespace: 'AWS::EC2',
10+
moduleName: 'aws-ec2',
11+
moduleFamily: 'AWS',
12+
moduleBaseName: 'EC2',
13+
packageName: '@aws-cdk/aws-ec2',
14+
dotnetPackage: 'Amazon.CDK.AWS.EC2',
15+
javaGroupId: 'software.amazon.awscdk',
16+
javaPackage: 'services.ec2',
17+
javaArtifactId: 'ec2',
18+
pythonDistName: 'aws-cdk.aws-ec2',
19+
pythonModuleName: 'aws_cdk.aws_ec2',
20+
});
21+
});
22+
23+
test('Serverless is special-cased to SAM', () => {
24+
const module = createModuleDefinitionFromCfnNamespace('AWS::Serverless');
25+
26+
expect(module).toEqual({
27+
namespace: 'AWS::Serverless',
28+
moduleName: 'aws-sam',
29+
moduleFamily: 'AWS',
30+
moduleBaseName: 'SAM',
31+
packageName: '@aws-cdk/aws-sam',
32+
dotnetPackage: 'Amazon.CDK.AWS.SAM',
33+
javaGroupId: 'software.amazon.awscdk',
34+
javaPackage: 'services.sam',
35+
javaArtifactId: 'sam',
36+
pythonDistName: 'aws-cdk.aws-sam',
37+
pythonModuleName: 'aws_cdk.aws_sam',
38+
});
39+
});
40+
41+
test('Java artifacts use different package/artifact when module family is not AWS', () => {
42+
const module = createModuleDefinitionFromCfnNamespace('Alexa::ASK');
43+
44+
expect(module).toEqual({
45+
namespace: 'Alexa::ASK',
46+
moduleName: 'alexa-ask',
47+
moduleFamily: 'Alexa',
48+
moduleBaseName: 'ASK',
49+
packageName: '@aws-cdk/alexa-ask',
50+
dotnetPackage: 'Amazon.CDK.Alexa.ASK',
51+
javaGroupId: 'software.amazon.awscdk',
52+
javaPackage: 'alexa.ask',
53+
javaArtifactId: 'alexa-ask',
54+
pythonDistName: 'aws-cdk.alexa-ask',
55+
pythonModuleName: 'aws_cdk.alexa_ask',
56+
});
57+
});
58+
59+
});

Diff for: tools/@aws-cdk/ubergen/bin/ubergen.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as console from 'console';
22
import * as path from 'path';
33
import * as process from 'process';
44
import cfn2ts from '@aws-cdk/cfn2ts';
5+
import * as cfnspec from '@aws-cdk/cfnspec';
56
import * as fs from 'fs-extra';
67
import * as ts from 'typescript';
78

@@ -284,12 +285,15 @@ async function transformPackage(
284285
const destinationLib = path.join(destination, 'lib');
285286
await fs.mkdirp(destinationLib);
286287
await cfn2ts(cfnScopes, destinationLib);
288+
287289
// create a lib/index.ts which only exports the generated files
288290
fs.writeFileSync(path.join(destinationLib, 'index.ts'),
289291
/// logic copied from `create-missing-libraries.ts`
290292
cfnScopes.map(s => (s === 'AWS::Serverless' ? 'AWS::SAM' : s).split('::')[1].toLocaleLowerCase())
291293
.map(s => `export * from './${s}.generated';`)
292294
.join('\n'));
295+
await cfnspec.createLibraryReadme(cfnScopes[0], path.join(destination, 'README.md'));
296+
293297
await copyOrTransformFiles(destination, destination, allLibraries, uberPackageJson);
294298
} else {
295299
await copyOrTransformFiles(library.root, destination, allLibraries, uberPackageJson);
@@ -395,9 +399,14 @@ async function copyOrTransformFiles(from: string, to: string, libraries: readonl
395399
}
396400
await fs.writeJson(destination, cfnTypes2Classes, { spaces: 2 });
397401
} else if (name === 'README.md') {
402+
// Rewrite the README to both adjust imports and remove the redundant stability banner.
403+
// (All modules included in ubergen-ed packages must be stable, so the banner is unnecessary.)
404+
const newReadme = (await rewriteReadmeImports(source))
405+
.replace(/<!--BEGIN STABILITY BANNER-->[\s\S]+<!--END STABILITY BANNER-->/gm, '');
406+
398407
return fs.writeFile(
399408
destination,
400-
await rewriteReadmeImports(source),
409+
newReadme,
401410
{ encoding: 'utf8' },
402411
);
403412
} else {

Diff for: tools/@aws-cdk/ubergen/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
},
3636
"dependencies": {
3737
"@aws-cdk/cfn2ts": "0.0.0",
38+
"@aws-cdk/cfnspec": "0.0.0",
3839
"fs-extra": "^9.1.0",
3940
"typescript": "~3.9.10"
4041
},

0 commit comments

Comments
 (0)