UNPKG

jsii

Version:

[![Join the chat at https://cdk.Dev](https://img.shields.io/static/v1?label=Slack&message=cdk.dev&color=brightgreen&logo=slack)](https://cdk.dev) [![All Contributors](https://img.shields.io/github/all-contributors/aws/jsii/main?label=%E2%9C%A8%20All%20Con

158 lines (138 loc) 5.19 kB
// +------------------------------------------------------------------------------------------------ // | 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); }