Merge branch 'master' into blam/actions-permissions

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2026-03-17 09:50:34 +01:00
committed by GitHub
704 changed files with 16218 additions and 5111 deletions
+256
View File
@@ -0,0 +1,256 @@
---
id: mcp-actions
title: MCP Actions Backend
description: The MCP Actions Backend exposes actions registered with the Actions Registry as MCP tools.
---
The MCP Actions Backend exposes [Actions](../backend-system/core-services/actions.md) registered with the [Actions Registry](../backend-system/core-services/actions-registry.md) as MCP tools.
## Installation
This plugin is installed via the `@backstage/plugin-mcp-actions-backend` package. To add it to your backend package, run the following command:
```bash title="From your root directory"
yarn --cwd packages/backend add @backstage/plugin-mcp-actions-backend
```
Then, add the plugin to your backend:
```ts title="packages/backend/src/index.ts"
const backend = createBackend();
// ...
backend.add(import('@backstage/plugin-mcp-actions-backend'));
// ...
backend.start();
```
## Actions Configuration
Populate the `pluginSources` configuration with the list of plugins you want exposed as MCP tools like so:
```yaml
backend:
actions:
pluginSources:
- 'catalog'
- 'my-custom-plugin'
```
For details on filtering actions, see the [filtering actions documentation](../backend-system/core-services/actions.md#filtering-actions).
## Single MCP Server Name & Description
You can configure the name and description of your Backstage MCP server with the following config:
```yaml title="app-config.yaml"
mcpActions:
name: 'My MCP Server' # defaults to "backstage"
description: 'Tools for interacting with My MCP Server' # optional
```
## Namespaced Tool Names
By default, MCP tool names include the plugin ID prefix to avoid collisions across plugins. For example, an action registered as `greet-user` by `my-custom-plugin` is exposed as `my-custom-plugin.greet-user`.
You can disable this if you need the short names for backward compatibility:
```yaml title="app-config.yaml"
mcpActions:
namespacedToolNames: false
```
## Multiple MCP Servers
By default, the plugin serves a single MCP server at `/api/mcp-actions/v1` that exposes all available actions. You can split actions into multiple focused servers by configuring `mcpActions.servers`, where each key becomes a separate MCP server endpoint.
```yaml title="app-config.yaml"
mcpActions:
servers:
catalog:
name: 'Backstage Catalog'
description: 'Tools for interacting with the software catalog'
filter:
include:
- id: 'catalog:*'
scaffolder:
name: 'Backstage Scaffolder'
description: 'Tools for creating new software from templates'
filter:
include:
- id: 'scaffolder:*'
```
This creates two MCP server endpoints:
- `http://localhost:7007/api/mcp-actions/v1/catalog`
- `http://localhost:7007/api/mcp-actions/v1/scaffolder`
Each server uses include filter rules with glob patterns on action IDs to control which actions are exposed. For example, `id: 'catalog:*'` matches all actions registered by the catalog plugin.
When `mcpActions.servers` is not configured, the plugin behaves exactly as before with a single server at `/api/mcp-actions/v1`.
### Filter Rules
Include and exclude filter rules support glob patterns on action IDs and attribute matching. Exclude rules take precedence over include rules. When include rules are specified, actions must match at least one include rule to be exposed.
```yaml title="app-config.yaml"
mcpActions:
servers:
catalog:
name: 'Backstage Catalog'
filter:
include:
- id: 'catalog:*'
exclude:
- attributes:
destructive: true
```
## Authentication Configuration
By default, the Backstage backend requires authentication for all requests.
### External Access with Static Tokens
:::warning
This is meant to be a temporary workaround until device authentication is completed.
:::
Configure external access with static tokens in your app configuration:
```yaml title="app-config.yaml"
backend:
auth:
externalAccess:
- type: static
options:
token: ${MCP_TOKEN}
subject: mcp-clients
accessRestrictions:
- plugin: mcp-actions
- plugin: catalog
```
Generate a secure token:
```bash
node -p 'require("crypto").randomBytes(24).toString("base64")'
```
Set the `MCP_TOKEN` environment variable and configure your MCP client to send:
```http
Authorization: Bearer <token>
```
For more details about external access tokens and service-to-service authentication, see the
[Service-to-Service Auth documentation](../auth/service-to-service-auth.md).
### Experimental: Dynamic Client Registration
:::warning
This feature is highly experimental and only works with the New Frontend System. Proceed with caution.
:::
You can configure the auth-backend and install the auth frontend plugin to enable **Dynamic Client Registration** with MCP clients. This means you do not need to manually configure a token in your MCP client settings. Instead, a client can request a token on your behalf. When adding the MCP server to an MCP client like Cursor or Claude, a popup requiring your approval will open in your Backstage instance (powered by the auth plugin).
**Requirements:**
- The `@backstage/plugin-auth-backend` plugin must be configured.
- The new `@backstage/plugin-auth` frontend plugin must be configured.
**Installation:**
1. Install the `@backstage/plugin-auth` frontend plugin:
```bash
yarn --cwd packages/app add @backstage/plugin-auth
```
2. If you use [feature discovery](../frontend-system/architecture/10-app.md#feature-discovery) the plugin will be added automatically, if you prefer explicit registration, register the plugin as a feature like this:
```tsx title="packages/app/src/App.tsx"
import authPlugin from '@backstage/plugin-auth';
const app = createApp({
features: [
// ...other features
authPlugin,
],
});
```
3. Enable the feature:
```yaml title="app-config.yaml"
auth:
experimentalDynamicClientRegistration:
enabled: true
# Optional: limit valid callback URLs for added security
allowedRedirectUriPatterns:
- cursor://*
```
## Configuring MCP Clients
The MCP server supports both **Server-Sent Events (SSE)** and **Streamable HTTP** protocols.
:::warning
The SSE protocol is deprecated and will be removed in a future release.
:::
### Endpoints
- **Streamable HTTP:** `http://localhost:7007/api/mcp-actions/v1`
- **SSE (deprecated):** `http://localhost:7007/api/mcp-actions/v1/sse`
```json
{
"mcpServers": {
"backstage-actions": {
"url": "http://localhost:7007/api/mcp-actions/v1",
"headers": {
"Authorization": "Bearer ${MCP_TOKEN}"
}
}
}
}
```
The `${MCP_TOKEN}` environment variable would be an [external access static token](#external-access-with-static-tokens).
### Multiple Servers
When `mcpActions.servers` is configured, each server key becomes part of the URL. For example, with servers named `catalog` and `scaffolder`:
- `http://localhost:7007/api/mcp-actions/v1/catalog`
- `http://localhost:7007/api/mcp-actions/v1/scaffolder`
```json
{
"mcpServers": {
"backstage-catalog": {
"url": "http://localhost:7007/api/mcp-actions/v1/catalog",
"headers": {
"Authorization": "Bearer ${MCP_TOKEN}"
}
},
"backstage-scaffolder": {
"url": "http://localhost:7007/api/mcp-actions/v1/scaffolder",
"headers": {
"Authorization": "Bearer ${MCP_TOKEN}"
}
}
}
}
```
## Metrics
The MCP Actions Backend emits metrics for the following operations:
- `mcp.server.operation.duration`: The duration taken to process an individual MCP operation
- `mcp.server.session.duration`: The duration of the MCP session from the perspective of the server
See the [OpenTelemetry tutorial](../tutorials/setup-opentelemetry.md) to learn how to make these metrics available.
+30
View File
@@ -0,0 +1,30 @@
---
id: well-known-actions
title: Well-known Actions
description: This section lists a number of well-known actions that are part of the Actions Registry.
---
This section lists a number of well-known [Actions](../backend-system/core-services/actions.md) registered with the [Actions Registry](../backend-system/core-services/actions-registry.md).
## Actions
This is a (non-exhaustive) list of actions that are known to be part of the Actions Registry. Entries are in the format: "`action-name` (Action Title): Shortened Action Description"
### Auth
- `auth.who-am-i` (Who Am I): Returns the catalog entity and user info for the currently authenticated user. This action requires user credentials and cannot be used with service or unauthenticated credentials.
### Catalog
- `catalog.get-catalog-entity` (Get Catalog Entity): This allows you to get a single entity from the software catalog.
- `catalog.query-catalog-entities` (Query Catalog Entities): Query entities from the Backstage Software Catalog using predicate filters.
- `catalog.register-entity` (Register entity in the Catalog): Registers one or more entities in the Backstage catalog by creating a Location entity that points to a remote `catalog-info.yaml` file.
- `catalog.unregister-entity` (Unregister entity from the Catalog): Unregisters a Location entity and all entities it owns from the Backstage catalog.
- `catalog.validate-entity` (Validate Catalog Entity): This action can be used to validate `catalog-info.yaml` file contents meant to be used with the software catalog.
### Scaffolder
- `scaffolder.dry-run-template` (Dry Run Scaffolder Template): Dry-runs a scaffolder template to validate it without making changes. Returns success with execution logs, or errors for validation failures.
- `scaffolder.list-scaffolder-actions` (List Scaffolder Actions): Lists all installed Scaffolder actions.
- `scaffolder.list-scaffolder-tasks` (List Scaffolder Tasks): This allows you to list scaffolder tasks that have been created.
- `scaffolder.get-scaffolder-task-logs` (Get Scaffolder Task Logs): This allows you to fetch the logs of a given scaffolder task.
+1 -1
View File
@@ -83,7 +83,7 @@ migrate to your own custom API.
First, you'll need to define a new Utility API reference. If you're only using
the API for sign-in, you can put the definition in `packages/app/src/apis.ts`.
However, if you need to access your auth API inside plugins you you'll need to
However, if you need to access your auth API inside plugins you'll need to
export it from a common package. If you don't already have one, we recommend
creating `@internal/apis` and from there exporting the API reference.
+4 -1
View File
@@ -144,7 +144,10 @@ are separated out into their own folder, see further down.
- [`dev-utils/`](https://github.com/backstage/backstage/tree/master/packages/dev-utils) -
Helps you setup a plugin for isolated development so that it can be served
separately.
separately. This is for plugins using the legacy frontend system.
- [`frontend-dev-utils/`](https://github.com/backstage/backstage/tree/master/packages/frontend-dev-utils) -
Utilities for developing frontend plugins using the new frontend system. Provides the `createDevApp` helper for setting up a minimal development app in a plugin's `dev/` entry point.
- [`e2e-test/`](https://github.com/backstage/backstage/tree/master/packages/e2e-test) -
Another CLI that can be run to try out what would happen if you build all the
+48 -1
View File
@@ -150,7 +150,54 @@ Some more real world usable examples:
#### Full text filtering
TODO
You can perform a text search across entity fields using the `fullTextFilterTerm`
query parameter. This performs a case-insensitive substring match against the
values in the entity YAML fields.
By default, when no `fullTextFilterFields` parameter is specified, the search
runs against the current sort field (from `orderField`), or `metadata.uid` if
no sort field is set. This means that without specifying fields explicitly, the
search may not match against the fields you expect.
To control which fields are searched, pass the `fullTextFilterFields` query
parameter as a comma-separated list of entity field paths.
Query parameters:
- `fullTextFilterTerm` - The text to search for (case insensitive, substring match)
- `fullTextFilterFields` - A comma-separated list of entity field paths to
search against (e.g. `metadata.name,metadata.title`)
Example:
```text
/entities/by-query?fullTextFilterTerm=my-service&fullTextFilterFields=metadata.name,metadata.title
Return entities whose metadata.name OR metadata.title contains "my-service"
```
Some more real world usable examples:
- Search for components by name:
`/entities/by-query?filter=kind=component&fullTextFilterTerm=payment&fullTextFilterFields=metadata.name`
- Search across both name and title:
`/entities/by-query?filter=kind=system&fullTextFilterTerm=platform&fullTextFilterFields=metadata.name,metadata.title`
- Combine with other filters (e.g. owned by a specific group):
`/entities/by-query?filter=kind=component,relations.ownedBy=group:default/my-team&fullTextFilterTerm=api&fullTextFilterFields=metadata.name`
:::note Note
Full text filtering is mutually exclusive with cursor-based pagination. When a
`cursor` is provided, `fullTextFilterTerm` and `fullTextFilterFields` are
ignored — the cursor already encodes the original filter parameters from the
initial request.
:::
#### Field selection
@@ -402,3 +402,46 @@ spec:
definition:
$openapi: ./spec/openapi.yaml # by using $openapi Backstage will now resolve all $ref instances
```
## Backstage OpenAPI Module
As Backstage increasingly uses OpenAPI to define its core APIs (such as the Catalog and Scaffolder), discovering and interacting with these APIs is essential for integrating external tools.
You can install the **Backstage OpenAPI Module** to easily expose the OpenAPI specifications for your Backstage instance plugins directly into the catalog.
### Installation
1. Install the module in your backend:
```bash
yarn --cwd packages/backend add @backstage/plugin-catalog-backend-module-backstage-openapi
```
2. Register the module in your backend:
```ts title="packages/backend/src/index.ts"
backend.add(
import('@backstage/plugin-catalog-backend-module-backstage-openapi'),
);
```
3. Add the configuration to your `app-config.yaml`:
```yaml title="app-config.yaml"
catalog:
providers:
backstageOpenapi:
plugins:
- catalog
- scaffolder
# Optional configuration:
# definitionFormat controls how generated definitions are serialized.
# Supported values: 'json' (default) or 'yaml'.
# definitionFormat: json
# entityOverrides can be used to override parts of the produced entities.
# For example, to add a tag to all generated APIs:
# entityOverrides:
# metadata:
# tags:
# - from-openapi
```
+6 -6
View File
@@ -89,12 +89,12 @@ page header, TechDocs Addons whose location is `Header` will not be rendered.
Addons can, in principle, be provided by any plugin! To make it easier to
discover available Addons, we've compiled a list of them here:
| Addon | Package/Plugin | Description |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`techDocsExpandableNavigationAddonModule`](https://backstage.io/api/stable/variables/_backstage_plugin-techdocs-module-addons-contrib.plugins_techdocs-module-addons-contrib_src_alpha.techDocsExpandableNavigationAddonModule.html) | `@backstage/plugin-techdocs-module-addons-contrib/alpha` | Allows TechDocs users to expand or collapse the entire TechDocs main navigation, and keeps the user's preferred state between documentation sites. |
| [`techDocsReportIssueAddonModule`](https://backstage.io/api/stable/variables/_backstage_plugin-techdocs-module-addons-contrib.plugins_techdocs-module-addons-contrib_src_alpha.techDocsReportIssueAddonModule.html) | `@backstage/plugin-techdocs-module-addons-contrib/alpha` | Allows TechDocs users to select a portion of text on a TechDocs page and open an issue against the repository that contains the documentation, populating the issue description with the selected text according to a configurable template. |
| [`techDocsTextSizeAddonModule`](https://backstage.io/api/stable/variables/_backstage_plugin-techdocs-module-addons-contrib.plugins_techdocs-module-addons-contrib_src_alpha.techDocsTextSizeAddonModule.html) | `@backstage/plugin-techdocs-module-addons-contrib/alpha` | This TechDocs addon allows users to customize text size on documentation pages, they can select how much they want to increase or decrease the font size via slider or buttons. The default value for font size is 100% and this setting is kept in the browser's local storage whenever it is changed. |
| [`techDocsLightBoxAddonModule`](https://backstage.io/api/stable/variables/_backstage_plugin-techdocs-module-addons-contrib.plugins_techdocs-module-addons-contrib_src_alpha.techDocsLightBoxAddonModule.html) | `@backstage/plugin-techdocs-module-addons-contrib/alpha` | This TechDocs addon allows users to open images in a light-box on documentation pages, they can navigate between images if there are several on one page. The image size of the light-box image is the same as the image size on the document page. When clicking on the zoom icon it zooms the image to fit in the screen (similar to `background-size: contain`). |
| Addon | Package/Plugin | Description |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`techDocsExpandableNavigationAddonModule`](https://backstage.io/api/stable/variables/_backstage_plugin-techdocs-module-addons-contrib.plugins_techdocs-module-addons-contrib_src_alpha.techDocsExpandableNavigationAddonModule.html) | `@backstage/plugin-techdocs-module-addons-contrib/alpha` | Allows TechDocs users to expand or collapse the entire TechDocs main navigation, and keeps the user's preferred state between documentation sites. |
| [`techDocsReportIssueAddonModule`](https://backstage.io/api/stable/variables/_backstage_plugin-techdocs-module-addons-contrib.plugins_techdocs-module-addons-contrib_src_alpha.techDocsReportIssueAddonModule.html) | `@backstage/plugin-techdocs-module-addons-contrib/alpha` | Allows TechDocs users to select a portion of text on a TechDocs page and open an issue against the repository that contains the documentation, populating the issue description with the selected text according to a configurable template. |
| [`techDocsTextSizeAddonModule`](https://backstage.io/api/stable/variables/_backstage_plugin-techdocs-module-addons-contrib.plugins_techdocs-module-addons-contrib_src_alpha.techDocsTextSizeAddonModule.html) | `@backstage/plugin-techdocs-module-addons-contrib/alpha` | This TechDocs addon allows users to customize text size on documentation pages, they can select how much they want to increase or decrease the font size via slider or buttons. The default value for font size is 100% and this setting is kept in the browser's local storage whenever it is changed. |
| [`techDocsLightBoxAddonModule`](https://backstage.io/api/stable/variables/_backstage_plugin-techdocs-module-addons-contrib.plugins_techdocs-module-addons-contrib_src_alpha.techDocsLightBoxAddonModule.html) | `@backstage/plugin-techdocs-module-addons-contrib/alpha` | This TechDocs addon allows users to open images in a light-box on documentation pages, they can navigate between images if there are several on one page. The image size of the light-box image is the same as the image size on the document page. When clicking on the zoom icon it zooms the image to fit in the screen (similar to `background-size: contain`). Images inside links are ignored to avoid blocking navigation. |
Got an Addon to contribute? Feel free to add a row above!
+6 -6
View File
@@ -126,12 +126,12 @@ page header, TechDocs Addons whose location is `Header` will not be rendered.
Addons can, in principle, be provided by any plugin! To make it easier to
discover available Addons, we've compiled a list of them here:
| Addon | Package/Plugin | Description |
| -------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`<ExpandableNavigation />`](https://backstage.io/api/stable/variables/_backstage_plugin-techdocs-module-addons-contrib.index.ExpandableNavigation.html) | `@backstage/plugin-techdocs-module-addons-contrib` | Allows TechDocs users to expand or collapse the entire TechDocs main navigation, and keeps the user's preferred state between documentation sites. |
| [`<ReportIssue />`](https://backstage.io/api/stable/variables/_backstage_plugin-techdocs-module-addons-contrib.index.ReportIssue.html) | `@backstage/plugin-techdocs-module-addons-contrib` | Allows TechDocs users to select a portion of text on a TechDocs page and open an issue against the repository that contains the documentation, populating the issue description with the selected text according to a configurable template. |
| [`<TextSize />`](https://backstage.io/api/stable/variables/_backstage_plugin-techdocs-module-addons-contrib.index.TextSize.html) | `@backstage/plugin-techdocs-module-addons-contrib` | This TechDocs addon allows users to customize text size on documentation pages, they can select how much they want to increase or decrease the font size via slider or buttons. The default value for font size is 100% and this setting is kept in the browser's local storage whenever it is changed. |
| [`<LightBox />`](https://backstage.io/api/stable/variables/_backstage_plugin-techdocs-module-addons-contrib.index.LightBox.html) | `@backstage/plugin-techdocs-module-addons-contrib` | This TechDocs addon allows users to open images in a light-box on documentation pages, they can navigate between images if there are several on one page. The image size of the light-box image is the same as the image size on the document page. When clicking on the zoom icon it zooms the image to fit in the screen (similar to `background-size: contain`). |
| Addon | Package/Plugin | Description |
| -------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`<ExpandableNavigation />`](https://backstage.io/api/stable/variables/_backstage_plugin-techdocs-module-addons-contrib.index.ExpandableNavigation.html) | `@backstage/plugin-techdocs-module-addons-contrib` | Allows TechDocs users to expand or collapse the entire TechDocs main navigation, and keeps the user's preferred state between documentation sites. |
| [`<ReportIssue />`](https://backstage.io/api/stable/variables/_backstage_plugin-techdocs-module-addons-contrib.index.ReportIssue.html) | `@backstage/plugin-techdocs-module-addons-contrib` | Allows TechDocs users to select a portion of text on a TechDocs page and open an issue against the repository that contains the documentation, populating the issue description with the selected text according to a configurable template. |
| [`<TextSize />`](https://backstage.io/api/stable/variables/_backstage_plugin-techdocs-module-addons-contrib.index.TextSize.html) | `@backstage/plugin-techdocs-module-addons-contrib` | This TechDocs addon allows users to customize text size on documentation pages, they can select how much they want to increase or decrease the font size via slider or buttons. The default value for font size is 100% and this setting is kept in the browser's local storage whenever it is changed. |
| [`<LightBox />`](https://backstage.io/api/stable/variables/_backstage_plugin-techdocs-module-addons-contrib.index.LightBox.html) | `@backstage/plugin-techdocs-module-addons-contrib` | This TechDocs addon allows users to open images in a light-box on documentation pages, they can navigate between images if there are several on one page. The image size of the light-box image is the same as the image size on the document page. When clicking on the zoom icon it zooms the image to fit in the screen (similar to `background-size: contain`). Images inside links are ignored to avoid blocking navigation. |
Got an Addon to contribute? Feel free to add a row above!
+1 -25
View File
@@ -46,31 +46,7 @@ App feature discovery lets you automatically discover and install features provi
Because feature discovery needs to interact with the compilation process, it is only available when using the `@backstage/cli` to build your app. It is hooked into the WebPack compilation process by scanning your app package for compatible dependencies, which are then made part of the app compilation bundle.
To enable frontend feature discovery, add the following configuration to your `app-config.yaml`:
```yaml
app:
packages: all
```
This will cause all dependencies in your app package to be installed automatically. If this is not desired, you can use include or exclude filters to narrow down the set of packages:
```yaml
app:
packages:
# Only the following packages will be included
include:
- '@backstage/plugin-catalog'
- '@backstage/plugin-scaffolder'
---
app:
packages:
# All but the following package will be included
exclude:
- '@backstage/plugin-catalog'
```
Note that you do not need to manually exclude packages that you also import explicitly in code, since plugin instances are deduplicated by the app. You will never end up with duplicate plugin installations except if they are in fact two different plugin instances with different IDs.
For information on how to configure feature discovery and other installation options, see [Installing Plugins](../building-apps/05-installing-plugins.md).
## Plugin Info Resolution
@@ -63,13 +63,9 @@ Visit the [built-in extensions](#customize-or-override-built-in-extensions) sect
Linking routes from different plugins requires this configuration. You can do this either through a configuration file or by coding, visit [this](https://backstage.io/docs/frontend-system/architecture/routes#binding-external-route-references) page for instructions.
### Enable feature discovery
### Install plugins
Use this setting to enable experimental feature discovery when building your app with `@backstage/cli`. With this configuration your application tries to discover and install package extensions automatically, check [here](../architecture/10-app.md#feature-discovery) for more details.
:::warning
Remember that package extensions that are not auto-discovered must be manually added to the application when creating an app. See [features](#install-features-manually) for more details.
:::
Plugins are typically installed by adding them as dependencies of your app package and relying on feature discovery to automatically detect them. For details on how this works, including how to manually install plugins or control which packages are discovered, see [Installing Plugins](./05-installing-plugins.md).
### Configure extensions individually
@@ -83,7 +79,7 @@ Previously you would customize the application routes, components, apis, sidebar
### Install features manually
A manual installation is required if your packages are not discovered automatically, either because you are not using `@backstage/cli` to build your application or because the features are defined in local modules in the app package. In order to manually install a feature, you must import it and pass it to the `createApp` function:
Most plugins are installed automatically through [feature discovery](./05-installing-plugins.md#feature-discovery). Manual installation is needed if your packages are not discovered automatically, either because you are not using `@backstage/cli` to build your application or because the features are defined in local modules in the app package. In order to manually install a feature, you must import it and pass it to the `createApp` function:
```tsx title="packages/app/src/App.tsx"
import { createApp } from '@backstage/frontend-defaults';
@@ -0,0 +1,71 @@
---
id: installing-plugins
title: Installing Plugins
sidebar_label: Installing Plugins
description: How to install frontend plugins in a Backstage app
---
Frontend plugins are installed in your Backstage app by adding them as dependencies of your app package. Most of the time this is all you need to do, as the app will automatically discover and install the plugin.
## Install a plugin package
To install a plugin, add it as a dependency to your app package. For example, to install the catalog plugin:
```bash title="From your Backstage root directory"
yarn --cwd packages/app add @backstage/plugin-catalog
```
If your app is set up with [feature discovery](#feature-discovery), the plugin will be automatically detected and installed in the app. No additional code changes are needed.
## Feature discovery
Feature discovery lets the app automatically discover and install plugins from the dependencies of your app package. This is enabled by setting `app.packages` to `all` in your `app-config.yaml`:
```yaml title="app-config.yaml"
app:
packages: all
```
This is the recommended setup and is the default for all new Backstage apps. With this enabled, any plugin that is added as a dependency of your app package will be automatically discovered and installed. You can use include or exclude filters to control which packages are discovered:
```yaml title="app-config.yaml"
app:
packages:
include:
- '@backstage/plugin-catalog'
- '@backstage/plugin-scaffolder'
```
```yaml title="app-config.yaml"
app:
packages:
exclude:
- '@backstage/plugin-catalog'
```
Feature discovery requires that your app is built using the `@backstage/cli`, which is the default for all Backstage apps. Note that you do not need to exclude packages that you also install manually in code, since plugin instances are deduplicated by the app.
For more details on how feature discovery works under the hood, see the [Feature Discovery](../architecture/10-app.md#feature-discovery) architecture documentation.
## Manual installation
If your app does not have [feature discovery](#feature-discovery) enabled, or if you need more control over the plugin installation, you can install plugins manually. This is done by importing the plugin and passing it to `createApp`:
```tsx title="packages/app/src/App.tsx"
import { createApp } from '@backstage/frontend-defaults';
import catalogPlugin from '@backstage/plugin-catalog/alpha';
const app = createApp({
features: [catalogPlugin],
});
export default app.createRoot();
```
Manual installation may also be necessary if you need to control the ordering of plugins, for example when customizing route priorities. Since manually installed plugins are deduplicated against automatically discovered ones, you can safely install a plugin both manually and through feature discovery without causing conflicts.
If you need to use a 3rd-party plugin that does not yet support the new frontend system, you can use the conversion utilities from `@backstage/core-compat-api` to wrap it. See [Converting 3rd-party Plugins](./06-plugin-conversion.md) for details.
## Configuring installed plugins
Once a plugin is installed, you can configure its extensions through the `app.extensions` section of your `app-config.yaml`. See [Configuring Extensions](./02-configuring-extensions.md) for details.
@@ -110,6 +110,21 @@ What we've built here is a very common type of plugin. It's a top-level tool tha
We have also provided external access to our route reference by passing it to the plugin `routes` option. This makes it possible for app integrators to bind an external link from a different plugin to our plugin page. You can read more about how this works in the [External Route References](../architecture/36-routes.md#external-route-references) section.
## Running a dev server
Each frontend plugin package has a `dev/` folder that is used as the entry point when you run `yarn start`. This is a convenient way to run your plugin in isolation during development. The `@backstage/frontend-dev-utils` package provides a `createDevApp` helper that sets up a minimal app for this purpose:
```tsx title="in dev/index.ts"
import { createDevApp } from '@backstage/frontend-dev-utils';
import myPlugin from '../src';
createDevApp({ features: [myPlugin] });
```
This will create and render a Backstage app with only your plugin installed. If you need to include additional features that your plugin depends on, pass them along in the `features` array. You can also use `bindRoutes` to wire up any external routes that your plugin depends on.
The dev setup is started by running `yarn start` in the plugin directory, which uses the `backstage-cli package start` command. It sets up a local development server with hot reloading, just like a full app.
## Utility APIs
Another type of extensions that is commonly used are [Utility APIs](../utility-apis/01-index.md). They can encapsulate shared pieces of functionality of your plugin, for example an API client for a backend service. You can optionally export your Utility API for other plugins to use, or allow integrators to replace the implementation of your Utility API with their own. For details on how to define and provide your own Utility API in your plugin, see the section on [creating Utility APIs](../utility-apis/02-creating.md).
+201
View File
@@ -0,0 +1,201 @@
---
id: homepage--old
title: Backstage homepage - Setup and Customization (Old Frontend System)
description: Documentation on setting up and customizing Backstage homepage
---
::::info
This documentation is for Backstage apps that still use the old frontend
system. If your app uses the new frontend system, read the
[current homepage guide](./homepage.md) instead.
::::
## Homepage
Having a good Backstage homepage can significantly improve the discoverability
of the platform. You want your users to find all the things they need right
from the homepage and never have to remember direct URLs in Backstage. The
[Home plugin](https://github.com/backstage/backstage/tree/master/plugins/home)
introduces a system for composing a homepage for Backstage in order to surface
relevant info and provide convenient shortcuts for common tasks. It's designed
with composability in mind with an open ecosystem that allows anyone to
contribute with any component, to be included in any homepage.
For App Integrators, the system is designed to be composable to give total
freedom in designing a Homepage that suits the needs of the organization. From
the perspective of a Component Developer who wishes to contribute with building
blocks to be included in Homepages, there's a convenient interface for bundling
the different parts and exporting them with both error boundary and lazy
loading handled under the surface.
At the end of this tutorial, you can expect:
- Your Backstage app to have a dedicated homepage instead of Software Catalog.
- Understand the composability of homepage and how to start customizing it for
your own organization.
### Prerequisites
Before we begin, make sure
- You have created your own standalone Backstage app using
[`@backstage/create-app`](./index.md#1-create-your-backstage-app) and not
using a fork of the [backstage](https://github.com/backstage/backstage)
repository.
- You do not have an existing homepage, and by default you are redirected to
Software Catalog when you open Backstage.
Now, let's get started by installing the home plugin and creating a simple
homepage for your Backstage app.
## Setup
### 1. Install the plugin
```bash title="From your Backstage root directory"
yarn --cwd packages/app add @backstage/plugin-home
```
### 2. Create a new HomePage component
Inside your `packages/app` directory, create a new file where our new homepage
component is going to live. Create `packages/app/src/components/home/HomePage.tsx`
with the following initial code
```tsx
export const HomePage = () => (
/* We will shortly compose a pretty homepage here. */
<h1>Welcome to Backstage!</h1>
);
```
### 3. Update router for the root `/` route
If you don't have a homepage already, most likely you have a redirect setup to
use the Catalog homepage as a homepage.
Inside your `packages/app/src/App.tsx`, look for
```tsx title="packages/app/src/App.tsx"
const routes = (
<FlatRoutes>
<Navigate key="/" to="catalog" />
{/* ... */}
</FlatRoutes>
);
```
Let's replace the `<Navigate>` line and use the new component we created in the
previous step as the new homepage.
```tsx title="packages/app/src/App.tsx"
/* highlight-add-start */
import { HomepageCompositionRoot } from '@backstage/plugin-home';
import { HomePage } from './components/home/HomePage';
/* highlight-add-end */
const routes = (
<FlatRoutes>
{/* highlight-remove-next-line */}
<Navigate key="/" to="catalog" />
{/* highlight-add-start */}
<Route path="/" element={<HomepageCompositionRoot />}>
<HomePage />
</Route>
{/* highlight-add-end */}
{/* ... */}
</FlatRoutes>
);
```
### 4. Update sidebar items
Let's update the route for "Home" in the Backstage sidebar to point to the new
homepage. We'll also add a Sidebar item to quickly open Catalog.
| Before | After |
| --------------------------------------------------------------------------------- | --------------------------------------------------------------------------- |
| ![Sidebar without Catalog](../assets/getting-started/sidebar-without-catalog.png) | ![Sidebar with Catalog](../assets/getting-started/sidebar-with-catalog.png) |
The code for the Backstage sidebar is most likely inside your
[`packages/app-legacy/src/components/Root/Root.tsx`](https://github.com/backstage/backstage/blob/master/packages/app-legacy/src/components/Root/Root.tsx).
Let's make the following changes
```tsx title="packages/app/src/components/Root/Root.tsx"
/* highlight-add-next-line */
import CategoryIcon from '@material-ui/icons/Category';
export const Root = ({ children }: PropsWithChildren<{}>) => (
<SidebarPage>
<Sidebar>
<SidebarLogo />
{/* ... */}
<SidebarGroup label="Menu" icon={<MenuIcon />}>
{/* Global nav, not org-specific */}
{/* highlight-remove-next-line */}
<SidebarItem icon={HomeIcon} to="catalog" text="Home" />
{/* highlight-add-start */}
<SidebarItem icon={HomeIcon} to="/" text="Home" />
<SidebarItem icon={CategoryIcon} to="catalog" text="Catalog" />
{/* highlight-add-end */}
<SidebarItem icon={ExtensionIcon} to="api-docs" text="APIs" />
<SidebarItem icon={LibraryBooks} to="docs" text="Docs" />
<SidebarItem icon={LayersIcon} to="explore" text="Explore" />
<SidebarItem icon={CreateComponentIcon} to="create" text="Create..." />
{/* End global nav */}
<SidebarDivider />
{/* ... */}
</SidebarGroup>
</Sidebar>
</SidebarPage>
);
```
That's it! You should now have _(although slightly boring)_ a homepage!
<!-- todo: Needs zoomable plugin -->
![Screenshot of a blank homepage](../assets/getting-started/simple-homepage.png)
In the next steps, we will make it interesting and useful!
#### Use the default template
There is a default homepage template
([storybook link](https://backstage.io/storybook/?path=/story/plugins-home-templates--default-template))
which we will use to set up our homepage. Checkout the
[blog post announcement](https://backstage.io/blog/2022/01/25/backstage-homepage-templates)
about the Backstage homepage templates for more information.
<!-- TODO for later: detailed instructions for using one of these templates. -->
#### Composing your homepage
Composing a homepage is no different from creating a regular React Component,
i.e. the App Integrator is free to include whatever content they like. However,
there are components developed with the homepage in mind. If you are looking
for components to use when composing your homepage, you can take a look at the
[collection of Homepage components](https://backstage.io/storybook?path=/story/plugins-home-components)
in storybook. If you don't find a component that suits your needs but want to
contribute, check the
[Contributing documentation](https://github.com/backstage/backstage/blob/master/plugins/home/README.md#contributing).
> If you want to use one of the available homepage templates you can find the
> [templates](https://backstage.io/storybook/?path=/story/plugins-home-templates)
> in the storybook under the "Home" plugin. And if you would like to contribute
> a template, please see the
> [Contributing documentation](https://github.com/backstage/backstage/blob/master/plugins/home/README.md#contributing)
```tsx
import Grid from '@material-ui/core/Grid';
import { HomePageCompanyLogo } from '@backstage/plugin-home';
export const HomePage = () => (
<Grid container spacing={3}>
<Grid item xs={12} md={4}>
<HomePageCompanyLogo />
</Grid>
</Grid>
);
```
+14 -173
View File
@@ -4,6 +4,13 @@ title: Backstage homepage - Setup and Customization
description: Documentation on setting up and customizing Backstage homepage
---
::::info
This documentation is written for the new frontend system, which is the default
in new Backstage apps. If your Backstage app still uses the old frontend system,
read the [old frontend system version of this guide](./homepage--old.md)
instead.
::::
## Homepage
Having a good Backstage homepage can significantly improve the discoverability of the platform. You want your users to find all the things they need right from the homepage and never have to remember direct URLs in Backstage. The [Home plugin](https://github.com/backstage/backstage/tree/master/plugins/home) introduces a system for composing a homepage for Backstage in order to surface relevant info and provide convenient shortcuts for common tasks. It's designed with composability in mind with an open ecosystem that allows anyone to contribute with any component, to be included in any homepage.
@@ -24,39 +31,17 @@ Before we begin, make sure
Now, let's get started by installing the home plugin and creating a simple homepage for your Backstage app.
## Setup Methods
## Setup
There are two ways to set up the home plugin, depending on which frontend system your Backstage app uses:
1. **New Frontend System (Recommended)** - For apps using the new plugin system with extensions and blueprints
2. **Legacy Frontend System** - For existing apps using the legacy plugin architecture
### New Frontend System Setup
If your Backstage app uses the [new frontend system](../frontend-system/index.md), follow these steps:
#### 1. Install the plugin
### 1. Install the plugin
```bash title="From your Backstage root directory"
yarn --cwd packages/app add @backstage/plugin-home
```
#### 2. Add the plugin to your app configuration
Once installed, the plugin is automatically available in your app through the default feature discovery. For more details and alternative installation methods, see [installing plugins](../frontend-system/building-apps/05-installing-plugins.md).
Update your `packages/app/src/app.tsx` to include the home plugin:
```tsx title="packages/app/src/app.tsx"
import homePlugin from '@backstage/plugin-home/alpha';
const app = createApp({
features: [
// ... other plugins
homePlugin,
],
});
```
#### 3. Configure the homepage as your root route
### 2. Configure the homepage as your root route
By default, the homepage will be available at `/home`. To make it your app's landing page at `/`, add this configuration to your `app-config.yaml`:
@@ -70,7 +55,7 @@ app:
The plugin will automatically add a "Home" navigation item to your sidebar and provide a basic homepage layout.
#### 4. Optional: Enable visit tracking
### 3. Optional: Enable visit tracking
Visit tracking is an optional feature that allows users to see their recently visited and most visited pages on the homepage. This feature is **disabled by default** to give you control over what data is collected and stored.
@@ -88,156 +73,12 @@ app:
- app-root-element:home/visit-listener: true
```
#### 5. Customizing your homepage
### 4. Customizing your homepage
The New Frontend System provides powerful customization options:
The home plugin provides powerful customization options:
**Custom Homepage Layouts**: Use the `HomePageLayoutBlueprint` from `@backstage/plugin-home-react/alpha` to create custom homepage layouts with your own design and widget arrangements. A layout receives the installed widgets and is responsible for rendering them. If no custom layout is installed, the plugin provides a built-in default.
**Adding Homepage Widgets**: Register custom widgets using the `HomePageWidgetBlueprint` from the `@backstage/plugin-home-react/alpha` package.
For detailed instructions on creating custom layouts, registering widgets, and advanced configuration options, see the [Home plugin documentation](https://github.com/backstage/backstage/tree/master/plugins/home#readme).
### Legacy Frontend System Setup
If your Backstage app uses the legacy frontend system, follow these steps:
#### 1. Install the plugin
```bash title="From your Backstage root directory"
yarn --cwd packages/app add @backstage/plugin-home
```
#### 2. Create a new HomePage component
Inside your `packages/app` directory, create a new file where our new homepage component is going to live. Create `packages/app/src/components/home/HomePage.tsx` with the following initial code
```tsx
export const HomePage = () => (
/* We will shortly compose a pretty homepage here. */
<h1>Welcome to Backstage!</h1>
);
```
#### 3. Update router for the root `/` route
If you don't have a homepage already, most likely you have a redirect setup to use the Catalog homepage as a homepage.
Inside your `packages/app/src/App.tsx`, look for
```tsx title="packages/app/src/App.tsx"
const routes = (
<FlatRoutes>
<Navigate key="/" to="catalog" />
{/* ... */}
</FlatRoutes>
);
```
Let's replace the `<Navigate>` line and use the new component we created in the previous step as the new homepage.
```tsx title="packages/app/src/App.tsx"
/* highlight-add-start */
import { HomepageCompositionRoot } from '@backstage/plugin-home';
import { HomePage } from './components/home/HomePage';
/* highlight-add-end */
const routes = (
<FlatRoutes>
{/* highlight-remove-next-line */}
<Navigate key="/" to="catalog" />
{/* highlight-add-start */}
<Route path="/" element={<HomepageCompositionRoot />}>
<HomePage />
</Route>
{/* highlight-add-end */}
{/* ... */}
</FlatRoutes>
);
```
#### 4. Update sidebar items
Let's update the route for "Home" in the Backstage sidebar to point to the new homepage. We'll also add a Sidebar item to quickly open Catalog.
| Before | After |
| --------------------------------------------------------------------------------- | --------------------------------------------------------------------------- |
| ![Sidebar without Catalog](../assets/getting-started/sidebar-without-catalog.png) | ![Sidebar with Catalog](../assets/getting-started/sidebar-with-catalog.png) |
The code for the Backstage sidebar is most likely inside your [`packages/app-legacy/src/components/Root/Root.tsx`](https://github.com/backstage/backstage/blob/master/packages/app-legacy/src/components/Root/Root.tsx).
Let's make the following changes
```tsx title="packages/app/src/components/Root/Root.tsx"
/* highlight-add-next-line */
import CategoryIcon from '@material-ui/icons/Category';
export const Root = ({ children }: PropsWithChildren<{}>) => (
<SidebarPage>
<Sidebar>
<SidebarLogo />
{/* ... */}
<SidebarGroup label="Menu" icon={<MenuIcon />}>
{/* Global nav, not org-specific */}
{/* highlight-remove-next-line */}
<SidebarItem icon={HomeIcon} to="catalog" text="Home" />
{/* highlight-add-start */}
<SidebarItem icon={HomeIcon} to="/" text="Home" />
<SidebarItem icon={CategoryIcon} to="catalog" text="Catalog" />
{/* highlight-add-end */}
<SidebarItem icon={ExtensionIcon} to="api-docs" text="APIs" />
<SidebarItem icon={LibraryBooks} to="docs" text="Docs" />
<SidebarItem icon={LayersIcon} to="explore" text="Explore" />
<SidebarItem icon={CreateComponentIcon} to="create" text="Create..." />
{/* End global nav */}
<SidebarDivider />
{/* ... */}
</SidebarGroup>
</Sidebar>
</SidebarPage>
);
```
That's it! You should now have _(although slightly boring)_ a homepage!
<!-- todo: Needs zoomable plugin -->
![Screenshot of a blank homepage](../assets/getting-started/simple-homepage.png)
In the next steps, we will make it interesting and useful!
### Use the default template
There is a default homepage template ([storybook link](https://backstage.io/storybook/?path=/story/plugins-home-templates--default-template)) which we will use to set up our homepage. Checkout the [blog post announcement](https://backstage.io/blog/2022/01/25/backstage-homepage-templates) about the Backstage homepage templates for more information.
<!-- TODO for later: detailed instructions for using one of these templates. -->
### Composing your homepage
Composing a homepage is no different from creating a regular React Component,
i.e. the App Integrator is free to include whatever content they like. However,
there are components developed with the homepage in mind. If you are looking
for components to use when composing your homepage, you can take a look at the
[collection of Homepage components](https://backstage.io/storybook?path=/story/plugins-home-components)
in storybook. If you don't find a component that suits your needs but want to
contribute, check the
[Contributing documentation](https://github.com/backstage/backstage/blob/master/plugins/home/README.md#contributing).
> If you want to use one of the available homepage templates you can find the
> [templates](https://backstage.io/storybook/?path=/story/plugins-home-templates)
> in the storybook under the "Home" plugin. And if you would like to contribute
> a template, please see the
> [Contributing documentation](https://github.com/backstage/backstage/blob/master/plugins/home/README.md#contributing)
```tsx
import Grid from '@material-ui/core/Grid';
import { HomePageCompanyLogo } from '@backstage/plugin-home';
export const HomePage = () => (
<Grid container spacing={3}>
<Grid item xs={12} md={4}>
<HomePageCompanyLogo />
</Grid>
</Grid>
);
```
@@ -61,7 +61,7 @@ the Azure catalog plugin:
yarn --cwd packages/backend add @backstage/plugin-catalog-backend-module-azure
```
Then updated your backend by adding the following line:
Then update your backend by adding the following line:
```ts title="packages/backend/src/index.ts"
backend.add(import('@backstage/plugin-catalog-backend'));
+1 -1
View File
@@ -97,7 +97,7 @@ the Azure catalog plugin:
yarn --cwd packages/backend add @backstage/plugin-catalog-backend-module-azure
```
Then updated your backend by adding the following line:
Then update your backend by adding the following line:
```ts title="packages/backend/src/index.ts"
backend.add(import('@backstage/plugin-catalog-backend'));
+1 -1
View File
@@ -41,7 +41,7 @@ catalog:
For large organizations, this plugin can take a long time, so be careful setting low frequency / timeouts and importing a large amount of users / groups for the first try.
:::
Finally, updated your backend by adding the following line:
Finally, update your backend by adding the following line:
```ts title="packages/backend/src/index.ts"
backend.add(import('@backstage/plugin-catalog-backend'));
+1 -1
View File
@@ -40,7 +40,7 @@ catalog:
timeout: PT15M
```
Finally, updated your backend by adding the following line:
Finally, update your backend by adding the following line:
```ts title="packages/backend/src/index.ts"
backend.add(import('@backstage/plugin-catalog-backend'));
+23
View File
@@ -0,0 +1,23 @@
---
id: org
title: Okta Organizational Data
sidebar_label: Org Data
description: Ingesting organizational data from Okta into Backstage
---
The Backstage catalog can be set up to ingest organizational data — users and
groups — directly from Okta. The result is a hierarchy of
[`User`](../../features/software-catalog/descriptor-format.md#kind-user) and
[`Group`](../../features/software-catalog/descriptor-format.md#kind-group) kind
entities that mirror your Okta organization.
This integration is provided by the community-maintained
[`@roadiehq/catalog-backend-module-okta`](https://github.com/RoadieHQ/roadie-backstage-plugins/tree/main/plugins/backend/catalog-backend-module-okta)
plugin, owned and maintained by [Roadie](https://roadie.io/).
## Installation and configuration
For setup instructions, including authentication options (API token and OAuth
2.0), user/group filtering, custom naming strategies, and entity transformers,
see the
[plugin documentation maintained by Roadie](https://github.com/RoadieHQ/roadie-backstage-plugins/tree/main/plugins/backend/catalog-backend-module-okta).
+1 -1
View File
@@ -115,7 +115,7 @@ description: Documentation landing page.
<ul>
<li><a href='https://backstage.io/docs/contribute/'>Contributor's Guide</a></li>
<li><a href='https://backstage.io/docs/contribute/getting-involved'>Getting Involved</a></li>
<li><a href=https://backstage.io/docs/contribute/project-structure'>Backstage Project Structure</a></li>
<li><a href='https://backstage.io/docs/contribute/project-structure'>Backstage Project Structure</a></li>
</ul>
</td>
</tr>
+1 -1
View File
@@ -30,7 +30,7 @@ This section assumes that you are using the
Backstage is primarily designed to be deployed in a protected environment rather than being exposed to the public internet. From a confidentiality and integrity perspective, Backstage is designed to protect against unauthorized access to data and to ensure that data is not tampered with. However, Backstage does not provide more than rudimentary protection against denial of service attacks, and it is the responsibility of the operator to ensure that the Backstage deployment is protected against such attacks. A common and recommended way to protect a Backstage deployment from unauthorized access is to deploy it behind an authenticating proxy such as AWSs ALB, GCPs IAP, or Cloudflare Access.
Users that are signed-in in to Backstage generally have full access to all information and actions. If more fine-grained control is required, the [permissions system](../permissions/overview.md) should be enabled and configured to restrict access as necessary.
Users that are signed in to Backstage generally have full access to all information and actions. If more fine-grained control is required, the [permissions system](../permissions/overview.md) should be enabled and configured to restrict access as necessary.
An operator is responsible for protecting the integrity of configuration files as it may otherwise be possible to introduce vulnerable configurations, as well as the confidentiality of configured secrets related to Backstage as these typically include authentication details to third party systems.
+14
View File
@@ -294,6 +294,20 @@ will be set up that listens to the protocol, host and port set by `app.baseUrl`
in the configuration. If needed it is also possible to override the listening
options through the `app.listen` configuration.
For frontend plugin packages using the new frontend system, the recommended way to
set up the `dev/index` entry point is to use the `createDevApp` helper from
`@backstage/frontend-dev-utils`. It creates and renders a minimal Backstage app
with your plugin loaded:
```tsx title="in dev/index.ts"
import { createDevApp } from '@backstage/frontend-dev-utils';
import myPlugin from '../src';
createDevApp({ features: [myPlugin] });
```
For the legacy frontend system, the `@backstage/dev-utils` package provides equivalent helpers.
The frontend development bundling is currently based on
[Webpack](https://webpack.js.org/) and
[Webpack Dev Server](https://webpack.js.org/configuration/dev-server/). The
+132 -1
View File
@@ -204,6 +204,129 @@ Options:
--module-federation Build a package as a module federation remote. Applies to frontend plugin packages only.
```
## package bundle
:::caution Experimental
This command is experimental and may receive breaking changes in future releases
without a deprecation period. It is hidden from the main `--help` output.
:::
Bundle a plugin for dynamic loading. This creates a self-contained plugin
package that can be deployed independently and loaded dynamically by a Backstage
application. Supports both backend and frontend plugins.
Unlike regular builds, the bundle command:
- Creates a fully self-contained plugin deliverable
- Produces module federation assets (frontend) or includes plugin dependencies in the plugin's private `node_modules`, building and packing (with `yarn pack`) the local `workspace:^` dependencies first (backend).
- Generates a config schema from plugin-related packages only.
- Validates that the plugin exports valid dynamic loading entry points (backend only)
### Usage
```bash
# Bundle the current package (output: ./bundle/)
yarn backstage-cli package bundle
# Bundle to a specific directory (output: ../dynamic-plugins/<mangled-package-name>/)
yarn backstage-cli package bundle --output-destination ../dynamic-plugins
# Override the bundle subdirectory name
yarn backstage-cli package bundle --output-name my-plugin-bundle
# Clean output before bundling
yarn backstage-cli package bundle --clean
# Skip building for the plugin and its local dependencies
yarn backstage-cli package bundle --no-build
# Skip dependency installation and entrypoint validation
yarn backstage-cli package bundle --no-install
# Stream detailed output from build, pack, and install steps
yarn backstage-cli package bundle --verbose
# Use a pre-built dist workspace for batch bundling.
# First, create the workspace with:
# backstage-cli build-workspace <output-dir> [packages...] --alwaysPack
# Then pass <output-dir> as --pre-packed-dir:
yarn backstage-cli package bundle --pre-packed-dir ../dist-workspace
```
### Options
```text
Usage: backstage-cli package bundle [options]
Bundle a plugin for dynamic loading
Options:
--output-destination <dir> Directory in which the bundle subdirectory is created.
Defaults to the current package directory.
--output-name <name> Name of the bundle subdirectory. Defaults to "bundle" when
output stays in the package directory, or to the mangled
package name (e.g. myorg-plugin-foo) when
--output-destination is specified.
--clean Clean the output directory before bundling
--no-build Skip building packages (assumes they are already built)
--no-install Skip dependency installation and entrypoint validation.
--verbose Stream detailed output from internal steps (build, pack,
install) to the console. Without this flag, output is
captured to per-step log files and only shown on error.
--pre-packed-dir <dir> Path to a pre-built dist workspace (from
build-workspace --alwaysPack). Skips local dependency
packing and uses pre-packed packages directly. For frontend
plugins, this also enables yarn.lock generation for SBOM.
```
### Output Contract
The bundle output is a directory that can be deployed as a standalone unit.
Consumers of the bundle (such as `@backstage/backend-dynamic-feature-service`
or `@backstage/frontend-dynamic-feature-loader`) can rely on the following
guarantees:
**All bundles:**
- A `package.json` at the bundle root with entry points configured for dynamic
loading. The `backstage.role` and `files` fields are preserved from the source package.
- A `dist/` directory containing the built plugin code.
- A `dist/.config-schema.json` file (when any config schemas apply) containing
gathered schemas from the plugin, its local workspace dependencies, and
third-party dependencies. Schemas from unrelated Backstage packages are excluded.
- No `scripts` or `devDependencies` in `package.json`.
**Backend plugins** (`backend-plugin`, `backend-plugin-module`):
- A `node_modules/` directory with all production dependencies (including local
workspace dependencies), pinned to their exact versions from the source lockfile.
- `bundleDependencies` is set to `true` in `package.json`.
**Frontend plugins** (`frontend-plugin`, `frontend-plugin-module`):
- `main` points to `dist/remoteEntry.js` (the Module Federation remote entry).
- `types` points to `dist/@mf-types/index.d.ts` when type declarations are
available.
- No embedded `node_modules/` directory.
### Environment Variables
The bundle command supports the same environment variables as the Backstage yarn plugin
for resolving `backstage:^` version specifiers:
- `BACKSTAGE_MANIFEST_FILE`: Path to a local manifest file (for offline usage)
- `BACKSTAGE_VERSIONS_BASE_URL`: Custom base URL for fetching release manifests
### Supported Package Roles
The bundle command supports packages with the following roles:
- `backend-plugin`
- `backend-plugin-module`
- `frontend-plugin`
- `frontend-plugin-module`
## package lint
Lint a package. In addition to the default `eslint` behavior, this command will
@@ -414,9 +537,17 @@ package. This essentially calls `yarn pack` in each included package and unpacks
the resulting archive in the target `workspace-dir`.
```text
Usage: backstage-cli build-workspace [options] <workspace-dir>
Usage: backstage-cli build-workspace [options] <workspace-dir> [packages...]
Options:
--alwaysPack Force workspace output to be a result of running `yarn pack` on
each package (warning: very slow)
```
When `--alwaysPack` is used, the output directory can be passed to
`backstage-cli package bundle --pre-packed-dir` to speed up batch bundling of
multiple plugins from the same monorepo.
## create-github-app
Creates a GitHub App in your GitHub organization. This is an alternative to