Address review feedback from freben

- Use cli-defaults instead of listing individual CLI modules in
  create-app template and root package.json
- Move nodeTransform config files from cli-module-build to cli-node
  to avoid cross-module direct imports
- Rename cli-module-create-github-app to cli-module-github
- Start createCliModule init chain with Promise.resolve()
- Deduplicate exitWithError in runCliModule.ts
- Extract shared isCommandNodeHidden to @internal/cli
- Add explanatory comment for fromArray deduplication field
- Restore error for cli role packages missing bin in runCliExtraction

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
This commit is contained in:
Patrik Oldsberg
2026-03-16 12:55:22 +01:00
parent 26eab3bf83
commit 4d081452b1
47 changed files with 147 additions and 185 deletions
+1 -1
View File
@@ -28,7 +28,7 @@ For fine-grained control you can instead install individual CLI modules:
"@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-github": "backstage:^",
"@backstage/cli-module-info": "backstage:^",
"@backstage/cli-module-lint": "backstage:^",
"@backstage/cli-module-maintenance": "backstage:^",
+1 -1
View File
@@ -2,7 +2,7 @@
'@backstage/cli-module-auth': minor
'@backstage/cli-module-build': minor
'@backstage/cli-module-config': minor
'@backstage/cli-module-create-github-app': minor
'@backstage/cli-module-github': minor
'@backstage/cli-module-info': minor
'@backstage/cli-module-lint': minor
'@backstage/cli-module-maintenance': minor
+1 -11
View File
@@ -125,17 +125,7 @@
},
"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/cli-defaults": "workspace:*",
"@backstage/codemods": "workspace:*",
"@backstage/create-app": "workspace:*",
"@backstage/e2e-test-utils": "workspace:*",
+13 -13
View File
@@ -4,19 +4,19 @@ The default set of CLI modules for the Backstage CLI. Installing this single pac
## Included Modules
| Module | Description |
| :--------------------------------------------------------------------------- | :--------------------------------------- |
| [`@backstage/cli-module-auth`](../cli-module-auth) | Authentication commands |
| [`@backstage/cli-module-build`](../cli-module-build) | Build, start, and packaging commands |
| [`@backstage/cli-module-config`](../cli-module-config) | Configuration inspection commands |
| [`@backstage/cli-module-create-github-app`](../cli-module-create-github-app) | GitHub App creation |
| [`@backstage/cli-module-info`](../cli-module-info) | Environment and dependency info |
| [`@backstage/cli-module-lint`](../cli-module-lint) | Linting commands |
| [`@backstage/cli-module-maintenance`](../cli-module-maintenance) | Repository maintenance commands |
| [`@backstage/cli-module-migrate`](../cli-module-migrate) | Migration and version management |
| [`@backstage/cli-module-new`](../cli-module-new) | Scaffolding for new plugins and packages |
| [`@backstage/cli-module-test-jest`](../cli-module-test-jest) | Jest-based testing commands |
| [`@backstage/cli-module-translations`](../cli-module-translations) | Translation management commands |
| Module | Description |
| :----------------------------------------------------------------- | :--------------------------------------- |
| [`@backstage/cli-module-auth`](../cli-module-auth) | Authentication commands |
| [`@backstage/cli-module-build`](../cli-module-build) | Build, start, and packaging commands |
| [`@backstage/cli-module-config`](../cli-module-config) | Configuration inspection commands |
| [`@backstage/cli-module-github`](../cli-module-github) | GitHub App creation |
| [`@backstage/cli-module-info`](../cli-module-info) | Environment and dependency info |
| [`@backstage/cli-module-lint`](../cli-module-lint) | Linting commands |
| [`@backstage/cli-module-maintenance`](../cli-module-maintenance) | Repository maintenance commands |
| [`@backstage/cli-module-migrate`](../cli-module-migrate) | Migration and version management |
| [`@backstage/cli-module-new`](../cli-module-new) | Scaffolding for new plugins and packages |
| [`@backstage/cli-module-test-jest`](../cli-module-test-jest) | Jest-based testing commands |
| [`@backstage/cli-module-translations`](../cli-module-translations) | Translation management commands |
For fine-grained control over which CLI commands are available, you can install individual modules instead.
+1 -1
View File
@@ -33,7 +33,7 @@
"@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-github": "workspace:^",
"@backstage/cli-module-info": "workspace:^",
"@backstage/cli-module-lint": "workspace:^",
"@backstage/cli-module-maintenance": "workspace:^",
+2 -2
View File
@@ -16,7 +16,7 @@
import auth from '@backstage/cli-module-auth';
import build from '@backstage/cli-module-build';
import config from '@backstage/cli-module-config';
import createGithubApp from '@backstage/cli-module-create-github-app';
import github from '@backstage/cli-module-github';
import info from '@backstage/cli-module-info';
import lint from '@backstage/cli-module-lint';
import maintenance from '@backstage/cli-module-maintenance';
@@ -34,7 +34,7 @@ export default [
auth,
build,
config,
createGithubApp,
github,
info,
lint,
maintenance,
@@ -53,3 +53,17 @@ export const OpaqueCommandLeafNode = OpaqueType.create<{
type: '@backstage/CommandLeafNode',
versions: ['v1'],
});
/**
* Checks whether a command node should be hidden from help output.
* Leaf nodes are hidden if they are deprecated or experimental.
* Tree nodes are hidden if all of their children are hidden.
*/
export function isCommandNodeHidden(node: CommandNode): boolean {
if (OpaqueCommandLeafNode.isType(node)) {
const { command } = OpaqueCommandLeafNode.toInternal(node);
return !!command.deprecated || !!command.experimental;
}
const { children } = OpaqueCommandTreeNode.toInternal(node);
return children.every(child => isCommandNodeHidden(child));
}
+1
View File
@@ -23,4 +23,5 @@ export type {
export {
OpaqueCommandTreeNode,
OpaqueCommandLeafNode,
isCommandNodeHidden,
} from './InternalCommandNode';
@@ -28,6 +28,6 @@ if (!isLocal) {
const pkg = require('../package.json');
runCliModule({ module: cliModule, name: pkg.name, version: pkg.version });
} else {
require('@backstage/cli/config/nodeTransform.cjs');
require('@backstage/cli-node/config/nodeTransform.cjs');
require('../src/cli');
}
@@ -28,6 +28,6 @@ if (!isLocal) {
const pkg = require('../package.json');
runCliModule({ module: cliModule, name: pkg.name, version: pkg.version });
} else {
require('@backstage/cli/config/nodeTransform.cjs');
require('@backstage/cli-node/config/nodeTransform.cjs');
require('../src/cli');
}
-1
View File
@@ -72,7 +72,6 @@
"node-stdlib-browser": "^1.3.1",
"npm-packlist": "^5.0.0",
"p-queue": "^6.6.2",
"pirates": "^4.0.6",
"postcss": "^8.1.0",
"postcss-import": "^16.1.0",
"process": "^0.11.10",
@@ -21,16 +21,15 @@ import { IpcServer, ServerDataStore } from '../ipc';
import debounce from 'lodash/debounce';
import { fileURLToPath } from 'node:url';
import { isAbsolute as isAbsolutePath } from 'node:path';
import { findOwnPaths, targetPaths } from '@backstage/cli-common';
import { targetPaths } from '@backstage/cli-common';
import spawn from 'cross-spawn';
const loaderArgs = [
'--enable-source-maps',
'--require',
/* eslint-disable-next-line no-restricted-syntax */
findOwnPaths(__dirname).resolve('config/nodeTransform.cjs'),
// TODO: Support modules, although there's currently no way to load them since import() is transpiled tp require()
require.resolve('@backstage/cli-node/config/nodeTransform.cjs'),
// TODO: Support modules, although there's currently no way to load them since import() is transpiled to require()
];
export type RunBackendOptions = {
@@ -16,7 +16,6 @@
import { execFileSync } from 'node:child_process';
import { resolve as resolvePath } from 'node:path';
import { findOwnPaths } from '@backstage/cli-common';
import { Output, buildPackage } from '../../lib/builder';
const exportValues = {
@@ -56,8 +55,7 @@ function loadFixture(fixture: string) {
'node',
[
'--import',
/* eslint-disable-next-line no-restricted-syntax */
findOwnPaths(__dirname).resolve('config/nodeTransform.cjs'),
require.resolve('@backstage/cli-node/config/nodeTransform.cjs'),
resolvePath(__dirname, `__fixtures__/${fixture}`),
],
{ encoding: 'utf8' },
@@ -28,6 +28,6 @@ if (!isLocal) {
const pkg = require('../package.json');
runCliModule({ module: cliModule, name: pkg.name, version: pkg.version });
} else {
require('@backstage/cli/config/nodeTransform.cjs');
require('@backstage/cli-node/config/nodeTransform.cjs');
require('../src/cli');
}
@@ -1,26 +0,0 @@
## CLI Report file for "@backstage/cli-module-create-github-app"
> Do not edit this file. It is a report generated by `yarn build:api-reports`
### `backstage-cli-module-create-github-app`
```
Usage: @backstage/cli-module-create-github-app [options] [command]
Options:
-V, --version
-h, --help
Commands:
create-github-app
help [command]
```
### `backstage-cli-module-create-github-app create-github-app`
```
Usage: @backstage/cli-module-create-github-app create-github-app <github-org>
Options:
-h, --help
```
@@ -1,4 +1,4 @@
# @backstage/cli-module-create-github-app
# @backstage/cli-module-github
CLI module that provides the `create-github-app` command for the Backstage CLI, used to create a new GitHub App in your organization for use with Backstage.
@@ -28,6 +28,6 @@ if (!isLocal) {
const pkg = require('../package.json');
runCliModule({ module: cliModule, name: pkg.name, version: pkg.version });
} else {
require('@backstage/cli/config/nodeTransform.cjs');
require('@backstage/cli-node/config/nodeTransform.cjs');
require('../src/cli');
}
@@ -1,8 +1,8 @@
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: backstage-cli-module-create-github-app
title: '@backstage/cli-module-create-github-app'
name: backstage-cli-module-github
title: '@backstage/cli-module-github'
description: CLI module for Backstage CLI
spec:
lifecycle: experimental
+26
View File
@@ -0,0 +1,26 @@
## CLI Report file for "@backstage/cli-module-github"
> Do not edit this file. It is a report generated by `yarn build:api-reports`
### `backstage-cli-module-github`
```
Usage: @backstage/cli-module-github [options] [command]
Options:
-V, --version
-h, --help
Commands:
create-github-app
help [command]
```
### `backstage-cli-module-github create-github-app`
```
Usage: @backstage/cli-module-github create-github-app <github-org>
Options:
-h, --help
```
@@ -1,5 +1,5 @@
{
"name": "@backstage/cli-module-create-github-app",
"name": "@backstage/cli-module-github",
"version": "0.0.0",
"description": "CLI module for Backstage CLI",
"backstage": {
@@ -14,7 +14,7 @@
"repository": {
"type": "git",
"url": "https://github.com/backstage/backstage",
"directory": "packages/cli-module-create-github-app"
"directory": "packages/cli-module-github"
},
"license": "Apache-2.0",
"main": "src/index.ts",
@@ -48,5 +48,5 @@
"@types/express": "^4.17.6",
"@types/fs-extra": "^11.0.0"
},
"bin": "bin/backstage-cli-module-create-github-app"
"bin": "bin/backstage-cli-module-github"
}
@@ -1,4 +1,4 @@
## API Report File for "@backstage/cli-module-create-github-app"
## API Report File for "@backstage/cli-module-github"
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
@@ -28,6 +28,6 @@ if (!isLocal) {
const pkg = require('../package.json');
runCliModule({ module: cliModule, name: pkg.name, version: pkg.version });
} else {
require('@backstage/cli/config/nodeTransform.cjs');
require('@backstage/cli-node/config/nodeTransform.cjs');
require('../src/cli');
}
@@ -28,6 +28,6 @@ if (!isLocal) {
const pkg = require('../package.json');
runCliModule({ module: cliModule, name: pkg.name, version: pkg.version });
} else {
require('@backstage/cli/config/nodeTransform.cjs');
require('@backstage/cli-node/config/nodeTransform.cjs');
require('../src/cli');
}
@@ -28,6 +28,6 @@ if (!isLocal) {
const pkg = require('../package.json');
runCliModule({ module: cliModule, name: pkg.name, version: pkg.version });
} else {
require('@backstage/cli/config/nodeTransform.cjs');
require('@backstage/cli-node/config/nodeTransform.cjs');
require('../src/cli');
}
@@ -28,6 +28,6 @@ if (!isLocal) {
const pkg = require('../package.json');
runCliModule({ module: cliModule, name: pkg.name, version: pkg.version });
} else {
require('@backstage/cli/config/nodeTransform.cjs');
require('@backstage/cli-node/config/nodeTransform.cjs');
require('../src/cli');
}
@@ -28,6 +28,6 @@ if (!isLocal) {
const pkg = require('../package.json');
runCliModule({ module: cliModule, name: pkg.name, version: pkg.version });
} else {
require('@backstage/cli/config/nodeTransform.cjs');
require('@backstage/cli-node/config/nodeTransform.cjs');
require('../src/cli');
}
@@ -28,6 +28,6 @@ if (!isLocal) {
const pkg = require('../package.json');
runCliModule({ module: cliModule, name: pkg.name, version: pkg.version });
} else {
require('@backstage/cli/config/nodeTransform.cjs');
require('@backstage/cli-node/config/nodeTransform.cjs');
require('../src/cli');
}
@@ -28,6 +28,6 @@ if (!isLocal) {
const pkg = require('../package.json');
runCliModule({ module: cliModule, name: pkg.name, version: pkg.version });
} else {
require('@backstage/cli/config/nodeTransform.cjs');
require('@backstage/cli-node/config/nodeTransform.cjs');
require('../src/cli');
}
+19 -1
View File
@@ -1 +1,19 @@
module.exports = require('@backstage/cli/config/eslint-factory')(__dirname);
/*
* Copyright 2026 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.
*/
module.exports = {
...require('@backstage/cli/config/eslint-factory')(__dirname),
ignorePatterns: ['config/**'],
};
+4 -1
View File
@@ -20,7 +20,8 @@
"main": "src/index.ts",
"types": "src/index.ts",
"files": [
"dist"
"dist",
"config"
],
"scripts": {
"build": "backstage-cli package build",
@@ -35,11 +36,13 @@
"@backstage/errors": "workspace:^",
"@backstage/types": "workspace:^",
"@manypkg/get-packages": "^1.1.3",
"@swc/core": "^1.15.6",
"@yarnpkg/lockfile": "^1.1.0",
"@yarnpkg/parsers": "^3.0.0",
"chalk": "^4.0.0",
"commander": "^12.0.0",
"fs-extra": "^11.2.0",
"pirates": "^4.0.6",
"semver": "^7.5.3",
"yaml": "^2.0.0",
"zod": "^3.25.76"
@@ -62,8 +62,8 @@ export function createCliModule(options: {
}
const commands: CliCommand[] = [];
const commandsPromise = options
.init({ addCommand: command => commands.push(command) })
const commandsPromise = Promise.resolve()
.then(() => options.init({ addCommand: command => commands.push(command) }))
.then(() => commands);
return OpaqueCliModule.createInstance('v1', {
@@ -18,6 +18,7 @@ import {
OpaqueCliModule,
OpaqueCommandTreeNode,
OpaqueCommandLeafNode,
isCommandNodeHidden,
} from '@internal/cli';
import type { CommandNode } from '@internal/cli';
import { Command } from 'commander';
@@ -25,15 +26,6 @@ import chalk from 'chalk';
import { isError, stringifyError } from '@backstage/errors';
import type { CliModule, CliCommand } from './types';
function isCommandHidden(node: CommandNode): boolean {
if (OpaqueCommandLeafNode.isType(node)) {
const { command } = OpaqueCommandLeafNode.toInternal(node);
return !!command.deprecated || !!command.experimental;
}
const { children } = OpaqueCommandTreeNode.toInternal(node);
return children.every(child => isCommandHidden(child));
}
function buildCommandGraph(commands: ReadonlyArray<CliCommand>): CommandNode[] {
const graph: CommandNode[] = [];
@@ -70,13 +62,11 @@ function buildCommandGraph(commands: ReadonlyArray<CliCommand>): CommandNode[] {
}
function exitWithError(error: unknown): never {
if (!isError(error)) {
process.stderr.write(`\n${chalk.red(stringifyError(error))}\n\n`);
process.exit(1);
}
process.stderr.write(`\n${chalk.red(stringifyError(error))}\n\n`);
process.exit(
'code' in error && typeof error.code === 'number' ? error.code : 1,
isError(error) && 'code' in error && typeof error.code === 'number'
? error.code
: 1,
);
}
@@ -94,7 +84,7 @@ function registerCommands(
const internal = OpaqueCommandTreeNode.toInternal(node);
const treeParser = argParser
.command(`${internal.name} [command]`, {
hidden: isCommandHidden(node),
hidden: isCommandNodeHidden(node),
})
.description(internal.name);
+2 -2
View File
@@ -15,11 +15,11 @@
*/
try {
require('@backstage/cli-module-build/config/nodeTransform.cjs');
require('@backstage/cli-node/config/nodeTransform.cjs');
} catch (e) {
if (e.code === 'MODULE_NOT_FOUND') {
throw new Error(
'@backstage/cli-module-build is required to use the node transform. ' +
'@backstage/cli-node is required to use the node transform. ' +
'Please install it as a dependency.',
);
}
+1 -1
View File
@@ -17,4 +17,4 @@
export {
resolve,
load,
} from '@backstage/cli-module-build/config/nodeTransformHooks.mjs';
} from '@backstage/cli-node/config/nodeTransformHooks.mjs';
+8 -11
View File
@@ -19,8 +19,8 @@ import {
OpaqueCliModule,
OpaqueCommandTreeNode,
OpaqueCommandLeafNode,
isCommandNodeHidden,
} from '@internal/cli';
import type { CommandNode } from '@internal/cli';
import type { CliModule } from '@backstage/cli-node';
import { Command } from 'commander';
import { version } from './version';
@@ -29,15 +29,6 @@ import { exitWithError } from './errors';
import { ForwardedError } from '@backstage/errors';
import { isPromise } from 'node:util/types';
function isNodeHidden(node: CommandNode): boolean {
if (OpaqueCommandLeafNode.isType(node)) {
const { command } = OpaqueCommandLeafNode.toInternal(node);
return !!command.deprecated || !!command.experimental;
}
const { children } = OpaqueCommandTreeNode.toInternal(node);
return children.every(child => isNodeHidden(child));
}
type UninitializedFeature =
| CliModule
| CliModule[]
@@ -45,6 +36,12 @@ type UninitializedFeature =
interface TaggedFeature {
feature: CliModule;
/**
* Whether this module was sourced from an array (e.g. cli-defaults).
* Array-sourced modules are silently skipped when any of their commands
* overlap with an individually-added module, allowing explicit module
* additions to take precedence without causing conflicts.
*/
fromArray: boolean;
}
@@ -136,7 +133,7 @@ export class CliInitializer {
const internal = OpaqueCommandTreeNode.toInternal(node);
const treeParser = argParser
.command(`${internal.name} [command]`, {
hidden: isNodeHidden(node),
hidden: isCommandNodeHidden(node),
})
.description(internal.name);
-11
View File
@@ -51,17 +51,6 @@ jest.mock('./versions', () => ({
root: '1.2.3',
'@backstage/cli': '1.0.0',
'@backstage/cli-defaults': '1.0.0',
'@backstage/cli-module-auth': '1.0.0',
'@backstage/cli-module-build': '1.0.0',
'@backstage/cli-module-config': '1.0.0',
'@backstage/cli-module-create-github-app': '1.0.0',
'@backstage/cli-module-info': '1.0.0',
'@backstage/cli-module-lint': '1.0.0',
'@backstage/cli-module-maintenance': '1.0.0',
'@backstage/cli-module-migrate': '1.0.0',
'@backstage/cli-module-new': '1.0.0',
'@backstage/cli-module-test-jest': '1.0.0',
'@backstage/cli-module-translations': '1.0.0',
'@backstage/backend-defaults': '1.0.0',
'@backstage/backend-tasks': '1.0.0',
'@backstage/catalog-model': '1.0.0',
-22
View File
@@ -39,17 +39,6 @@ import { version as catalogClient } from '../../../catalog-client/package.json';
import { version as catalogModel } from '../../../catalog-model/package.json';
import { version as cli } from '../../../cli/package.json';
import { version as cliDefaults } from '../../../cli-defaults/package.json';
import { version as cliModuleAuth } from '../../../cli-module-auth/package.json';
import { version as cliModuleBuild } from '../../../cli-module-build/package.json';
import { version as cliModuleConfig } from '../../../cli-module-config/package.json';
import { version as cliModuleCreateGithubApp } from '../../../cli-module-create-github-app/package.json';
import { version as cliModuleInfo } from '../../../cli-module-info/package.json';
import { version as cliModuleLint } from '../../../cli-module-lint/package.json';
import { version as cliModuleMaintenance } from '../../../cli-module-maintenance/package.json';
import { version as cliModuleMigrate } from '../../../cli-module-migrate/package.json';
import { version as cliModuleNew } from '../../../cli-module-new/package.json';
import { version as cliModuleTestJest } from '../../../cli-module-test-jest/package.json';
import { version as cliModuleTranslations } from '../../../cli-module-translations/package.json';
import { version as config } from '../../../config/package.json';
import { version as coreAppApi } from '../../../core-app-api/package.json';
import { version as coreCompatApi } from '../../../core-compat-api/package.json';
@@ -120,17 +109,6 @@ export const packageVersions = {
'@backstage/catalog-model': catalogModel,
'@backstage/cli': cli,
'@backstage/cli-defaults': cliDefaults,
'@backstage/cli-module-auth': cliModuleAuth,
'@backstage/cli-module-build': cliModuleBuild,
'@backstage/cli-module-config': cliModuleConfig,
'@backstage/cli-module-create-github-app': cliModuleCreateGithubApp,
'@backstage/cli-module-info': cliModuleInfo,
'@backstage/cli-module-lint': cliModuleLint,
'@backstage/cli-module-maintenance': cliModuleMaintenance,
'@backstage/cli-module-migrate': cliModuleMigrate,
'@backstage/cli-module-new': cliModuleNew,
'@backstage/cli-module-test-jest': cliModuleTestJest,
'@backstage/cli-module-translations': cliModuleTranslations,
'@backstage/config': config,
'@backstage/core-app-api': coreAppApi,
'@backstage/core-compat-api': coreCompatApi,
@@ -50,17 +50,7 @@
],
"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/cli-defaults": "^{{version '@backstage/cli-defaults'}}",
"@backstage/e2e-test-utils": "^{{version '@backstage/e2e-test-utils'}}",
"@jest/environment-jsdom-abstract": "^30.0.0",
"@playwright/test": "^1.32.3",
@@ -132,6 +132,11 @@ export async function runCliExtraction({
const pkgJson = await fs.readJson(resolvePath(fullDir, 'package.json'));
if (!pkgJson.bin) {
if (pkgJson.backstage?.role === 'cli') {
throw new Error(
`CLI package ${pkgJson.name} is missing a "bin" field in its package.json`,
);
}
continue;
}
+18 -27
View File
@@ -2801,7 +2801,7 @@ __metadata:
languageName: unknown
linkType: soft
"@backstage/cli-defaults@workspace:^, @backstage/cli-defaults@workspace:packages/cli-defaults":
"@backstage/cli-defaults@workspace:*, @backstage/cli-defaults@workspace:^, @backstage/cli-defaults@workspace:packages/cli-defaults":
version: 0.0.0-use.local
resolution: "@backstage/cli-defaults@workspace:packages/cli-defaults"
dependencies:
@@ -2809,7 +2809,7 @@ __metadata:
"@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-github": "workspace:^"
"@backstage/cli-module-info": "workspace:^"
"@backstage/cli-module-lint": "workspace:^"
"@backstage/cli-module-maintenance": "workspace:^"
@@ -2820,7 +2820,7 @@ __metadata:
languageName: unknown
linkType: soft
"@backstage/cli-module-auth@workspace:*, @backstage/cli-module-auth@workspace:^, @backstage/cli-module-auth@workspace:packages/cli-module-auth":
"@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:
@@ -2847,7 +2847,7 @@ __metadata:
languageName: unknown
linkType: soft
"@backstage/cli-module-build@workspace:*, @backstage/cli-module-build@workspace:^, @backstage/cli-module-build@workspace:packages/cli-module-build":
"@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:
@@ -2894,7 +2894,6 @@ __metadata:
node-stdlib-browser: "npm:^1.3.1"
npm-packlist: "npm:^5.0.0"
p-queue: "npm:^6.6.2"
pirates: "npm:^4.0.6"
postcss: "npm:^8.1.0"
postcss-import: "npm:^16.1.0"
process: "npm:^0.11.10"
@@ -2922,7 +2921,7 @@ __metadata:
languageName: unknown
linkType: soft
"@backstage/cli-module-config@workspace:*, @backstage/cli-module-config@workspace:^, @backstage/cli-module-config@workspace:packages/cli-module-config":
"@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:
@@ -2944,9 +2943,9 @@ __metadata:
languageName: unknown
linkType: soft
"@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":
"@backstage/cli-module-github@workspace:^, @backstage/cli-module-github@workspace:packages/cli-module-github":
version: 0.0.0-use.local
resolution: "@backstage/cli-module-create-github-app@workspace:packages/cli-module-create-github-app"
resolution: "@backstage/cli-module-github@workspace:packages/cli-module-github"
dependencies:
"@backstage/cli": "workspace:^"
"@backstage/cli-common": "workspace:^"
@@ -2962,11 +2961,11 @@ __metadata:
react-dev-utils: "npm:^12.0.0-next.60"
yaml: "npm:^2.0.0"
bin:
cli-module-create-github-app: bin/backstage-cli-module-create-github-app
cli-module-github: bin/backstage-cli-module-github
languageName: unknown
linkType: soft
"@backstage/cli-module-info@workspace:*, @backstage/cli-module-info@workspace:^, @backstage/cli-module-info@workspace:packages/cli-module-info":
"@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:
@@ -2982,7 +2981,7 @@ __metadata:
languageName: unknown
linkType: soft
"@backstage/cli-module-lint@workspace:*, @backstage/cli-module-lint@workspace:^, @backstage/cli-module-lint@workspace:packages/cli-module-lint":
"@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:
@@ -3003,7 +3002,7 @@ __metadata:
languageName: unknown
linkType: soft
"@backstage/cli-module-maintenance@workspace:*, @backstage/cli-module-maintenance@workspace:^, @backstage/cli-module-maintenance@workspace:packages/cli-module-maintenance":
"@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:
@@ -3020,7 +3019,7 @@ __metadata:
languageName: unknown
linkType: soft
"@backstage/cli-module-migrate@workspace:*, @backstage/cli-module-migrate@workspace:^, @backstage/cli-module-migrate@workspace:packages/cli-module-migrate":
"@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:
@@ -3047,7 +3046,7 @@ __metadata:
languageName: unknown
linkType: soft
"@backstage/cli-module-new@workspace:*, @backstage/cli-module-new@workspace:^, @backstage/cli-module-new@workspace:packages/cli-module-new":
"@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:
@@ -3079,7 +3078,7 @@ __metadata:
languageName: unknown
linkType: soft
"@backstage/cli-module-test-jest@workspace:*, @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:packages/cli-module-test-jest":
version: 0.0.0-use.local
resolution: "@backstage/cli-module-test-jest@workspace:packages/cli-module-test-jest"
dependencies:
@@ -3112,7 +3111,7 @@ __metadata:
languageName: unknown
linkType: soft
"@backstage/cli-module-translations@workspace:*, @backstage/cli-module-translations@workspace:^, @backstage/cli-module-translations@workspace:packages/cli-module-translations":
"@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:
@@ -3139,12 +3138,14 @@ __metadata:
"@backstage/test-utils": "workspace:^"
"@backstage/types": "workspace:^"
"@manypkg/get-packages": "npm:^1.1.3"
"@swc/core": "npm:^1.15.6"
"@types/yarnpkg__lockfile": "npm:^1.1.4"
"@yarnpkg/lockfile": "npm:^1.1.0"
"@yarnpkg/parsers": "npm:^3.0.0"
chalk: "npm:^4.0.0"
commander: "npm:^12.0.0"
fs-extra: "npm:^11.2.0"
pirates: "npm:^4.0.6"
semver: "npm:^7.5.3"
yaml: "npm:^2.0.0"
zod: "npm:^3.25.76"
@@ -45365,17 +45366,7 @@ __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/cli-defaults": "workspace:*"
"@backstage/codemods": "workspace:*"
"@backstage/create-app": "workspace:*"
"@backstage/e2e-test-utils": "workspace:*"