feat: introduce backstage repo tools package
Signed-off-by: djamaile <rdjamaile@gmail.com>
This commit is contained in:
committed by
Juan Pablo Garcia Ripa
parent
fb18925780
commit
c72656e719
@@ -10,6 +10,8 @@
|
||||
"start-backend": "yarn workspace example-backend start",
|
||||
"build:backend": "yarn workspace backend build",
|
||||
"build:all": "backstage-cli repo build --all",
|
||||
"build": "backstage-cli repo build --all",
|
||||
"build:api-reports-tooling": "backstage-repo-tools api-reports",
|
||||
"build:api-reports": "yarn build:api-reports:only --tsc",
|
||||
"build:api-reports:only": "ts-node -T -P scripts/tsconfig.json scripts/api-extractor.ts",
|
||||
"build:api-docs": "LANG=en_EN yarn build:api-reports --docs",
|
||||
@@ -59,6 +61,7 @@
|
||||
"@backstage/cli": "workspace:*",
|
||||
"@backstage/codemods": "workspace:*",
|
||||
"@backstage/create-app": "workspace:*",
|
||||
"@backstage/repo-tools": "workspace:*",
|
||||
"@changesets/cli": "^2.14.0",
|
||||
"@octokit/rest": "^19.0.3",
|
||||
"@spotify/prettier-config": "^14.0.0",
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
module.exports = require('@backstage/cli/config/eslint-factory')(__dirname, {
|
||||
ignorePatterns: ['templates/**'],
|
||||
rules: {
|
||||
'no-console': 0,
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env node
|
||||
/*
|
||||
* Copyright 2022 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
|
||||
// Figure out whether we're running inside the backstage repo or as an installed dependency
|
||||
/* eslint-disable-next-line no-restricted-syntax */
|
||||
const isLocal = require('fs').existsSync(path.resolve(__dirname, '../src'));
|
||||
|
||||
if (!isLocal || process.env.BACKSTAGE_E2E_CLI_TEST) {
|
||||
require('..');
|
||||
} else {
|
||||
require('ts-node').register({
|
||||
transpileOnly: true,
|
||||
/* eslint-disable-next-line no-restricted-syntax */
|
||||
project: path.resolve(__dirname, '../../../tsconfig.json'),
|
||||
compilerOptions: {
|
||||
module: 'CommonJS',
|
||||
},
|
||||
});
|
||||
|
||||
require('../src');
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"name": "@backstage/repo-tools",
|
||||
"description": "",
|
||||
"version": "0.0.0",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"backstage": {
|
||||
"role": "cli"
|
||||
},
|
||||
"homepage": "https://backstage.io",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/backstage/backstage",
|
||||
"directory": "packages/repo-tools"
|
||||
},
|
||||
"keywords": [
|
||||
"backstage"
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"main": "dist/index.cjs.js",
|
||||
"scripts": {
|
||||
"build": "backstage-cli package build",
|
||||
"lint": "backstage-cli package lint",
|
||||
"test": "backstage-cli package test",
|
||||
"clean": "backstage-cli package clean",
|
||||
"start": "nodemon --"
|
||||
},
|
||||
"bin": {
|
||||
"backstage-repo-tools": "bin/backstage-repo-tools"
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/errors": "workspace:^",
|
||||
"chalk": "^4.0.0",
|
||||
"commander": "^9.1.0",
|
||||
"fs-extra": "10.1.0",
|
||||
"ts-node": "^10.0.0"
|
||||
},
|
||||
"files": [
|
||||
"asset-types",
|
||||
"templates",
|
||||
"config",
|
||||
"bin",
|
||||
"dist/**/*.js"
|
||||
],
|
||||
"nodemonConfig": {
|
||||
"watch": "./src",
|
||||
"exec": "bin/backstage-repo-tools",
|
||||
"ext": "ts"
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright 2022 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { OptionValues } from 'commander';
|
||||
import {resolve as resolvePath} from 'path';
|
||||
import fs from 'fs-extra';
|
||||
import { spawnSync } from 'child_process';
|
||||
import {resolvePackagePath} from "@backstage/backend-common"
|
||||
import {findSpecificPackageDirs, createTemporaryTsConfig, findPackageDirs, categorizePackageDirs, runApiExtraction, runCliExtraction, buildDocs} from './api-extractor';
|
||||
|
||||
export default async (paths:string[], opts: OptionValues ) => {
|
||||
if(opts.ci){
|
||||
process.stderr.write(
|
||||
`hello ci`,
|
||||
);
|
||||
}
|
||||
console.log(opts, paths)
|
||||
process.stderr.write(
|
||||
`hello `,
|
||||
);
|
||||
|
||||
const tmpDir = resolvePath('./node_modules/.cache/api-extractor');
|
||||
const projectRoot = resolvePath(process.cwd());
|
||||
console.log(`DIRNAME: ${__dirname}, ${projectRoot}`)
|
||||
const isCiBuild = opts.ci;
|
||||
const isDocsBuild = opts.docs;
|
||||
const runTsc = opts.tsc;
|
||||
|
||||
const selectedPackageDirs = await findSpecificPackageDirs(paths
|
||||
);
|
||||
if (selectedPackageDirs && isCiBuild) {
|
||||
throw new Error(
|
||||
'Package path arguments are not supported together with the --ci flag',
|
||||
);
|
||||
}
|
||||
if (!selectedPackageDirs && !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',
|
||||
);
|
||||
console.log('');
|
||||
}
|
||||
|
||||
let temporaryTsConfigPath: string | undefined;
|
||||
if (selectedPackageDirs) {
|
||||
temporaryTsConfigPath = await createTemporaryTsConfig(selectedPackageDirs);
|
||||
}
|
||||
const tsconfigFilePath =
|
||||
temporaryTsConfigPath ?? resolvePath(projectRoot, 'tsconfig.json');
|
||||
|
||||
if (runTsc) {
|
||||
await fs.remove(resolvePath(projectRoot, 'dist-types'));
|
||||
const { status } = spawnSync(
|
||||
'yarn',
|
||||
[
|
||||
'tsc',
|
||||
['--project', tsconfigFilePath],
|
||||
['--skipLibCheck', 'false'],
|
||||
['--incremental', 'false'],
|
||||
].flat(),
|
||||
{
|
||||
stdio: 'inherit',
|
||||
shell: true,
|
||||
cwd: projectRoot,
|
||||
},
|
||||
);
|
||||
if (status !== 0) {
|
||||
process.exit(status || undefined);
|
||||
}
|
||||
}
|
||||
|
||||
const packageDirs = selectedPackageDirs ?? (await findPackageDirs());
|
||||
|
||||
const { tsPackageDirs, cliPackageDirs } = await categorizePackageDirs(
|
||||
projectRoot,
|
||||
packageDirs,
|
||||
);
|
||||
|
||||
if (tsPackageDirs.length > 0) {
|
||||
console.log('# Generating package API reports');
|
||||
await runApiExtraction({
|
||||
packageDirs: tsPackageDirs,
|
||||
outputDir: tmpDir,
|
||||
isLocalBuild: !isCiBuild,
|
||||
tsconfigFilePath,
|
||||
});
|
||||
}
|
||||
if (cliPackageDirs.length > 0) {
|
||||
console.log('# Generating package CLI reports');
|
||||
await runCliExtraction({
|
||||
projectRoot,
|
||||
packageDirs: cliPackageDirs,
|
||||
isLocalBuild: !isCiBuild,
|
||||
});
|
||||
}
|
||||
|
||||
if (isDocsBuild) {
|
||||
console.log('# Generating package documentation');
|
||||
await buildDocs({
|
||||
inputDir: tmpDir,
|
||||
outputDir: resolvePath(projectRoot, 'docs/reference'),
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2022 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { assertError } from '@backstage/errors';
|
||||
import { Command } from 'commander';
|
||||
import { exitWithError } from '../lib/errors';
|
||||
|
||||
const configOption = [
|
||||
'--config <path>',
|
||||
'Config files to load instead of app-config.yaml',
|
||||
(opt: string, opts: string[]) => (opts ? [...opts, opt] : [opt]),
|
||||
Array<string>(),
|
||||
] as const;
|
||||
|
||||
export function registerCommands(program: Command) {
|
||||
program
|
||||
.command('api-reports [path...]')
|
||||
.option('--ci', 'Do not require environment variables to be set')
|
||||
.option('--tsc', 'Only validate the frontend configuration')
|
||||
.option('--docs', 'Output deprecated configuration settings')
|
||||
.description('Generate an API report for changed packages')
|
||||
.action(
|
||||
lazy(() => import('./api-reports/api-reports').then(m => m.default)),
|
||||
);
|
||||
}
|
||||
|
||||
// Wraps an action function so that it always exits and handles errors
|
||||
function lazy(
|
||||
getActionFunc: () => Promise<(...args: any[]) => Promise<void>>,
|
||||
): (...args: any[]) => Promise<never> {
|
||||
return async (...args: any[]) => {
|
||||
try {
|
||||
const actionFunc = await getActionFunc();
|
||||
await actionFunc(...args);
|
||||
|
||||
process.exit(0);
|
||||
} catch (error) {
|
||||
assertError(error);
|
||||
exitWithError(error);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2020 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* CLI for developing Backstage plugins and apps
|
||||
*
|
||||
* @packageDocumentation
|
||||
*/
|
||||
|
||||
import { program } from 'commander';
|
||||
import chalk from 'chalk';
|
||||
import { exitWithError } from './lib/errors';
|
||||
// import { version } from './lib/version';
|
||||
import { registerCommands } from './commands';
|
||||
|
||||
const main = (argv: string[]) => {
|
||||
program.name('backstage-repo-tools').version('1.0');
|
||||
|
||||
registerCommands(program);
|
||||
|
||||
program.on('command:*', () => {
|
||||
console.log();
|
||||
console.log(chalk.red(`Invalid command: ${program.args.join(' ')}`));
|
||||
console.log();
|
||||
program.outputHelp();
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
program.parse(argv);
|
||||
};
|
||||
|
||||
process.on('unhandledRejection', rejection => {
|
||||
if (rejection instanceof Error) {
|
||||
exitWithError(rejection);
|
||||
} else {
|
||||
exitWithError(new Error(`Unknown rejection: '${rejection}'`));
|
||||
}
|
||||
});
|
||||
|
||||
main(process.argv);
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2020 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import chalk from 'chalk';
|
||||
|
||||
export class CustomError extends Error {
|
||||
get name(): string {
|
||||
return this.constructor.name;
|
||||
}
|
||||
}
|
||||
|
||||
export class ExitCodeError extends CustomError {
|
||||
readonly code: number;
|
||||
|
||||
constructor(code: number, command?: string) {
|
||||
super(
|
||||
command
|
||||
? `Command '${command}' exited with code ${code}`
|
||||
: `Child exited with code ${code}`,
|
||||
);
|
||||
this.code = code;
|
||||
}
|
||||
}
|
||||
|
||||
export function exitWithError(error: Error): never {
|
||||
if (error instanceof ExitCodeError) {
|
||||
process.stderr.write(`\n${chalk.red(error.message)}\n\n`);
|
||||
process.exit(error.code);
|
||||
} else {
|
||||
process.stderr.write(`\n${chalk.red(`${error}`)}\n\n`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
export class NotFoundError extends CustomError {}
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright 2022 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
@@ -7653,6 +7653,20 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@backstage/repo-tools@workspace:*, @backstage/repo-tools@workspace:packages/repo-tools":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@backstage/repo-tools@workspace:packages/repo-tools"
|
||||
dependencies:
|
||||
"@backstage/errors": "workspace:^"
|
||||
chalk: ^4.0.0
|
||||
commander: ^9.1.0
|
||||
fs-extra: 10.1.0
|
||||
ts-node: ^10.0.0
|
||||
bin:
|
||||
backstage-repo-tools: bin/backstage-repo-tools
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@backstage/test-utils@workspace:^, @backstage/test-utils@workspace:packages/test-utils":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@backstage/test-utils@workspace:packages/test-utils"
|
||||
@@ -33054,6 +33068,7 @@ __metadata:
|
||||
"@backstage/codemods": "workspace:*"
|
||||
"@backstage/create-app": "workspace:*"
|
||||
"@backstage/errors": "workspace:^"
|
||||
"@backstage/repo-tools": "workspace:*"
|
||||
"@changesets/cli": ^2.14.0
|
||||
"@manypkg/get-packages": ^1.1.3
|
||||
"@microsoft/api-documenter": ^7.17.11
|
||||
|
||||
Reference in New Issue
Block a user