Merge pull request #33355 from backstage/rugvip/cli-plugin-api

cli: add CLI module plugin API and auto-discovery
This commit is contained in:
Patrik Oldsberg
2026-03-16 14:50:27 +01:00
committed by GitHub
369 changed files with 5707 additions and 1824 deletions
+1
View File
@@ -0,0 +1 @@
module.exports = require('@backstage/cli/config/eslint-factory')(__dirname);
+26
View File
@@ -0,0 +1,26 @@
# @backstage/cli-defaults
The default set of CLI modules for the Backstage CLI. Installing this single package provides all standard CLI commands without needing to list each module individually.
## 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-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.
## Documentation
- [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md)
- [Backstage Documentation](https://backstage.io/docs)
+10
View File
@@ -0,0 +1,10 @@
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: backstage-cli-defaults
title: '@backstage/cli-defaults'
description: Default set of CLI modules for the Backstage CLI
spec:
lifecycle: experimental
type: backstage-cli-module
owner: tooling-maintainers
+48
View File
@@ -0,0 +1,48 @@
{
"name": "@backstage/cli-defaults",
"version": "0.0.0",
"description": "Default set of CLI modules for the Backstage CLI",
"backstage": {
"role": "cli-module"
},
"publishConfig": {
"access": "public",
"main": "dist/index.cjs.js",
"types": "dist/index.d.ts"
},
"homepage": "https://backstage.io",
"repository": {
"type": "git",
"url": "https://github.com/backstage/backstage",
"directory": "packages/cli-defaults"
},
"license": "Apache-2.0",
"main": "src/index.ts",
"types": "src/index.ts",
"files": [
"dist"
],
"scripts": {
"build": "backstage-cli package build",
"clean": "backstage-cli package clean",
"lint": "backstage-cli package lint",
"prepack": "backstage-cli package prepack",
"postpack": "backstage-cli package postpack"
},
"dependencies": {
"@backstage/cli-module-auth": "workspace:^",
"@backstage/cli-module-build": "workspace:^",
"@backstage/cli-module-config": "workspace:^",
"@backstage/cli-module-github": "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:^"
},
"devDependencies": {
"@backstage/cli": "workspace:^"
}
}
+13
View File
@@ -0,0 +1,13 @@
## API Report File for "@backstage/cli-defaults"
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
```ts
import { CliModule } from '@backstage/cli-node';
// @public
const _default: CliModule[];
export default _default;
// (No @packageDocumentation comment for this package)
```
+45
View File
@@ -0,0 +1,45 @@
/*
* Copyright 2025 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 auth from '@backstage/cli-module-auth';
import build from '@backstage/cli-module-build';
import config from '@backstage/cli-module-config';
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';
import migrate from '@backstage/cli-module-migrate';
import newModule from '@backstage/cli-module-new';
import testJest from '@backstage/cli-module-test-jest';
import translations from '@backstage/cli-module-translations';
/**
* The default set of CLI modules for the Backstage CLI.
*
* @public
*/
export default [
auth,
build,
config,
github,
info,
lint,
maintenance,
migrate,
newModule,
testJest,
translations,
];
+1
View File
@@ -0,0 +1 @@
module.exports = require('@backstage/cli/config/eslint-factory')(__dirname);
+9
View File
@@ -0,0 +1,9 @@
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: internal-cli
title: '@internal/cli'
spec:
lifecycle: experimental
type: backstage-node-library
owner: tooling-maintainers
+30
View File
@@ -0,0 +1,30 @@
{
"name": "@internal/cli",
"version": "0.0.1",
"backstage": {
"role": "node-library",
"inline": true
},
"private": true,
"repository": {
"type": "git",
"url": "https://github.com/backstage/backstage",
"directory": "packages/cli-internal"
},
"license": "Apache-2.0",
"main": "src/index.ts",
"types": "src/index.ts",
"files": [
"dist"
],
"scripts": {
"lint": "backstage-cli package lint",
"test": "backstage-cli package test"
},
"dependencies": {
"@backstage/cli-node": "workspace:^"
},
"devDependencies": {
"@backstage/cli": "workspace:^"
}
}
@@ -0,0 +1,30 @@
/*
* 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 { CliCommand, CliModule } from '@backstage/cli-node';
import { OpaqueType } from '@internal/opaque';
export const OpaqueCliModule = OpaqueType.create<{
public: CliModule;
versions: {
readonly version: 'v1';
readonly packageName: string;
readonly commands: Promise<ReadonlyArray<CliCommand>>;
};
}>({
type: '@backstage/CliModule',
versions: ['v1'],
});
@@ -0,0 +1,69 @@
/*
* 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 { CliCommand, CliModule } from '@backstage/cli-node';
import { OpaqueType } from '@internal/opaque';
/** @internal */
export interface CommandTreeNode {
readonly $$type: '@backstage/CommandTreeNode';
}
/** @internal */
export interface CommandLeafNode {
readonly $$type: '@backstage/CommandLeafNode';
}
export type CommandNode = CommandTreeNode | CommandLeafNode;
export const OpaqueCommandTreeNode = OpaqueType.create<{
public: CommandTreeNode;
versions: {
readonly version: 'v1';
readonly name: string;
readonly children: CommandNode[];
};
}>({
type: '@backstage/CommandTreeNode',
versions: ['v1'],
});
export const OpaqueCommandLeafNode = OpaqueType.create<{
public: CommandLeafNode;
versions: {
readonly version: 'v1';
readonly name: string;
readonly command: CliCommand;
readonly module?: CliModule;
};
}>({
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,5 +1,5 @@
/*
* Copyright 2023 The Backstage Authors
* 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.
@@ -14,7 +14,14 @@
* limitations under the License.
*/
// Single re-export to avoid doing this import in multiple places, but still
// avoid duplicate declarations because this one is a bit tricky.
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
export { describeParentCallSite } from '../../../frontend-plugin-api/src/routing/describeParentCallSite';
export { OpaqueCliModule } from './InternalCliModule';
export type {
CommandNode,
CommandTreeNode,
CommandLeafNode,
} from './InternalCommandNode';
export {
OpaqueCommandTreeNode,
OpaqueCommandLeafNode,
isCommandNodeHidden,
} from './InternalCommandNode';
+1
View File
@@ -0,0 +1 @@
module.exports = require('@backstage/cli/config/eslint-factory')(__dirname);
+19
View File
@@ -0,0 +1,19 @@
# @backstage/cli-module-auth
CLI module that provides authentication commands for the Backstage CLI, enabling login, logout, and credential management for Backstage instances.
## Commands
| Command | Description |
| :----------------- | :------------------------------------------------------- |
| `auth login` | Log in the CLI to a Backstage instance |
| `auth logout` | Log out the CLI and clear stored credentials |
| `auth show` | Show details of an authenticated instance |
| `auth list` | List authenticated instances |
| `auth print-token` | Print an access token to stdout (auto-refresh if needed) |
| `auth select` | Select the default instance |
## Documentation
- [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md)
- [Backstage Documentation](https://backstage.io/docs)
+32
View File
@@ -0,0 +1,32 @@
#!/usr/bin/env node
/*
* 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.
*/
const path = require('node:path');
/* eslint-disable-next-line no-restricted-syntax */
const isLocal = require('node:fs').existsSync(
path.resolve(__dirname, '../src'),
);
if (isLocal) {
require('@backstage/cli-node/config/nodeTransform.cjs');
}
const { runCliModule } = require('@backstage/cli-node');
const cliModule = require(isLocal ? '../src/index' : '..').default;
const pkg = require('../package.json');
runCliModule({ module: cliModule, name: pkg.name, version: pkg.version });
@@ -0,0 +1,10 @@
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: backstage-cli-module-auth
title: '@backstage/cli-module-auth'
description: CLI module for Backstage CLI
spec:
lifecycle: experimental
type: backstage-cli-module
owner: tooling-maintainers
+96
View File
@@ -0,0 +1,96 @@
## CLI Report file for "@backstage/cli-module-auth"
> Do not edit this file. It is a report generated by `yarn build:api-reports`
### `backstage-cli-module-auth`
```
Usage: @backstage/cli-module-auth [options] [command]
Options:
-V, --version
-h, --help
Commands:
auth [command]
help [command]
```
### `backstage-cli-module-auth auth`
```
Usage: @backstage/cli-module-auth auth [options] [command] [command]
Options:
-h, --help
Commands:
help [command]
list
login
logout
print-token
select
show
```
### `backstage-cli-module-auth auth list`
```
Usage: @backstage/cli-module-auth auth list
Options:
-h, --help
```
### `backstage-cli-module-auth auth login`
```
Usage: @backstage/cli-module-auth auth login
Options:
--backend-url <string>
--instance <string>
--no-browser
-h, --help
```
### `backstage-cli-module-auth auth logout`
```
Usage: @backstage/cli-module-auth auth logout
Options:
--instance <string>
-h, --help
```
### `backstage-cli-module-auth auth print-token`
```
Usage: @backstage/cli-module-auth auth print-token
Options:
--instance <string>
-h, --help
```
### `backstage-cli-module-auth auth select`
```
Usage: @backstage/cli-module-auth auth select
Options:
--instance <string>
-h, --help
```
### `backstage-cli-module-auth auth show`
```
Usage: @backstage/cli-module-auth auth show
Options:
--instance <string>
-h, --help
```
+56
View File
@@ -0,0 +1,56 @@
{
"name": "@backstage/cli-module-auth",
"version": "0.0.0",
"description": "CLI module for Backstage CLI",
"backstage": {
"role": "cli-module"
},
"publishConfig": {
"access": "public",
"main": "dist/index.cjs.js",
"types": "dist/index.d.ts"
},
"homepage": "https://backstage.io",
"repository": {
"type": "git",
"url": "https://github.com/backstage/backstage",
"directory": "packages/cli-module-auth"
},
"license": "Apache-2.0",
"main": "src/index.ts",
"types": "src/index.ts",
"files": [
"dist",
"bin"
],
"scripts": {
"build": "backstage-cli package build",
"clean": "backstage-cli package clean",
"lint": "backstage-cli package lint",
"prepack": "backstage-cli package prepack",
"postpack": "backstage-cli package postpack",
"test": "backstage-cli package test"
},
"dependencies": {
"@backstage/cli-node": "workspace:^",
"@backstage/errors": "workspace:^",
"cleye": "^2.3.0",
"cross-fetch": "^4.0.0",
"fs-extra": "^11.2.0",
"glob": "^7.1.7",
"inquirer": "^8.2.0",
"proper-lockfile": "^4.1.2",
"yaml": "^2.0.0",
"zod": "^3.25.76"
},
"devDependencies": {
"@backstage/backend-test-utils": "workspace:^",
"@backstage/cli": "workspace:^",
"@types/fs-extra": "^11.0.0",
"@types/proper-lockfile": "^4"
},
"optionalDependencies": {
"keytar": "^7.9.0"
},
"bin": "bin/backstage-cli-module-auth"
}
+13
View File
@@ -0,0 +1,13 @@
## API Report File for "@backstage/cli-module-auth"
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
```ts
import { CliModule } from '@backstage/cli-node';
// @public (undocumented)
const _default: CliModule;
export default _default;
// (No @packageDocumentation comment for this package)
```
@@ -15,10 +15,10 @@
*/
import { cli } from 'cleye';
import type { CommandContext } from '../../../wiring/types';
import type { CliCommandContext } from '@backstage/cli-node';
import { getAllInstances } from '../lib/storage';
export default async ({ args, info }: CommandContext) => {
export default async ({ args, info }: CliCommandContext) => {
cli({ help: info }, undefined, args);
const { instances, selected } = await getAllInstances();
@@ -15,7 +15,7 @@
*/
import { cli } from 'cleye';
import type { CommandContext } from '../../../wiring/types';
import type { CliCommandContext } from '@backstage/cli-node';
import { startCallbackServer } from '../lib/localServer';
import { spawn } from 'node:child_process';
import { challengeFromVerifier, generateVerifier } from '../lib/pkce';
@@ -37,7 +37,7 @@ import inquirer from 'inquirer';
const TOKEN_EXCHANGE_TIMEOUT_MS = 30_000;
export default async ({ args, info }: CommandContext) => {
export default async ({ args, info }: CliCommandContext) => {
const {
flags: { backendUrl, noBrowser, instance: instanceFlag },
} = cli(
@@ -15,7 +15,7 @@
*/
import { cli } from 'cleye';
import type { CommandContext } from '../../../wiring/types';
import type { CliCommandContext } from '@backstage/cli-node';
import { getSecretStore } from '../lib/secretStore';
import {
removeInstance,
@@ -25,7 +25,7 @@ import {
import { httpJson } from '../lib/http';
import { pickInstance } from '../lib/prompt';
export default async ({ args, info }: CommandContext) => {
export default async ({ args, info }: CliCommandContext) => {
const {
flags: { instance: instanceFlag },
} = cli(
@@ -15,12 +15,12 @@
*/
import { cli } from 'cleye';
import type { CommandContext } from '../../../wiring/types';
import type { CliCommandContext } from '@backstage/cli-node';
import { accessTokenNeedsRefresh, refreshAccessToken } from '../lib/auth';
import { getSelectedInstance } from '../lib/storage';
import { getSecretStore } from '../lib/secretStore';
export default async ({ args, info }: CommandContext) => {
export default async ({ args, info }: CliCommandContext) => {
const {
flags: { instance: instanceFlag },
} = cli(
@@ -15,11 +15,11 @@
*/
import { cli } from 'cleye';
import type { CommandContext } from '../../../wiring/types';
import type { CliCommandContext } from '@backstage/cli-node';
import { setSelectedInstance } from '../lib/storage';
import { pickInstance } from '../lib/prompt';
export default async ({ args, info }: CommandContext) => {
export default async ({ args, info }: CliCommandContext) => {
const {
flags: { instance: instanceFlag },
} = cli(
@@ -15,13 +15,13 @@
*/
import { cli } from 'cleye';
import type { CommandContext } from '../../../wiring/types';
import type { CliCommandContext } from '@backstage/cli-node';
import { httpJson } from '../lib/http';
import { getSelectedInstance } from '../lib/storage';
import { accessTokenNeedsRefresh, refreshAccessToken } from '../lib/auth';
import { getSecretStore } from '../lib/secretStore';
export default async ({ args, info }: CommandContext) => {
export default async ({ args, info }: CliCommandContext) => {
const {
flags: { instance: instanceFlag },
} = cli(
@@ -14,10 +14,11 @@
* limitations under the License.
*/
import { createCliPlugin } from '../../wiring/factory';
import { createCliModule } from '@backstage/cli-node';
import packageJson from '../package.json';
export default createCliPlugin({
pluginId: 'auth',
export default createCliModule({
packageJson,
init: async reg => {
reg.addCommand({
path: ['auth', 'login'],
+3
View File
@@ -0,0 +1,3 @@
module.exports = require('@backstage/cli/config/eslint-factory')(__dirname, {
ignorePatterns: ['config/**', 'templates/**'],
});
+23
View File
@@ -0,0 +1,23 @@
# @backstage/cli-module-build
CLI module that provides build, start, and packaging commands for the Backstage CLI.
## Commands
| Command | Description |
| :----------------- | :------------------------------------------------------------------------ |
| `package build` | Build a package for production deployment or publishing |
| `package start` | Start a package for local development |
| `package clean` | Delete cache directories |
| `package prepack` | Prepares a package for packaging before publishing |
| `package postpack` | Restores the changes made by the prepack command |
| `repo build` | Build packages in the project, excluding bundled app and backend packages |
| `repo start` | Starts packages in the repo for local development |
| `repo clean` | Delete cache and output directories |
| `build-workspace` | Builds a temporary dist workspace from the provided packages |
## Documentation
- [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md)
- [Backstage Documentation](https://backstage.io/docs)
- [Build System](https://backstage.io/docs/tooling/cli/build-system)
+32
View File
@@ -0,0 +1,32 @@
#!/usr/bin/env node
/*
* 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.
*/
const path = require('node:path');
/* eslint-disable-next-line no-restricted-syntax */
const isLocal = require('node:fs').existsSync(
path.resolve(__dirname, '../src'),
);
if (isLocal) {
require('@backstage/cli-node/config/nodeTransform.cjs');
}
const { runCliModule } = require('@backstage/cli-node');
const cliModule = require(isLocal ? '../src/index' : '..').default;
const pkg = require('../package.json');
runCliModule({ module: cliModule, name: pkg.name, version: pkg.version });
@@ -0,0 +1,10 @@
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: backstage-cli-module-build
title: '@backstage/cli-module-build'
description: CLI module for Backstage CLI
spec:
lifecycle: experimental
type: backstage-cli-module
owner: tooling-maintainers
+156
View File
@@ -0,0 +1,156 @@
## CLI Report file for "@backstage/cli-module-build"
> Do not edit this file. It is a report generated by `yarn build:api-reports`
### `backstage-cli-module-build`
```
Usage: @backstage/cli-module-build [options] [command]
Options:
-V, --version
-h, --help
Commands:
build-workspace
help [command]
package [command]
repo [command]
```
### `backstage-cli-module-build build-workspace`
```
Usage: @backstage/cli-module-build build-workspace <workspace-dir> [packages...]
Options:
--always-pack
-h, --help
```
### `backstage-cli-module-build package`
```
Usage: @backstage/cli-module-build package [options] [command] [command]
Options:
-h, --help
Commands:
build
clean
help [command]
postpack
prepack
start
```
### `backstage-cli-module-build package build`
```
Usage: @backstage/cli-module-build package build
Options:
--config <string>
--minify
--module-federation
--role <string>
--skip-build-dependencies
--stats
-h, --help
```
### `backstage-cli-module-build package clean`
```
Usage: @backstage/cli-module-build package clean
Options:
-h, --help
```
### `backstage-cli-module-build package postpack`
```
Usage: @backstage/cli-module-build package postpack
Options:
-h, --help
```
### `backstage-cli-module-build package prepack`
```
Usage: @backstage/cli-module-build package prepack
Options:
-h, --help
```
### `backstage-cli-module-build package start`
```
Usage: @backstage/cli-module-build package start
Options:
--check
--config <string>
--entrypoint <string>
--inspect <string>
--inspect-brk <string>
--link <string>
--require <string>
--role <string>
-h, --help
```
### `backstage-cli-module-build repo`
```
Usage: @backstage/cli-module-build repo [options] [command] [command]
Options:
-h, --help
Commands:
build
clean
help [command]
start
```
### `backstage-cli-module-build repo build`
```
Usage: @backstage/cli-module-build repo build
Options:
--all
--minify
--since <string>
-h, --help
```
### `backstage-cli-module-build repo clean`
```
Usage: @backstage/cli-module-build repo clean
Options:
-h, --help
```
### `backstage-cli-module-build repo start`
```
Usage: @backstage/cli-module-build repo start [packages...]
Options:
--config <string>
--inspect <string>
--inspect-brk <string>
--link <string>
--plugin <string>
--require <string>
-h, --help
```
@@ -0,0 +1,31 @@
/*
* 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.
*/
// This script is used to pick up and set the public path of the Webpack bundle
// at runtime. The meta tag is injected by the app build, but only present in
// the `index.html.tmpl` file. The runtime value of the meta tag is populated by
// the app backend, when it templates the final `index.html` file.
//
// This is needed for additional chunks to use the correct public path, and it
// is not possible to set the `__webpack_public_path__` variable outside of the
// build itself. The Webpack output also does not read any <base> tags or
// similar, this seems to be the only way to dynamically configure the public
// path at runtime.
const el = document.querySelector('meta[name="backstage-public-path"]');
const path = el?.getAttribute('content');
if (path) {
__webpack_public_path__ = path;
}
+106
View File
@@ -0,0 +1,106 @@
{
"name": "@backstage/cli-module-build",
"version": "0.0.0",
"description": "CLI module for Backstage CLI",
"backstage": {
"role": "cli-module"
},
"publishConfig": {
"access": "public",
"main": "dist/index.cjs.js",
"types": "dist/index.d.ts"
},
"homepage": "https://backstage.io",
"repository": {
"type": "git",
"url": "https://github.com/backstage/backstage",
"directory": "packages/cli-module-build"
},
"license": "Apache-2.0",
"main": "src/index.ts",
"types": "src/index.ts",
"bin": "bin/backstage-cli-module-build",
"files": [
"dist",
"bin",
"config",
"templates"
],
"scripts": {
"build": "backstage-cli package build",
"clean": "backstage-cli package clean",
"lint": "backstage-cli package lint",
"prepack": "backstage-cli package prepack",
"postpack": "backstage-cli package postpack",
"test": "backstage-cli package test"
},
"dependencies": {
"@backstage/cli-common": "workspace:^",
"@backstage/cli-node": "workspace:^",
"@backstage/config": "workspace:^",
"@backstage/config-loader": "workspace:^",
"@backstage/errors": "workspace:^",
"@backstage/module-federation-common": "workspace:^",
"@manypkg/get-packages": "^1.1.3",
"@module-federation/enhanced": "^0.21.6",
"@pmmmwh/react-refresh-webpack-plugin": "^0.6.0",
"@rollup/plugin-commonjs": "^26.0.0",
"@rollup/plugin-json": "^6.0.0",
"@rollup/plugin-node-resolve": "^15.0.0",
"@rollup/plugin-yaml": "^4.0.0",
"@rspack/core": "^1.4.11",
"@rspack/dev-server": "^1.1.4",
"@rspack/plugin-react-refresh": "^1.4.3",
"@swc/core": "^1.15.6",
"bfj": "^9.0.2",
"buffer": "^6.0.3",
"chalk": "^4.0.0",
"chokidar": "^3.3.1",
"cleye": "^2.3.0",
"cross-spawn": "^7.0.3",
"css-loader": "^6.5.1",
"ctrlc-windows": "^2.1.0",
"esbuild-loader": "^4.0.0",
"eslint-rspack-plugin": "^4.2.1",
"eslint-webpack-plugin": "^4.2.0",
"fork-ts-checker-webpack-plugin": "^9.0.0",
"fs-extra": "^11.2.0",
"glob": "^7.1.7",
"html-webpack-plugin": "^5.6.3",
"lodash": "^4.17.21",
"mini-css-extract-plugin": "^2.4.2",
"node-stdlib-browser": "^1.3.1",
"npm-packlist": "^5.0.0",
"p-queue": "^6.6.2",
"postcss": "^8.1.0",
"postcss-import": "^16.1.0",
"process": "^0.11.10",
"raw-loader": "^4.0.2",
"react-dev-utils": "^12.0.0-next.60",
"react-refresh": "^0.18.0",
"rollup": "^4.27.3",
"rollup-plugin-dts": "^6.1.0",
"rollup-plugin-esbuild": "^6.1.1",
"rollup-plugin-postcss": "^4.0.0",
"rollup-pluginutils": "^2.8.2",
"shell-quote": "^1.8.1",
"style-loader": "^3.3.1",
"swc-loader": "^0.2.3",
"tar": "^7.5.6",
"ts-checker-rspack-plugin": "^1.1.5",
"ts-morph": "^24.0.0",
"util": "^0.12.3",
"webpack": "~5.105.0",
"webpack-dev-server": "^5.0.0",
"yml-loader": "^2.1.0",
"yn": "^4.0.0"
},
"devDependencies": {
"@backstage/backend-test-utils": "workspace:^",
"@backstage/cli": "workspace:^",
"@types/fs-extra": "^11.0.0",
"@types/lodash": "^4.14.151",
"@types/npm-packlist": "^3.0.0",
"@types/shell-quote": "^1.7.5"
}
}
+13
View File
@@ -0,0 +1,13 @@
## API Report File for "@backstage/cli-module-build"
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
```ts
import { CliModule } from '@backstage/cli-node';
// @public (undocumented)
const _default: CliModule;
export default _default;
// (No @packageDocumentation comment for this package)
```
@@ -17,9 +17,9 @@
import fs from 'fs-extra';
import { cli } from 'cleye';
import { createDistWorkspace } from '../lib/packager';
import type { CommandContext } from '../../../wiring/types';
import type { CliCommandContext } from '@backstage/cli-node';
export default async ({ args, info }: CommandContext) => {
export default async ({ args, info }: CliCommandContext) => {
// Normalize legacy --alwaysYarnPack alias (a genuinely different name, not
// just a casing variant — type-flag handles camelCase/kebab-case natively)
const normalizedArgs = args.map(a => {
@@ -29,9 +29,9 @@ import { buildFrontend } from '../../../lib/buildFrontend';
import { buildBackend } from '../../../lib/buildBackend';
import { isValidUrl } from '../../../lib/urls';
import chalk from 'chalk';
import type { CommandContext } from '../../../../../wiring/types';
import type { CliCommandContext } from '@backstage/cli-node';
export default async ({ args, info }: CommandContext) => {
export default async ({ args, info }: CliCommandContext) => {
const {
flags: {
role,
@@ -17,9 +17,9 @@
import { cli } from 'cleye';
import fs from 'fs-extra';
import { targetPaths } from '@backstage/cli-common';
import type { CommandContext } from '../../../../wiring/types';
import type { CliCommandContext } from '@backstage/cli-node';
export default async ({ args, info }: CommandContext) => {
export default async ({ args, info }: CliCommandContext) => {
cli({ help: info, booleanFlagNegation: true }, undefined, args);
await fs.remove(targetPaths.resolve('dist'));
await fs.remove(targetPaths.resolve('dist-types'));
@@ -17,9 +17,9 @@
import { cli } from 'cleye';
import { targetPaths } from '@backstage/cli-common';
import { revertProductionPack } from '../../lib/packager/productionPack';
import type { CommandContext } from '../../../../wiring/types';
import type { CliCommandContext } from '@backstage/cli-node';
export default async ({ args, info }: CommandContext) => {
export default async ({ args, info }: CliCommandContext) => {
cli({ help: info, booleanFlagNegation: true }, undefined, args);
await revertProductionPack(targetPaths.dir);
};
@@ -20,9 +20,9 @@ import { targetPaths } from '@backstage/cli-common';
import { productionPack } from '../../lib/packager/productionPack';
import { publishPreflightCheck } from '../../lib/publishing';
import { createTypeDistProject } from '../../lib/typeDistProject';
import type { CommandContext } from '../../../../wiring/types';
import type { CliCommandContext } from '@backstage/cli-node';
export default async ({ args, info }: CommandContext) => {
export default async ({ args, info }: CliCommandContext) => {
cli({ help: info, booleanFlagNegation: true }, undefined, args);
publishPreflightCheck({
@@ -19,9 +19,9 @@ import { startPackage } from './startPackage';
import { resolveLinkedWorkspace } from './resolveLinkedWorkspace';
import { findRoleFromCommand } from '../../../lib/role';
import { targetPaths } from '@backstage/cli-common';
import type { CommandContext } from '../../../../../wiring/types';
import type { CliCommandContext } from '@backstage/cli-node';
export default async ({ args, info }: CommandContext) => {
export default async ({ args, info }: CliCommandContext) => {
const {
flags: {
config,
@@ -29,9 +29,9 @@ import {
import { buildFrontend } from '../../lib/buildFrontend';
import { buildBackend } from '../../lib/buildBackend';
import { createScriptOptionsParser } from '../../lib/optionsParser';
import type { CommandContext } from '../../../../wiring/types';
import type { CliCommandContext } from '@backstage/cli-node';
export default async ({ args, info }: CommandContext) => {
export default async ({ args, info }: CliCommandContext) => {
const {
flags: { all, since, minify },
} = cli(
@@ -19,9 +19,9 @@ import fs from 'fs-extra';
import { resolve as resolvePath } from 'node:path';
import { PackageGraph } from '@backstage/cli-node';
import { run, targetPaths } from '@backstage/cli-common';
import type { CommandContext } from '../../../../wiring/types';
import type { CliCommandContext } from '@backstage/cli-node';
export default async ({ args, info }: CommandContext) => {
export default async ({ args, info }: CliCommandContext) => {
cli({ help: info, booleanFlagNegation: true }, undefined, args);
const packages = await PackageGraph.listTargetPackages();
@@ -26,7 +26,7 @@ import { cli } from 'cleye';
import { resolveLinkedWorkspace } from '../package/start/resolveLinkedWorkspace';
import { startPackage } from '../package/start/startPackage';
import { parseArgs } from 'node:util';
import type { CommandContext } from '../../../../wiring/types';
import type { CliCommandContext } from '@backstage/cli-node';
const ACCEPTED_PACKAGE_ROLES: Array<PackageRole | undefined> = [
'frontend',
@@ -35,7 +35,7 @@ const ACCEPTED_PACKAGE_ROLES: Array<PackageRole | undefined> = [
'backend-plugin',
];
export default async ({ args, info }: CommandContext) => {
export default async ({ args, info }: CliCommandContext) => {
const {
flags: { plugin, config, require: requirePath, link, inspect, inspectBrk },
_: namesOrPaths,
@@ -14,10 +14,11 @@
* limitations under the License.
*/
import { createCliPlugin } from '../../wiring/factory';
import { createCliModule } from '@backstage/cli-node';
import packageJson from '../package.json';
export const buildPlugin = createCliPlugin({
pluginId: 'build',
export default createCliModule({
packageJson,
init: async reg => {
reg.addCommand({
path: ['package', 'build'],
@@ -84,5 +85,3 @@ export const buildPlugin = createCliPlugin({
});
},
});
export default buildPlugin;
@@ -29,10 +29,10 @@ import { ModuleFederationPlugin } from '@module-federation/enhanced/rspack';
import fs from 'fs-extra';
import { optimization as optimizationConfig } from './optimization';
import pickBy from 'lodash/pickBy';
import { runOutput, targetPaths } from '@backstage/cli-common';
import { findOwnPaths, runOutput, targetPaths } from '@backstage/cli-common';
import { transforms } from './transforms';
import { version } from '../../../../wiring/version';
import { version } from '../../../package.json';
import yn from 'yn';
import { hasReactDomClient } from './hasReactDomClient';
import { createWorkspaceLinkingPlugins } from './linkWorkspaces';
@@ -330,7 +330,8 @@ export async function createConfig(
devtool: isDev ? 'eval-cheap-module-source-map' : 'source-map',
context: paths.targetPath,
entry: [
require.resolve('@backstage/cli/config/webpack-public-path'),
/* eslint-disable-next-line no-restricted-syntax */
findOwnPaths(__dirname).resolve('config/webpack-public-path'),
...(options.additionalEntryPoints ?? []),
paths.targetEntry,
],
@@ -26,11 +26,10 @@ import * as tar from 'tar';
import partition from 'lodash/partition';
import { run, targetPaths } from '@backstage/cli-common';
import {
dependencies as cliDependencies,
devDependencies as cliDevDependencies,
} from '../../../../../package.json';
} from '../../../package.json';
import {
BuildOptions,
buildPackages,

Some files were not shown because too many files have changed in this diff Show More