From 1176a73050b45422d42cef1a0dc66eb88b31c104 Mon Sep 17 00:00:00 2001 From: Juan Pablo Garcia Ripa Date: Wed, 30 Nov 2022 23:51:05 +0100 Subject: [PATCH] use package.json workspace package as default roots Signed-off-by: Juan Pablo Garcia Ripa --- package.json | 2 +- packages/repo-tools/cli-report.md | 5 +- packages/repo-tools/package.json | 4 + .../src/commands/api-reports/api-extractor.ts | 73 ++++++++----------- .../src/commands/api-reports/api-reports.ts | 38 +++++----- packages/repo-tools/src/commands/index.ts | 10 +-- yarn.lock | 9 +++ 7 files changed, 69 insertions(+), 72 deletions(-) diff --git a/package.json b/package.json index 524cdf4bbe..497a652cdf 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "build:backend": "yarn workspace backend build", "build:all": "backstage-cli repo build --all", "build:api-reports": "yarn build:api-reports:only --tsc", - "build:api-reports:only": "backstage-repo-tools api-reports", + "build:api-reports:only": "backstage-repo-tools api-reports --allow-warnings packages/core-components plugins/catalog plugins/catalog-import plugins/git-release-manager plugins/jenkins plugins/kubernetes", "build:api-docs": "LANG=en_EN yarn build:api-reports --docs", "tsc": "tsc", "tsc:full": "backstage-cli repo clean && tsc --skipLibCheck false --incremental false", diff --git a/packages/repo-tools/cli-report.md b/packages/repo-tools/cli-report.md index b2a171cf42..ba15ecc674 100644 --- a/packages/repo-tools/cli-report.md +++ b/packages/repo-tools/cli-report.md @@ -12,7 +12,7 @@ Options: -h, --help Commands: - api-reports [options] [path...] + api-reports [options] [paths...] type-deps help [command] ``` @@ -20,14 +20,13 @@ Commands: ### `backstage-repo-tools api-reports` ``` -Usage: backstage-repo-tools api-reports [options] [path...] +Usage: backstage-repo-tools api-reports [options] [paths...] Options: --ci --tsc --docs --allow-warnings [allowWarningsPaths...] - --folders --omitMessages -h, --help ``` diff --git a/packages/repo-tools/package.json b/packages/repo-tools/package.json index b779b0798f..657bbb4404 100644 --- a/packages/repo-tools/package.json +++ b/packages/repo-tools/package.json @@ -40,8 +40,12 @@ "chalk": "^4.0.0", "commander": "^9.1.0", "fs-extra": "10.1.0", + "is-glob": "^4.0.3", "ts-node": "^10.0.0" }, + "devDependencies": { + "@types/is-glob": "^4.0.2" + }, "files": [ "bin", "dist/**/*.js" diff --git a/packages/repo-tools/src/commands/api-reports/api-extractor.ts b/packages/repo-tools/src/commands/api-reports/api-extractor.ts index 9f4f9b238d..d1e8d86240 100644 --- a/packages/repo-tools/src/commands/api-reports/api-extractor.ts +++ b/packages/repo-tools/src/commands/api-reports/api-extractor.ts @@ -67,8 +67,14 @@ import { IMarkdownEmitterContext } from '@microsoft/api-documenter/lib/markdown/ import { AstDeclaration } from '@microsoft/api-extractor/lib/analyzer/AstDeclaration'; import { paths as cliPaths } from '../../lib/paths'; -const tmpDir = resolvePath( - cliPaths.targetRoot, +import g from 'glob'; +import isGlob from 'is-glob'; + +import { promisify } from 'util'; + +const glob = promisify(g); + +const tmpDir = cliPaths.resolveTargetRoot( './node_modules/.cache/api-extractor', ); @@ -220,11 +226,10 @@ ApiReportGenerator.generateReviewFileContent = }); }; -async function resolvePackagePath( +export async function resolvePackagePath( packagePath: string, ): Promise { - const projectRoot = resolvePath(cliPaths.targetRoot); - const fullPackageDir = resolvePath(projectRoot, packagePath); + const fullPackageDir = cliPaths.resolveTargetRoot(packagePath); const stat = await fs.stat(fullPackageDir); if (!stat.isDirectory()) { @@ -237,49 +242,29 @@ async function resolvePackagePath( } catch (_) { return undefined; } - - return relativePath(projectRoot, fullPackageDir); + return relativePath(cliPaths.targetRoot, fullPackageDir); } -export async function findSpecificPackageDirs(unresolvedPackageDirs: string[]) { +export async function findPackageDirs(selectedPaths: string[]) { const packageDirs = new Array(); + for (const packageRoot of selectedPaths) { + const fullPath = cliPaths.resolveTargetRoot(packageRoot); - for (const unresolvedPackageDir of unresolvedPackageDirs) { - const packageDir = await resolvePackagePath(unresolvedPackageDir); - if (!packageDir) { - throw new Error(`'${unresolvedPackageDir}' is not a valid package path`); - } - packageDirs.push(packageDir); - } - - if (packageDirs.length === 0) { - return undefined; - } - - return packageDirs; -} - -export async function findPackageDirs(packageRoots: string[]) { - const packageDirs = new Array(); - const projectRoot = resolvePath(cliPaths.targetRoot); - - for (const packageRoot of packageRoots) { - const dirs = await fs.readdir(resolvePath(projectRoot, packageRoot)); + // if the path contain any glob notation we resolve all the paths to process one by one + const dirs = isGlob(fullPath) ? await glob(fullPath) : [fullPath]; for (const dir of dirs) { - const packageDir = await resolvePackagePath(join(packageRoot, dir)); + const packageDir = await resolvePackagePath(dir); if (!packageDir) { continue; } - packageDirs.push(packageDir); } } - return packageDirs; } export async function createTemporaryTsConfig(includedPackageDirs: string[]) { - const path = resolvePath(cliPaths.targetRoot, 'tsconfig.tmp.json'); + const path = cliPaths.resolveTargetRoot('tsconfig.tmp.json'); process.once('exit', () => { fs.removeSync(path); @@ -380,8 +365,7 @@ export async function runApiExtraction({ await fs.remove(outputDir); const entryPoints = packageDirs.map(packageDir => { - return resolvePath( - cliPaths.targetRoot, + return cliPaths.resolveTargetRoot( `./dist-types/${packageDir}/src/index.d.ts`, ); }); @@ -404,9 +388,8 @@ export async function runApiExtraction({ ? allowWarnings.includes(packageDir) : allowWarnings; - const projectFolder = resolvePath(cliPaths.targetRoot, packageDir); - const packageFolder = resolvePath( - cliPaths.targetRoot, + const projectFolder = cliPaths.resolveTargetRoot(packageDir); + const packageFolder = cliPaths.resolveTargetRoot( './dist-types', packageDir, ); @@ -1138,10 +1121,7 @@ export async function buildDocs({ documenter.generateFiles(); } -export async function categorizePackageDirs( - projectRoot: string, - packageDirs: any[], -) { +export async function categorizePackageDirs(packageDirs: any[]) { const dirs = packageDirs.slice(); const tsPackageDirs = new Array(); const cliPackageDirs = new Array(); @@ -1157,7 +1137,7 @@ export async function categorizePackageDirs( } const pkgJson = await fs - .readJson(resolvePath(projectRoot, dir, 'package.json')) + .readJson(cliPaths.resolveTargetRoot(dir, 'package.json')) .catch(error => { if (error.code === 'ENOENT') { return undefined; @@ -1211,6 +1191,7 @@ function parseHelpPage(helpPageContent: string) { let options = new Array(); let commands = new Array(); + let commandArguments = new Array(); while (lines.length > 0) { while (lines.length > 0 && !lines[0].endsWith(':')) { @@ -1235,6 +1216,8 @@ function parseHelpPage(helpPageContent: string) { options = sectionItems; } else if (sectionName?.toLocaleLowerCase('en-US') === 'commands:') { commands = sectionItems; + } else if (sectionName?.toLocaleLowerCase('en-US') === 'arguments:') { + commandArguments = sectionItems; } else { throw new Error(`Unknown CLI section: ${sectionName}`); } @@ -1245,6 +1228,7 @@ function parseHelpPage(helpPageContent: string) { usage, options, commands, + commandArguments, }; } @@ -1256,6 +1240,7 @@ interface CliHelpPage { usage: string | undefined; options: string[]; commands: string[]; + commandArguments: string[]; } async function exploreCliHelpPages( @@ -1335,7 +1320,7 @@ export async function runCliExtraction({ }: CliExtractionOptions) { for (const packageDir of packageDirs) { console.log(`## Processing ${packageDir}`); - const fullDir = resolvePath(projectRoot, packageDir); + const fullDir = cliPaths.resolveTargetRoot(packageDir); const pkgJson = await fs.readJson(resolvePath(fullDir, 'package.json')); if (!pkgJson.bin) { diff --git a/packages/repo-tools/src/commands/api-reports/api-reports.ts b/packages/repo-tools/src/commands/api-reports/api-reports.ts index c66d084d64..9b0d78d6a8 100644 --- a/packages/repo-tools/src/commands/api-reports/api-reports.ts +++ b/packages/repo-tools/src/commands/api-reports/api-reports.ts @@ -19,7 +19,6 @@ import { resolve as resolvePath } from 'path'; import fs from 'fs-extra'; import { spawnSync } from 'child_process'; import { - findSpecificPackageDirs, createTemporaryTsConfig, findPackageDirs, categorizePackageDirs, @@ -30,14 +29,6 @@ import { import { paths as cliPaths } from '../../lib/paths'; export default async (paths: string[], opts: OptionValues) => { - console.log(opts); - console.log({ - ownDir: cliPaths.ownDir, - ownRoot: cliPaths.ownRoot, - targetDir: cliPaths.targetDir, - targetRoot: cliPaths.targetRoot, - 'process.cwd()': process.cwd(), - }); const tmpDir = resolvePath( cliPaths.targetRoot, './node_modules/.cache/api-extractor', @@ -47,25 +38,26 @@ export default async (paths: string[], opts: OptionValues) => { const isCiBuild = opts.ci; const isDocsBuild = opts.docs; const runTsc = opts.tsc; - const packageRoots = opts.folders; + const selectedPaths = paths.length ? paths : await getWorkspacePkgs(); const allowWarnings: boolean | string[] = opts.allowWarnings; const omitMessages = opts.omitMessages; - const selectedPackageDirs = await findSpecificPackageDirs(paths); + const selectedPackageDirs = await findPackageDirs(selectedPaths); - if (selectedPackageDirs && isCiBuild) { + if (paths.length && isCiBuild) { + // TODO @sarabadu we can remove this validation to allow `/plugins/*` on CI?? throw new Error( 'Package path arguments are not supported together with the --ci flag', ); } - if (!selectedPackageDirs && !isCiBuild && !isDocsBuild) { + if (!paths.length && !isCiBuild && !isDocsBuild) { console.log(''); console.log( 'TIP: You can generate api-reports for select packages by passing package paths:', ); console.log(''); console.log( - ' yarn build:api-reports packages/config packages/core-plugin-api', + ' yarn build:api-reports packages/config packages/core-plugin-api plugins/*', ); console.log(''); } @@ -98,12 +90,8 @@ export default async (paths: string[], opts: OptionValues) => { } } - const packageDirs = - selectedPackageDirs ?? (await findPackageDirs(packageRoots)); - const { tsPackageDirs, cliPackageDirs } = await categorizePackageDirs( - projectRoot, - packageDirs, + selectedPackageDirs, ); if (tsPackageDirs.length > 0) { @@ -134,3 +122,15 @@ export default async (paths: string[], opts: OptionValues) => { }); } }; +async function getWorkspacePkgs() { + const pkgJson = await fs + .readJson(cliPaths.resolveTargetRoot('package.json')) + .catch(error => { + if (error.code === 'ENOENT') { + return undefined; + } + throw error; + }); + const workspaces = pkgJson?.workspaces?.packages; + return workspaces; +} diff --git a/packages/repo-tools/src/commands/index.ts b/packages/repo-tools/src/commands/index.ts index 5821dfdd3d..bbc6773f83 100644 --- a/packages/repo-tools/src/commands/index.ts +++ b/packages/repo-tools/src/commands/index.ts @@ -20,7 +20,11 @@ import { exitWithError } from '../lib/errors'; export function registerCommands(program: Command) { program - .command('api-reports [path...]') + .command('api-reports') + .argument( + '[paths...]', + 'path of package folder to extract API reports, `workspaces.packages` from root packages.json by default', + ) .option('--ci', 'CI run checks that there is no changes on API reports') .option('--tsc', 'executes the tsc compilation before extracting the APIs') .option('--docs', 'generates the api documentation') @@ -29,10 +33,6 @@ export function registerCommands(program: Command) { 'continue processing packages after getting errors on selected packages', false, ) - .option('--folders ', 'packages folder containers', [ - 'packages', - 'plugins', - ]) .option( '--omitMessages ', 'select some message code to be omited on the API Extractor (i.e ae-cyclic-inherit-doc)', diff --git a/yarn.lock b/yarn.lock index e39514bb98..c9a9d1daea 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8474,9 +8474,11 @@ __metadata: "@microsoft/api-extractor": ^7.23.0 "@microsoft/api-extractor-model": ^7.17.2 "@microsoft/tsdoc": 0.14.1 + "@types/is-glob": ^4.0.2 chalk: ^4.0.0 commander: ^9.1.0 fs-extra: 10.1.0 + is-glob: ^4.0.3 ts-node: ^10.0.0 bin: backstage-repo-tools: bin/backstage-repo-tools @@ -14201,6 +14203,13 @@ __metadata: languageName: node linkType: hard +"@types/is-glob@npm:^4.0.2": + version: 4.0.2 + resolution: "@types/is-glob@npm:4.0.2" + checksum: 50b0a52b6d179781b36bfce35155e1e0dc66b62e2943153d7d7c7079c40ba6236528a254de8be6c52ff9a7a351996887802efd7fd763da3e2121315e4ffe2edf + languageName: node + linkType: hard + "@types/istanbul-lib-coverage@npm:*, @types/istanbul-lib-coverage@npm:^2.0.0, @types/istanbul-lib-coverage@npm:^2.0.1": version: 2.0.1 resolution: "@types/istanbul-lib-coverage@npm:2.0.1"