Add automatic discovery of CLI modules from project dependencies
The CLI now scans the project root's dependencies and devDependencies for packages with the cli-module role, loading them automatically. Falls back to the built-in set with a deprecation warning when no modules are found. Updated create-app templates and the monorepo root to include all CLI modules as explicit devDependencies. Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> Made-with: Cursor
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
---
|
||||
'@backstage/cli': minor
|
||||
---
|
||||
|
||||
The CLI now automatically discovers CLI modules from the project root's `dependencies` and `devDependencies`. Any installed package with the `cli-module` Backstage role will be loaded automatically without needing to be hardcoded in the CLI itself.
|
||||
|
||||
If no CLI modules are found in the project dependencies, the CLI falls back to the built-in set of modules and prints a deprecation warning. This fallback will be removed in a future release. To prepare for this, add the following CLI modules as `devDependencies` in your root `package.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"devDependencies": {
|
||||
"@backstage/cli-module-auth": "backstage:^",
|
||||
"@backstage/cli-module-build": "backstage:^",
|
||||
"@backstage/cli-module-config": "backstage:^",
|
||||
"@backstage/cli-module-create-github-app": "backstage:^",
|
||||
"@backstage/cli-module-info": "backstage:^",
|
||||
"@backstage/cli-module-lint": "backstage:^",
|
||||
"@backstage/cli-module-maintenance": "backstage:^",
|
||||
"@backstage/cli-module-migrate": "backstage:^",
|
||||
"@backstage/cli-module-new": "backstage:^",
|
||||
"@backstage/cli-module-test-jest": "backstage:^",
|
||||
"@backstage/cli-module-translations": "backstage:^"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
If you are not using the Backstage Yarn plugin, run the following instead:
|
||||
|
||||
```sh
|
||||
yarn workspace root add --dev @backstage/cli-module-auth @backstage/cli-module-build @backstage/cli-module-config @backstage/cli-module-create-github-app @backstage/cli-module-info @backstage/cli-module-lint @backstage/cli-module-maintenance @backstage/cli-module-migrate @backstage/cli-module-new @backstage/cli-module-test-jest @backstage/cli-module-translations
|
||||
```
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/create-app': patch
|
||||
---
|
||||
|
||||
The create-app templates now include all standard `@backstage/cli-module-*` packages as `devDependencies`, enabling the CLI's automatic module discovery for newly created projects.
|
||||
@@ -125,6 +125,17 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "workspace:*",
|
||||
"@backstage/cli-module-auth": "workspace:*",
|
||||
"@backstage/cli-module-build": "workspace:*",
|
||||
"@backstage/cli-module-config": "workspace:*",
|
||||
"@backstage/cli-module-create-github-app": "workspace:*",
|
||||
"@backstage/cli-module-info": "workspace:*",
|
||||
"@backstage/cli-module-lint": "workspace:*",
|
||||
"@backstage/cli-module-maintenance": "workspace:*",
|
||||
"@backstage/cli-module-migrate": "workspace:*",
|
||||
"@backstage/cli-module-new": "workspace:*",
|
||||
"@backstage/cli-module-test-jest": "workspace:*",
|
||||
"@backstage/cli-module-translations": "workspace:*",
|
||||
"@backstage/codemods": "workspace:*",
|
||||
"@backstage/create-app": "workspace:*",
|
||||
"@backstage/e2e-test-utils": "workspace:*",
|
||||
|
||||
+35
-11
@@ -14,20 +14,44 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import chalk from 'chalk';
|
||||
import { CliInitializer } from './wiring/CliInitializer';
|
||||
import { discoverCliModules } from './wiring/discoverCliModules';
|
||||
|
||||
(async () => {
|
||||
const initializer = new CliInitializer();
|
||||
initializer.add(import('@backstage/cli-module-build'));
|
||||
initializer.add(import('@backstage/cli-module-config'));
|
||||
initializer.add(import('@backstage/cli-module-create-github-app'));
|
||||
initializer.add(import('@backstage/cli-module-info'));
|
||||
initializer.add(import('@backstage/cli-module-lint'));
|
||||
initializer.add(import('@backstage/cli-module-maintenance'));
|
||||
initializer.add(import('@backstage/cli-module-migrate'));
|
||||
initializer.add(import('@backstage/cli-module-new'));
|
||||
initializer.add(import('@backstage/cli-module-test-jest'));
|
||||
initializer.add(import('@backstage/cli-module-translations'));
|
||||
initializer.add(import('@backstage/cli-module-auth'));
|
||||
|
||||
const discoveredModules = discoverCliModules();
|
||||
|
||||
if (discoveredModules.length > 0) {
|
||||
for (const moduleName of discoveredModules) {
|
||||
initializer.add(import(moduleName));
|
||||
}
|
||||
} else {
|
||||
// No CLI modules found in the project root; fall back to the built-in
|
||||
// set while printing a deprecation warning.
|
||||
console.error(
|
||||
chalk.yellow(
|
||||
`No CLI modules found in the project root dependencies. ` +
|
||||
`Falling back to the built-in set of modules.\n` +
|
||||
`This fallback will be removed in a future release. ` +
|
||||
`Please add the CLI modules you need as devDependencies ` +
|
||||
`in your root package.json.\n`,
|
||||
),
|
||||
);
|
||||
|
||||
initializer.add(import('@backstage/cli-module-build'));
|
||||
initializer.add(import('@backstage/cli-module-config'));
|
||||
initializer.add(import('@backstage/cli-module-create-github-app'));
|
||||
initializer.add(import('@backstage/cli-module-info'));
|
||||
initializer.add(import('@backstage/cli-module-lint'));
|
||||
initializer.add(import('@backstage/cli-module-maintenance'));
|
||||
initializer.add(import('@backstage/cli-module-migrate'));
|
||||
initializer.add(import('@backstage/cli-module-new'));
|
||||
initializer.add(import('@backstage/cli-module-test-jest'));
|
||||
initializer.add(import('@backstage/cli-module-translations'));
|
||||
initializer.add(import('@backstage/cli-module-auth'));
|
||||
}
|
||||
|
||||
await initializer.run();
|
||||
})();
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2024 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 { targetPaths } from '@backstage/cli-common';
|
||||
import { PackageRoles } from '@backstage/cli-node';
|
||||
import fs from 'node:fs';
|
||||
import { resolve as resolvePath } from 'node:path';
|
||||
|
||||
/**
|
||||
* Scans the target project root's package.json for dependencies that are CLI
|
||||
* modules (packages with `backstage.role === 'cli-module'`).
|
||||
*
|
||||
* Returns the names of discovered CLI module packages, or an empty array if
|
||||
* none are found or the project root cannot be read.
|
||||
*/
|
||||
export function discoverCliModules(): string[] {
|
||||
const rootDir = targetPaths.rootDir;
|
||||
const pkgJsonPath = resolvePath(rootDir, 'package.json');
|
||||
|
||||
let projectPkg: {
|
||||
dependencies?: Record<string, string>;
|
||||
devDependencies?: Record<string, string>;
|
||||
};
|
||||
try {
|
||||
projectPkg = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf8'));
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
|
||||
const allDeps = {
|
||||
...projectPkg.dependencies,
|
||||
...projectPkg.devDependencies,
|
||||
};
|
||||
|
||||
const modules: string[] = [];
|
||||
|
||||
for (const depName of Object.keys(allDeps)) {
|
||||
try {
|
||||
const depPkgPath = require.resolve(`${depName}/package.json`, {
|
||||
paths: [rootDir],
|
||||
});
|
||||
const depPkg = JSON.parse(fs.readFileSync(depPkgPath, 'utf8'));
|
||||
if (PackageRoles.getRoleFromPackage(depPkg) === 'cli-module') {
|
||||
modules.push(depName);
|
||||
}
|
||||
} catch {
|
||||
// Skip packages that can't be resolved or read
|
||||
}
|
||||
}
|
||||
|
||||
return modules;
|
||||
}
|
||||
@@ -28,6 +28,17 @@
|
||||
],
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^{{version '@backstage/cli'}}",
|
||||
"@backstage/cli-module-auth": "^{{version '@backstage/cli-module-auth'}}",
|
||||
"@backstage/cli-module-build": "^{{version '@backstage/cli-module-build'}}",
|
||||
"@backstage/cli-module-config": "^{{version '@backstage/cli-module-config'}}",
|
||||
"@backstage/cli-module-create-github-app": "^{{version '@backstage/cli-module-create-github-app'}}",
|
||||
"@backstage/cli-module-info": "^{{version '@backstage/cli-module-info'}}",
|
||||
"@backstage/cli-module-lint": "^{{version '@backstage/cli-module-lint'}}",
|
||||
"@backstage/cli-module-maintenance": "^{{version '@backstage/cli-module-maintenance'}}",
|
||||
"@backstage/cli-module-migrate": "^{{version '@backstage/cli-module-migrate'}}",
|
||||
"@backstage/cli-module-new": "^{{version '@backstage/cli-module-new'}}",
|
||||
"@backstage/cli-module-test-jest": "^{{version '@backstage/cli-module-test-jest'}}",
|
||||
"@backstage/cli-module-translations": "^{{version '@backstage/cli-module-translations'}}",
|
||||
"@backstage/e2e-test-utils": "^{{version '@backstage/e2e-test-utils'}}",
|
||||
"@jest/environment-jsdom-abstract": "^30.0.0",
|
||||
"@playwright/test": "^1.32.3",
|
||||
|
||||
@@ -50,6 +50,17 @@
|
||||
],
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^{{version '@backstage/cli'}}",
|
||||
"@backstage/cli-module-auth": "^{{version '@backstage/cli-module-auth'}}",
|
||||
"@backstage/cli-module-build": "^{{version '@backstage/cli-module-build'}}",
|
||||
"@backstage/cli-module-config": "^{{version '@backstage/cli-module-config'}}",
|
||||
"@backstage/cli-module-create-github-app": "^{{version '@backstage/cli-module-create-github-app'}}",
|
||||
"@backstage/cli-module-info": "^{{version '@backstage/cli-module-info'}}",
|
||||
"@backstage/cli-module-lint": "^{{version '@backstage/cli-module-lint'}}",
|
||||
"@backstage/cli-module-maintenance": "^{{version '@backstage/cli-module-maintenance'}}",
|
||||
"@backstage/cli-module-migrate": "^{{version '@backstage/cli-module-migrate'}}",
|
||||
"@backstage/cli-module-new": "^{{version '@backstage/cli-module-new'}}",
|
||||
"@backstage/cli-module-test-jest": "^{{version '@backstage/cli-module-test-jest'}}",
|
||||
"@backstage/cli-module-translations": "^{{version '@backstage/cli-module-translations'}}",
|
||||
"@backstage/e2e-test-utils": "^{{version '@backstage/e2e-test-utils'}}",
|
||||
"@jest/environment-jsdom-abstract": "^30.0.0",
|
||||
"@playwright/test": "^1.32.3",
|
||||
|
||||
@@ -2801,7 +2801,7 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@backstage/cli-module-auth@workspace:^, @backstage/cli-module-auth@workspace:packages/cli-module-auth":
|
||||
"@backstage/cli-module-auth@workspace:*, @backstage/cli-module-auth@workspace:^, @backstage/cli-module-auth@workspace:packages/cli-module-auth":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@backstage/cli-module-auth@workspace:packages/cli-module-auth"
|
||||
dependencies:
|
||||
@@ -2824,7 +2824,7 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@backstage/cli-module-build@workspace:^, @backstage/cli-module-build@workspace:packages/cli-module-build":
|
||||
"@backstage/cli-module-build@workspace:*, @backstage/cli-module-build@workspace:^, @backstage/cli-module-build@workspace:packages/cli-module-build":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@backstage/cli-module-build@workspace:packages/cli-module-build"
|
||||
dependencies:
|
||||
@@ -2888,7 +2888,7 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@backstage/cli-module-config@workspace:^, @backstage/cli-module-config@workspace:packages/cli-module-config":
|
||||
"@backstage/cli-module-config@workspace:*, @backstage/cli-module-config@workspace:^, @backstage/cli-module-config@workspace:packages/cli-module-config":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@backstage/cli-module-config@workspace:packages/cli-module-config"
|
||||
dependencies:
|
||||
@@ -2910,7 +2910,7 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@backstage/cli-module-create-github-app@workspace:^, @backstage/cli-module-create-github-app@workspace:packages/cli-module-create-github-app":
|
||||
"@backstage/cli-module-create-github-app@workspace:*, @backstage/cli-module-create-github-app@workspace:^, @backstage/cli-module-create-github-app@workspace:packages/cli-module-create-github-app":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@backstage/cli-module-create-github-app@workspace:packages/cli-module-create-github-app"
|
||||
dependencies:
|
||||
@@ -2932,7 +2932,7 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@backstage/cli-module-info@workspace:^, @backstage/cli-module-info@workspace:packages/cli-module-info":
|
||||
"@backstage/cli-module-info@workspace:*, @backstage/cli-module-info@workspace:^, @backstage/cli-module-info@workspace:packages/cli-module-info":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@backstage/cli-module-info@workspace:packages/cli-module-info"
|
||||
dependencies:
|
||||
@@ -2948,7 +2948,7 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@backstage/cli-module-lint@workspace:^, @backstage/cli-module-lint@workspace:packages/cli-module-lint":
|
||||
"@backstage/cli-module-lint@workspace:*, @backstage/cli-module-lint@workspace:^, @backstage/cli-module-lint@workspace:packages/cli-module-lint":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@backstage/cli-module-lint@workspace:packages/cli-module-lint"
|
||||
dependencies:
|
||||
@@ -2968,7 +2968,7 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@backstage/cli-module-maintenance@workspace:^, @backstage/cli-module-maintenance@workspace:packages/cli-module-maintenance":
|
||||
"@backstage/cli-module-maintenance@workspace:*, @backstage/cli-module-maintenance@workspace:^, @backstage/cli-module-maintenance@workspace:packages/cli-module-maintenance":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@backstage/cli-module-maintenance@workspace:packages/cli-module-maintenance"
|
||||
dependencies:
|
||||
@@ -2985,7 +2985,7 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@backstage/cli-module-migrate@workspace:^, @backstage/cli-module-migrate@workspace:packages/cli-module-migrate":
|
||||
"@backstage/cli-module-migrate@workspace:*, @backstage/cli-module-migrate@workspace:^, @backstage/cli-module-migrate@workspace:packages/cli-module-migrate":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@backstage/cli-module-migrate@workspace:packages/cli-module-migrate"
|
||||
dependencies:
|
||||
@@ -3005,7 +3005,7 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@backstage/cli-module-new@workspace:^, @backstage/cli-module-new@workspace:packages/cli-module-new":
|
||||
"@backstage/cli-module-new@workspace:*, @backstage/cli-module-new@workspace:^, @backstage/cli-module-new@workspace:packages/cli-module-new":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@backstage/cli-module-new@workspace:packages/cli-module-new"
|
||||
dependencies:
|
||||
@@ -3016,7 +3016,7 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@backstage/cli-module-test-jest@workspace:^, @backstage/cli-module-test-jest@workspace:packages/cli-module-test-jest":
|
||||
"@backstage/cli-module-test-jest@workspace:*, @backstage/cli-module-test-jest@workspace:^, @backstage/cli-module-test-jest@workspace:packages/cli-module-test-jest":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@backstage/cli-module-test-jest@workspace:packages/cli-module-test-jest"
|
||||
dependencies:
|
||||
@@ -3027,7 +3027,7 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@backstage/cli-module-translations@workspace:^, @backstage/cli-module-translations@workspace:packages/cli-module-translations":
|
||||
"@backstage/cli-module-translations@workspace:*, @backstage/cli-module-translations@workspace:^, @backstage/cli-module-translations@workspace:packages/cli-module-translations":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@backstage/cli-module-translations@workspace:packages/cli-module-translations"
|
||||
dependencies:
|
||||
@@ -45616,6 +45616,17 @@ __metadata:
|
||||
resolution: "root@workspace:."
|
||||
dependencies:
|
||||
"@backstage/cli": "workspace:*"
|
||||
"@backstage/cli-module-auth": "workspace:*"
|
||||
"@backstage/cli-module-build": "workspace:*"
|
||||
"@backstage/cli-module-config": "workspace:*"
|
||||
"@backstage/cli-module-create-github-app": "workspace:*"
|
||||
"@backstage/cli-module-info": "workspace:*"
|
||||
"@backstage/cli-module-lint": "workspace:*"
|
||||
"@backstage/cli-module-maintenance": "workspace:*"
|
||||
"@backstage/cli-module-migrate": "workspace:*"
|
||||
"@backstage/cli-module-new": "workspace:*"
|
||||
"@backstage/cli-module-test-jest": "workspace:*"
|
||||
"@backstage/cli-module-translations": "workspace:*"
|
||||
"@backstage/codemods": "workspace:*"
|
||||
"@backstage/create-app": "workspace:*"
|
||||
"@backstage/e2e-test-utils": "workspace:*"
|
||||
|
||||
Reference in New Issue
Block a user