use package.json workspace package as default roots

Signed-off-by: Juan Pablo Garcia Ripa <juanpablog@spotify.com>
This commit is contained in:
Juan Pablo Garcia Ripa
2022-11-30 23:51:05 +01:00
parent b56bfd12de
commit 1176a73050
7 changed files with 69 additions and 72 deletions
+1 -1
View File
@@ -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",
+2 -3
View File
@@ -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 <folders...>
--omitMessages <messageCodes...>
-h, --help
```
+4
View File
@@ -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"
@@ -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<string | undefined> {
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<string>();
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<string>();
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<string>();
const cliPackageDirs = new Array<string>();
@@ -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<string>();
let commands = new Array<string>();
let commandArguments = new Array<string>();
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) {
@@ -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;
}
+5 -5
View File
@@ -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 <folders...>', 'packages folder containers', [
'packages',
'plugins',
])
.option(
'--omitMessages <messageCodes...>',
'select some message code to be omited on the API Extractor (i.e ae-cyclic-inherit-doc)',
+9
View File
@@ -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"