jsii
Version:
[](https://cdk.dev) [ • 5.19 kB
text/typescript
// +------------------------------------------------------------------------------------------------
// | this script is executed post packaging to verify that experimental modules in aws-cdk-lib includes **only** L1 autogenerated files.
// | The purpose is to avoid publishing L2 of experimental modules with aws-cdk-lib
// |
import { spawnSync } from 'child_process';
import * as console from 'console';
import * as os from 'os';
import * as path from 'path';
import * as fs from 'fs-extra';
async function main(tempDir: string) {
console.log('🧐 Verifying all experimental modules includes only L1s files...');
const cwd = process.cwd();
const awsCdkModulesRepoPath = path.join(findWorkspacePath(), 'packages', '@aws-cdk');
// eslint-disable-next-line @typescript-eslint/no-require-imports
const version = require('./../package.json').version;
const tarFullPath = path.join(cwd, 'dist', 'js', `aws-cdk-lib@${version}.jsii.tgz`);
const invalidCfnModules = new Map<string, Array<String>>();
const invalidModules = new Array<string>();
// install the tarball in a temp directory
console.log(`installing aws-cdk-lib from dist/js into ${tempDir}`);
exec('npm', ['install', '--prefix', tempDir, tarFullPath]);
const installedAwsCdkLibPath = path.join(tempDir, 'node_modules', 'aws-cdk-lib', 'lib');
for (const module of fs.readdirSync(awsCdkModulesRepoPath)) {
// eslint-disable-next-line @typescript-eslint/no-require-imports
const pkgJson = require(path.join(awsCdkModulesRepoPath, module, 'package.json'));
if (pkgJson.stability !== 'experimental') {
continue;
}
if (pkgJson['cdk-build']?.cloudformation) {
// if a cfn module, verify only the allowed files exists
const files = await listAllFiles(path.join(installedAwsCdkLibPath, module));
const invalidFiles = new Array();
files.forEach(file => {
if (!isAllowedFile(file)) {
invalidFiles.push(file);
}
});
if (invalidFiles.length > 0) {
invalidCfnModules.set(module, invalidFiles);
}
} else {
// not a cfn module, verify it was entirely removed
if (fs.existsSync(path.join(installedAwsCdkLibPath, module))) {
invalidModules.push(module);
}
}
}
if (invalidCfnModules.size > 0 || invalidModules.length > 0) {
if (invalidCfnModules.size > 0 ) {
console.log('cfn module with invalid files:');
for (let [module, files] of invalidCfnModules.entries()) {
console.log(`${module}:`);
files.forEach(file => console.log(`\t ${file}`));
}
}
console.log('---------------------------------------------');
if (invalidModules.length > 0) {
console.log('non-cfn experimental modules:');
invalidModules.forEach(m => console.log(`\t ${m}`));
}
throw new Error('Verification Error');
}
}
const tempDir = fs.mkdtempSync(os.tmpdir());
main(tempDir).then(
() => {
fs.removeSync(tempDir);
console.log('✅ All experimental modules includes only L1s files!');
process.exit(0);
},
(err) => {
process.stderr.write(`${err}\n`);
process.stderr.write(`❌ Verification failed, Some experimental modules includes non L1 files, see details above. Inspect working directory: '${tempDir}'`);
process.exit(1);
},
);
/**
* Spawn sync with error handling
*/
function exec(cmd: string, args: string[]) {
const proc = spawnSync(cmd, args);
if (proc.error) {
throw proc.error;
}
if (proc.status !== 0) {
if (proc.stdout || proc.stderr) {
throw new Error(`${cmd} exited with status ${proc.status}; stdout: ${proc.stdout?.toString().trim()}\n\n\nstderr: ${proc.stderr?.toString().trim()}`);
}
throw new Error(`${cmd} exited with status ${proc.status}`);
}
return proc;
}
const GENERATED_SUFFIX_REGEX = new RegExp(/generated\.(js|d\.ts)$/);
const ALLOWED_FILES = ['.jsiirc.json', 'index.ts', 'index.js', 'index.d.ts'];
/**
* Recursively collect all files in dir
*/
async function listAllFiles(dir: string) {
const ret = new Array();
async function recurse(part: string) {
const files = await fs.readdir(part);
for (const file of files) {
const fullPath = path.join(part, file);
if ((await fs.stat(fullPath)).isDirectory()) {
await recurse(fullPath);
} else {
ret.push(file);
}
}
}
await recurse(dir);
return ret;
}
/**
* Find the workspace root path. Walk up the directory tree until you find lerna.json
*/
function findWorkspacePath() {
return _findRootPath(process.cwd());
function _findRootPath(part: string): string {
if (part === path.resolve(part, '..')) {
throw new Error('couldn\'t find a \'lerna.json\' file when walking up the directory tree, are you in a aws-cdk project?');
}
if (fs.existsSync(path.resolve(part, 'lerna.json'))) {
return part;
}
return _findRootPath(path.resolve(part, '..'));
}
}
/**
* @param file
* @returns true if the file allowed in an L1 only modules, otherwise false
*/
function isAllowedFile(file: string) {
if (GENERATED_SUFFIX_REGEX.test(file)) {
return true;
}
return ALLOWED_FILES.includes(file);
}