use package.json workspace package as default roots
Signed-off-by: Juan Pablo Garcia Ripa <juanpablog@spotify.com>
This commit is contained in:
+1
-1
@@ -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",
|
||||
|
||||
@@ -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
|
||||
```
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)',
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user