diff --git a/.changeset/add-scheduler-cancel-task-test-utils.md b/.changeset/add-scheduler-cancel-task-test-utils.md
new file mode 100644
index 0000000000..242b103eef
--- /dev/null
+++ b/.changeset/add-scheduler-cancel-task-test-utils.md
@@ -0,0 +1,5 @@
+---
+'@backstage/backend-test-utils': patch
+---
+
+Added `cancelTask` to `MockSchedulerService` and mock scheduler service factory.
diff --git a/.changeset/add-scheduler-cancel-task.md b/.changeset/add-scheduler-cancel-task.md
new file mode 100644
index 0000000000..1f98bccb1c
--- /dev/null
+++ b/.changeset/add-scheduler-cancel-task.md
@@ -0,0 +1,6 @@
+---
+'@backstage/backend-plugin-api': minor
+'@backstage/backend-defaults': patch
+---
+
+Added `cancelTask` method to the `SchedulerService` interface and implementation, allowing cancellation of currently running scheduled tasks. For global tasks, the database lock is released and a periodic liveness check aborts the running task function. For local tasks, the task's abort signal is triggered directly. A new `POST /.backstage/scheduler/v1/tasks/:id/cancel` endpoint is also available.
diff --git a/.changeset/add-withApis-core-compat-api.md b/.changeset/add-withApis-core-compat-api.md
new file mode 100644
index 0000000000..135dcf87c7
--- /dev/null
+++ b/.changeset/add-withApis-core-compat-api.md
@@ -0,0 +1,5 @@
+---
+'@backstage/core-compat-api': patch
+---
+
+Added `withApis`, which is a Higher-Order Component for providing APIs as props to a component via `useApiHolder`.
diff --git a/.changeset/auth-backend-cimd-endpoint.md b/.changeset/auth-backend-cimd-endpoint.md
new file mode 100644
index 0000000000..5e2fd6761a
--- /dev/null
+++ b/.changeset/auth-backend-cimd-endpoint.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-auth-backend': patch
+---
+
+Added optional client metadata document endpoint at `/.well-known/oauth-client/cli.json` relative to the auth backend base URL for CLI authentication. Enabled when `auth.experimentalClientIdMetadataDocuments.enabled` is set to `true`.
diff --git a/.changeset/bui-analytics.md b/.changeset/bui-analytics.md
new file mode 100644
index 0000000000..65ba31b1cf
--- /dev/null
+++ b/.changeset/bui-analytics.md
@@ -0,0 +1,11 @@
+---
+'@backstage/ui': patch
+---
+
+Added analytics capabilities to the component library. Components with navigation behavior (Link, ButtonLink, Tab, MenuItem, Tag, Row) now fire analytics events on click when a `BUIProvider` is present.
+
+New exports: `BUIProvider`, `useAnalytics`, `getNodeText`, and associated types (`AnalyticsTracker`, `UseAnalyticsFn`, `BUIProviderProps`, `AnalyticsEventAttributes`).
+
+Components with analytics support now accept a `noTrack` prop to suppress event firing.
+
+**Affected components:** Link, ButtonLink, Tab, MenuItem, Tag, Row
diff --git a/.changeset/card-hybrid-click.md b/.changeset/card-hybrid-click.md
new file mode 100644
index 0000000000..48343c72a7
--- /dev/null
+++ b/.changeset/card-hybrid-click.md
@@ -0,0 +1,7 @@
+---
+'@backstage/ui': patch
+---
+
+Fixed interactive cards so that CardBody can scroll when the card has a constrained height. Previously, the overlay element blocked scroll events.
+
+**Affected components:** Card
diff --git a/.changeset/cli-auth-commands.md b/.changeset/cli-auth-commands.md
new file mode 100644
index 0000000000..e642996694
--- /dev/null
+++ b/.changeset/cli-auth-commands.md
@@ -0,0 +1,5 @@
+---
+'@backstage/cli': minor
+---
+
+Added new `auth` command group for authenticating the CLI with Backstage instances using OAuth 2.0 with a pre-registered client metadata document. Commands include `login`, `logout`, `list`, `show`, `print-token`, and `select` for managing multiple authenticated instances.
diff --git a/.changeset/cli-hidden-commands.md b/.changeset/cli-hidden-commands.md
new file mode 100644
index 0000000000..57d7468cc8
--- /dev/null
+++ b/.changeset/cli-hidden-commands.md
@@ -0,0 +1,5 @@
+---
+'@backstage/cli': patch
+---
+
+Internal refactor of the CLI command registration
diff --git a/.changeset/core-app-api-analytics-provider.md b/.changeset/core-app-api-analytics-provider.md
new file mode 100644
index 0000000000..f63bace0f3
--- /dev/null
+++ b/.changeset/core-app-api-analytics-provider.md
@@ -0,0 +1,5 @@
+---
+'@backstage/core-app-api': patch
+---
+
+Added `BUIProvider` from `@backstage/ui` to the app shell provider tree, enabling BUI components to fire analytics events through the Backstage analytics system.
diff --git a/.changeset/curvy-socks-punch.md b/.changeset/curvy-socks-punch.md
new file mode 100644
index 0000000000..a353824c13
--- /dev/null
+++ b/.changeset/curvy-socks-punch.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-notifications-backend-module-slack': minor
+---
+
+**BREAKING**: Only send direct messages to user entity recipients. Notifications sent to non-user entities no longer send Slack direct messages to resolved users.
diff --git a/.changeset/dependabot-6f7950a.md b/.changeset/dependabot-6f7950a.md
new file mode 100644
index 0000000000..ee4ac87e14
--- /dev/null
+++ b/.changeset/dependabot-6f7950a.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-techdocs': patch
+---
+
+chore(deps): bump `dompurify` from 3.3.1 to 3.3.2
diff --git a/.changeset/deprecate-headerpage-to-header.md b/.changeset/deprecate-headerpage-to-header.md
new file mode 100644
index 0000000000..83f673a422
--- /dev/null
+++ b/.changeset/deprecate-headerpage-to-header.md
@@ -0,0 +1,5 @@
+---
+'@backstage/ui': patch
+---
+
+Deprecated the `HeaderPage` component name in favor of `Header`. The old `HeaderPage`, `HeaderPageProps`, `HeaderPageOwnProps`, `HeaderPageBreadcrumb`, and `HeaderPageDefinition` exports are still available as deprecated aliases.
diff --git a/.changeset/deprecate-mock-api-classes.md b/.changeset/deprecate-mock-api-classes.md
new file mode 100644
index 0000000000..8aac45bc1f
--- /dev/null
+++ b/.changeset/deprecate-mock-api-classes.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-test-utils': patch
+---
+
+Deprecated standalone mock API exports in favor of the `mockApis` namespace. This includes the mock classes (`MockAlertApi`, `MockAnalyticsApi`, `MockConfigApi`, `MockErrorApi`, `MockFetchApi`, `MockFeatureFlagsApi`, `MockPermissionApi`, `MockStorageApi`, `MockTranslationApi`), their option types (`MockErrorApiOptions`, `MockFeatureFlagsApiOptions`), and the `ErrorWithContext` type. `MockFetchApiOptions` is kept as a non-deprecated export. Use the `mockApis` namespace instead, for example `mockApis.alert()` or `mockApis.alert.mock()`.
diff --git a/.changeset/deprecate-nav-item-blueprint.md b/.changeset/deprecate-nav-item-blueprint.md
new file mode 100644
index 0000000000..adb4f051dd
--- /dev/null
+++ b/.changeset/deprecate-nav-item-blueprint.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-plugin-api': patch
+---
+
+Deprecated `NavItemBlueprint`. Nav items are now automatically inferred from `PageBlueprint` extensions based on their `title` and `icon` params.
diff --git a/.changeset/deprecate-withApis-frontend-plugin-api.md b/.changeset/deprecate-withApis-frontend-plugin-api.md
new file mode 100644
index 0000000000..5e0408fd04
--- /dev/null
+++ b/.changeset/deprecate-withApis-frontend-plugin-api.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-plugin-api': patch
+---
+
+Deprecated `withApis`, use the `withApis` export from `@backstage/core-compat-api` instead.
diff --git a/.changeset/eager-toes-rest.md b/.changeset/eager-toes-rest.md
new file mode 100644
index 0000000000..ce9764574c
--- /dev/null
+++ b/.changeset/eager-toes-rest.md
@@ -0,0 +1,8 @@
+---
+'@backstage/core-plugin-api': patch
+'@backstage/core-app-api': patch
+'@backstage/frontend-plugin-api': patch
+'@backstage/frontend-app-api': patch
+---
+
+Add optional `description` field to plugin-level feature flags.
diff --git a/.changeset/eight-poems-take.md b/.changeset/eight-poems-take.md
new file mode 100644
index 0000000000..00f1d09466
--- /dev/null
+++ b/.changeset/eight-poems-take.md
@@ -0,0 +1,6 @@
+---
+'@backstage/catalog-client': minor
+'@backstage/plugin-catalog-backend': minor
+---
+
+Add an `onConflict` option to location creation that can refresh an existing location instead of throwing a conflict error.
diff --git a/.changeset/export-use-entity-route.md b/.changeset/export-use-entity-route.md
new file mode 100644
index 0000000000..c5ab9a9b33
--- /dev/null
+++ b/.changeset/export-use-entity-route.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog-react': minor
+---
+
+Exported `useEntityRefLink` hook that returns a function for generating entity page URLs from entity references.
diff --git a/.changeset/fix-dialog-api-jsx-type.md b/.changeset/fix-dialog-api-jsx-type.md
new file mode 100644
index 0000000000..67ece8913b
--- /dev/null
+++ b/.changeset/fix-dialog-api-jsx-type.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-plugin-api': patch
+---
+
+Fixed inconsistent `JSX.Element` type reference in the `DialogApiDialog.update` method signature.
diff --git a/.changeset/fluffy-colts-stop.md b/.changeset/fluffy-colts-stop.md
new file mode 100644
index 0000000000..9f6c9aba3d
--- /dev/null
+++ b/.changeset/fluffy-colts-stop.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog-backend-module-msgraph': patch
+---
+
+Fixed scheduler task remaining stuck in running state after pod termination by propagating AbortSignal into MicrosoftGraphOrgEntityProvider.read()
diff --git a/.changeset/happy-dogs-fly.md b/.changeset/happy-dogs-fly.md
new file mode 100644
index 0000000000..30b21a66e7
--- /dev/null
+++ b/.changeset/happy-dogs-fly.md
@@ -0,0 +1,25 @@
+---
+'@backstage/plugin-org': minor
+'@backstage/plugin-catalog-graph': minor
+'@backstage/create-app': patch
+---
+
+**BREAKING**: Migrated `MembersListCard`, `OwnershipCard`, and `CatalogGraphCard` to use BUI card primitives via `EntityInfoCard`.
+
+- `OwnershipCard`: Removed `variant` and `maxScrollHeight` props. Card height and scrolling are now controlled by the parent container â the card fills its container and the body scrolls automatically when content overflows.
+- `CatalogGraphCard`: Removed `variant` prop.
+- `MembersListCard`: Translation keys `subtitle`, `paginationLabel`, `aggregateMembersToggle.directMembers`, `aggregateMembersToggle.aggregatedMembers`, and `aggregateMembersToggle.ariaLabel` have been removed. The `title` key now includes `{{groupName}}`. New keys added: `cardLabel`, `noSearchResult`, `aggregateMembersToggle.label`.
+- `OwnershipCard`: Translation keys `aggregateRelationsToggle.directRelations`, `aggregateRelationsToggle.aggregatedRelations`, and `aggregateRelationsToggle.ariaLabel` have been removed. New key added: `aggregateRelationsToggle.label`.
+- Removed `MemberComponentClassKey` export, and `root` and `cardContent` from `MembersListCardClassKey`, `card` from `OwnershipCardClassKey`, and `card` from `CatalogGraphCardClassKey`.
+
+**Migration:**
+
+```diff
+-
++
+```
+
+```diff
+-
++
+```
diff --git a/.changeset/layout-html-attributes.md b/.changeset/layout-html-attributes.md
new file mode 100644
index 0000000000..6dff67e7f1
--- /dev/null
+++ b/.changeset/layout-html-attributes.md
@@ -0,0 +1,7 @@
+---
+'@backstage/ui': patch
+---
+
+Added support for native HTML div attributes on the `Flex`, `Grid`, and `Grid.Item` components.
+
+**Affected components:** Flex, Grid, Grid.Item
diff --git a/.changeset/menu-item-onaction-chaining.md b/.changeset/menu-item-onaction-chaining.md
new file mode 100644
index 0000000000..fe89854a07
--- /dev/null
+++ b/.changeset/menu-item-onaction-chaining.md
@@ -0,0 +1,5 @@
+---
+'@backstage/ui': patch
+---
+
+Fixed MenuItem `onAction` prop ordering so user-provided `onAction` handlers are chained rather than silently overwritten.
diff --git a/.changeset/migrate-cli-commands-to-cleye.md b/.changeset/migrate-cli-commands-to-cleye.md
new file mode 100644
index 0000000000..e6792423ee
--- /dev/null
+++ b/.changeset/migrate-cli-commands-to-cleye.md
@@ -0,0 +1,5 @@
+---
+'@backstage/cli': patch
+---
+
+Migrated remaining CLI command handlers from `commander` to `cleye` for argument parsing. Several camelCase CLI flags have been deprecated in favor of their kebab-case equivalents (e.g. `--successCache` â `--success-cache`). The old camelCase forms still work but will now log a deprecation warning. Please update any scripts or CI configurations to use the kebab-case versions.
diff --git a/.changeset/move-analytics-blueprint-deprecate.md b/.changeset/move-analytics-blueprint-deprecate.md
new file mode 100644
index 0000000000..c4ba61966a
--- /dev/null
+++ b/.changeset/move-analytics-blueprint-deprecate.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-plugin-api': patch
+---
+
+Deprecated `AnalyticsImplementationBlueprint` and `AnalyticsImplementationFactory` in favor of the exports from `@backstage/plugin-app-react`.
diff --git a/.changeset/move-analytics-blueprint-to-app-react.md b/.changeset/move-analytics-blueprint-to-app-react.md
new file mode 100644
index 0000000000..09dc530317
--- /dev/null
+++ b/.changeset/move-analytics-blueprint-to-app-react.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-app-react': patch
+---
+
+Added `AnalyticsImplementationBlueprint` and `AnalyticsImplementationFactory`, migrated from `@backstage/frontend-plugin-api`.
diff --git a/.changeset/move-extension-factory-middleware-app-api.md b/.changeset/move-extension-factory-middleware-app-api.md
new file mode 100644
index 0000000000..6cc77a5d26
--- /dev/null
+++ b/.changeset/move-extension-factory-middleware-app-api.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-app-api': patch
+---
+
+Added the `ExtensionFactoryMiddleware` type as a public export.
diff --git a/.changeset/move-extension-factory-middleware-plugin-api.md b/.changeset/move-extension-factory-middleware-plugin-api.md
new file mode 100644
index 0000000000..607da295a3
--- /dev/null
+++ b/.changeset/move-extension-factory-middleware-plugin-api.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-plugin-api': patch
+---
+
+Deprecated the `ExtensionFactoryMiddleware` type, which has been moved to `@backstage/frontend-app-api`.
diff --git a/.changeset/mui-to-bui-header.md b/.changeset/mui-to-bui-header.md
new file mode 100644
index 0000000000..2efa147e29
--- /dev/null
+++ b/.changeset/mui-to-bui-header.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-mui-to-bui': patch
+---
+
+Updated the MUI to BUI theme converter page to use the renamed `Header` component from `@backstage/ui`.
diff --git a/.changeset/plugin-app-analytics-wrapper.md b/.changeset/plugin-app-analytics-wrapper.md
new file mode 100644
index 0000000000..7e95de5f0f
--- /dev/null
+++ b/.changeset/plugin-app-analytics-wrapper.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-app': patch
+---
+
+Added `BUIProvider` from `@backstage/ui` to the app root, enabling BUI components to fire analytics events through the Backstage analytics system.
diff --git a/.changeset/remove-allowUnknownExtensionConfig-app-api.md b/.changeset/remove-allowUnknownExtensionConfig-app-api.md
new file mode 100644
index 0000000000..7be9c33a30
--- /dev/null
+++ b/.changeset/remove-allowUnknownExtensionConfig-app-api.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-app-api': minor
+---
+
+**BREAKING**: Removed the `allowUnknownExtensionConfig` option from `createSpecializedApp`. This flag had no effect and was a no-op, so no behavioral changes are expected.
diff --git a/.changeset/remove-allowUnknownExtensionConfig-defaults.md b/.changeset/remove-allowUnknownExtensionConfig-defaults.md
new file mode 100644
index 0000000000..3936cc226d
--- /dev/null
+++ b/.changeset/remove-allowUnknownExtensionConfig-defaults.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-defaults': minor
+---
+
+**BREAKING**: Removed the `allowUnknownExtensionConfig` option from `createApp`. This flag had no effect and was a no-op, so no behavioral changes are expected.
diff --git a/.changeset/remove-any-extension-data-ref.md b/.changeset/remove-any-extension-data-ref.md
new file mode 100644
index 0000000000..b220f5b871
--- /dev/null
+++ b/.changeset/remove-any-extension-data-ref.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-plugin-api': minor
+---
+
+**BREAKING**: Removed the deprecated `AnyExtensionDataRef` type. Use `ExtensionDataRef` without type parameters instead.
diff --git a/.changeset/remove-createPublicSignInApp.md b/.changeset/remove-createPublicSignInApp.md
new file mode 100644
index 0000000000..2d80d4790b
--- /dev/null
+++ b/.changeset/remove-createPublicSignInApp.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-defaults': minor
+---
+
+**BREAKING**: Removed the deprecated `createPublicSignInApp` function. Use `createApp` from `@backstage/frontend-defaults` with `appModulePublicSignIn` from `@backstage/plugin-app/alpha` instead.
diff --git a/.changeset/remove-page-blueprint-defaultpath.md b/.changeset/remove-page-blueprint-defaultpath.md
new file mode 100644
index 0000000000..848039a939
--- /dev/null
+++ b/.changeset/remove-page-blueprint-defaultpath.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-plugin-api': patch
+---
+
+Removed the deprecated `defaultPath` migration helper from `PageBlueprint` params.
diff --git a/.changeset/rename-page-tab-to-page-layout-tab.md b/.changeset/rename-page-tab-to-page-layout-tab.md
new file mode 100644
index 0000000000..c0b1f9e807
--- /dev/null
+++ b/.changeset/rename-page-tab-to-page-layout-tab.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-plugin-api': patch
+---
+
+Renamed the `PageTab` type to `PageLayoutTab`. The old `PageTab` name is now a deprecated type alias.
diff --git a/.changeset/renovate-2d5eed6.md b/.changeset/renovate-2d5eed6.md
new file mode 100644
index 0000000000..899fc43084
--- /dev/null
+++ b/.changeset/renovate-2d5eed6.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-scaffolder-react': patch
+---
+
+Updated dependency `flatted` to `3.3.4`.
diff --git a/.changeset/renovate-9a29a92.md b/.changeset/renovate-9a29a92.md
new file mode 100644
index 0000000000..5e8393e040
--- /dev/null
+++ b/.changeset/renovate-9a29a92.md
@@ -0,0 +1,5 @@
+---
+'@backstage/backend-defaults': patch
+---
+
+Updated dependency `express-rate-limit` to `^8.0.0`.
diff --git a/.changeset/simplify-extension-attach-to.md b/.changeset/simplify-extension-attach-to.md
new file mode 100644
index 0000000000..2beb00d056
--- /dev/null
+++ b/.changeset/simplify-extension-attach-to.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-plugin-api': minor
+---
+
+**BREAKING**: Simplified the `ExtensionAttachTo` type to only support a single attachment target. The array form for attaching to multiple extension points has been removed. Also removed the deprecated `ExtensionAttachToSpec` type alias.
diff --git a/.changeset/smooth-bees-invite.md b/.changeset/smooth-bees-invite.md
new file mode 100644
index 0000000000..104fd708b9
--- /dev/null
+++ b/.changeset/smooth-bees-invite.md
@@ -0,0 +1,7 @@
+---
+'@backstage/plugin-api-docs': patch
+---
+
+Updated dependency `graphiql` to `3.9.0` to address security vulnerability in `markdown-it` package.
+Updated dependency `@graphiql/react` to `0.29.0` to match the version used by `graphiql`.
+Moved dependency `graphql-config` to `devDependencies` as it is needed only for types.
diff --git a/.changeset/split-mcp-servers.md b/.changeset/split-mcp-servers.md
new file mode 100644
index 0000000000..7cfc24ad1f
--- /dev/null
+++ b/.changeset/split-mcp-servers.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-mcp-actions-backend': patch
+---
+
+Added support for splitting MCP actions into multiple servers via `mcpActions.servers` configuration. Each server gets its own endpoint at `/api/mcp-actions/v1/{key}` with actions scoped using include/exclude filter rules. Tool names are now namespaced with the plugin ID by default, configurable via `mcpActions.namespacedToolNames`. When `mcpActions.servers` is not configured, the plugin continues to serve a single server at `/api/mcp-actions/v1`.
diff --git a/.changeset/template-secrets-schema.md b/.changeset/template-secrets-schema.md
new file mode 100644
index 0000000000..5f6b0c4c9e
--- /dev/null
+++ b/.changeset/template-secrets-schema.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-scaffolder-common': minor
+---
+
+Added an optional `secrets` field to `TemplateEntityV1beta3` for configuring secrets validation. The schema for validating secrets is defined under `secrets.schema` as a JSON Schema object.
diff --git a/.changeset/template-secrets-validation.md b/.changeset/template-secrets-validation.md
new file mode 100644
index 0000000000..2b484ea758
--- /dev/null
+++ b/.changeset/template-secrets-validation.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-scaffolder-backend': minor
+---
+
+Added secrets schema validation for task creation, retry, and dry-run endpoints. When a template defines `spec.secrets.schema`, the API validates provided secrets against the schema and returns a `400` error if validation fails.
diff --git a/.changeset/use-api-holder-no-throw.md b/.changeset/use-api-holder-no-throw.md
new file mode 100644
index 0000000000..465cc9f401
--- /dev/null
+++ b/.changeset/use-api-holder-no-throw.md
@@ -0,0 +1,6 @@
+---
+'@backstage/frontend-plugin-api': patch
+'@backstage/core-plugin-api': patch
+---
+
+Changed `useApiHolder` to return an empty `ApiHolder` instead of throwing when used outside of an API context.
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index f4369920a5..e6dc0e98f5 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -3,7 +3,7 @@
"forwardPorts": [3000, 7007],
"build": { "dockerfile": "Dockerfile" },
"features": {
- "ghcr.io/devcontainers/features/common-utils:2.5.6": {},
+ "ghcr.io/devcontainers/features/common-utils:2.5.7": {},
"ghcr.io/devcontainers-extra/features/mkdocs:2": {}
},
"postCreateCommand": "bash .devcontainer/setup.sh",
diff --git a/.github/vale/config/vocabularies/Backstage/accept.txt b/.github/vale/config/vocabularies/Backstage/accept.txt
index 11df7fc1a0..fe8306afa8 100644
--- a/.github/vale/config/vocabularies/Backstage/accept.txt
+++ b/.github/vale/config/vocabularies/Backstage/accept.txt
@@ -246,6 +246,7 @@ Levenshtein
lightbox
Lightsail
limitranges
+liveness
LocalStack
lockdown
lockfile
diff --git a/.github/workflows/api-breaking-changes.yml b/.github/workflows/api-breaking-changes.yml
index dc63ed3b1b..4425f81905 100644
--- a/.github/workflows/api-breaking-changes.yml
+++ b/.github/workflows/api-breaking-changes.yml
@@ -27,7 +27,7 @@ jobs:
run: git fetch --depth 1 origin ${{ github.base_ref }}
- name: setup-node
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
+ uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 22.x
registry-url: https://registry.npmjs.org/
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index a3bf6a2eb1..24854003fa 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -49,7 +49,7 @@ jobs:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: use node.js ${{ matrix.node-version }}
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
+ uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: ${{ matrix.node-version }}
registry-url: https://registry.npmjs.org/ # Needed for auth
@@ -85,7 +85,7 @@ jobs:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: use node.js ${{ matrix.node-version }}
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
+ uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: ${{ matrix.node-version }}
registry-url: https://registry.npmjs.org/ # Needed for auth
@@ -241,7 +241,7 @@ jobs:
run: git fetch origin ${{ github.event.pull_request.base.ref }}
- name: use node.js ${{ matrix.node-version }}
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
+ uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: ${{ matrix.node-version }}
registry-url: https://registry.npmjs.org/ # Needed for auth
diff --git a/.github/workflows/deploy_docker-image.yml b/.github/workflows/deploy_docker-image.yml
index a53004dbdd..61841f4052 100644
--- a/.github/workflows/deploy_docker-image.yml
+++ b/.github/workflows/deploy_docker-image.yml
@@ -31,7 +31,7 @@ jobs:
ref: ${{ github.event.client_payload.version && env.RELEASE_VERSION || github.ref }}
- name: use node.js ${{ matrix.node-version }}
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
+ uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: ${{ matrix.node-version }}
registry-url: https://registry.npmjs.org/ # Needed for auth
diff --git a/.github/workflows/deploy_microsite.yml b/.github/workflows/deploy_microsite.yml
index ae9b3656d5..f88f84adad 100644
--- a/.github/workflows/deploy_microsite.yml
+++ b/.github/workflows/deploy_microsite.yml
@@ -59,7 +59,7 @@ jobs:
ref: refs/tags/${{ steps.find-release.outputs.result }}
- name: Use Node.js 22.x
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
+ uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 22.x
registry-url: https://registry.npmjs.org/ # Needed for auth
@@ -132,7 +132,7 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Use Node.js 22.x
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
+ uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 22.x
registry-url: https://registry.npmjs.org/ # Needed for auth
@@ -223,7 +223,7 @@ jobs:
egress-policy: audit
- name: Use Node.js 22.x
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
+ uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 22.x
registry-url: https://registry.npmjs.org/ # Needed for auth
diff --git a/.github/workflows/deploy_packages.yml b/.github/workflows/deploy_packages.yml
index 34dbcdb781..601751c005 100644
--- a/.github/workflows/deploy_packages.yml
+++ b/.github/workflows/deploy_packages.yml
@@ -71,7 +71,7 @@ jobs:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: use node.js ${{ matrix.node-version }}
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
+ uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: ${{ matrix.node-version }}
registry-url: https://registry.npmjs.org/ # Needed for auth
diff --git a/.github/workflows/mui-migration-tracker.yml b/.github/workflows/mui-migration-tracker.yml
index 2cb5c025e2..36107d33f2 100644
--- a/.github/workflows/mui-migration-tracker.yml
+++ b/.github/workflows/mui-migration-tracker.yml
@@ -26,7 +26,7 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Setup Node.js
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
+ uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 22.x
registry-url: https://registry.npmjs.org/ # Needed for auth
diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml
index c1c55f7abc..8f7c462785 100644
--- a/.github/workflows/scorecard.yml
+++ b/.github/workflows/scorecard.yml
@@ -67,6 +67,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard.
- name: 'Upload to code-scanning'
- uses: github/codeql-action/upload-sarif@f5c2471be782132e47a6e6f9c725e56730d6e9a3 # v3.32.3
+ uses: github/codeql-action/upload-sarif@820e3160e279568db735cee8ed8f8e77a6da7818 # v3.32.6
with:
sarif_file: results.sarif
diff --git a/.github/workflows/sync_bui-docs.yml b/.github/workflows/sync_bui-docs.yml
index 274307415c..15319c19b9 100644
--- a/.github/workflows/sync_bui-docs.yml
+++ b/.github/workflows/sync_bui-docs.yml
@@ -16,7 +16,7 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Use Node.js 22.x
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
+ uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 22.x
registry-url: https://registry.npmjs.org/ # Needed for auth
diff --git a/.github/workflows/sync_code-formatting.yml b/.github/workflows/sync_code-formatting.yml
index 924dd82a40..2ae13eaa25 100644
--- a/.github/workflows/sync_code-formatting.yml
+++ b/.github/workflows/sync_code-formatting.yml
@@ -20,7 +20,7 @@ jobs:
fetch-depth: 0
- name: use node.js ${{ matrix.node-version }}
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
+ uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: ${{ matrix.node-version }}
registry-url: https://registry.npmjs.org/ # Needed for auth
diff --git a/.github/workflows/sync_dependabot-changesets.yml b/.github/workflows/sync_dependabot-changesets.yml
index fb51949fd1..8768aff21a 100644
--- a/.github/workflows/sync_dependabot-changesets.yml
+++ b/.github/workflows/sync_dependabot-changesets.yml
@@ -21,11 +21,47 @@ jobs:
fetch-depth: 2
ref: ${{ github.head_ref }}
token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }}
+ - name: Verify Dependabot branch
+ id: verify
+ run: |
+ if git branch --show-current | grep -q '^dependabot/'; then
+ echo "is_dependabot=true" >> "$GITHUB_OUTPUT"
+ else
+ echo "Not a dependabot branch, skipping"
+ echo "is_dependabot=false" >> "$GITHUB_OUTPUT"
+ fi
- name: Configure Git
+ if: steps.verify.outputs.is_dependabot == 'true'
run: |
git config --global user.email noreply@backstage.io
git config --global user.name 'Github changeset workflow'
+ - name: Setup Node
+ if: steps.verify.outputs.is_dependabot == 'true'
+ uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
+ with:
+ node-version: 22.x
+ - name: Dedupe lockfiles
+ if: steps.verify.outputs.is_dependabot == 'true'
+ id: dedupe
+ run: |
+ corepack enable
+ changed=false
+
+ for dir in . docs-ui microsite; do
+ if [ "$dir" = "." ]; then lockfile=yarn.lock; else lockfile="$dir/yarn.lock"; fi
+ if git diff --name-only HEAD~1 | grep -q "^${lockfile}$"; then
+ yarn --cwd "$dir" dedupe
+ if ! git diff --quiet "$lockfile"; then
+ git add "$lockfile"
+ changed=true
+ fi
+ fi
+ done
+
+ echo "changed=$changed" >> "$GITHUB_OUTPUT"
- name: Generate changeset
+ if: steps.verify.outputs.is_dependabot == 'true'
+ id: changeset
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
with:
script: |
@@ -50,12 +86,6 @@ jobs:
await fs.writeFile(fileName, body);
}
- const branch = await exec.getExecOutput('git branch --show-current');
- if (!branch.stdout.startsWith('dependabot/')) {
- console.log('Not a dependabot branch, skipping');
- return;
- }
-
const diffOutput = await exec.getExecOutput('git diff --name-only HEAD~1');
const diffFiles = diffOutput.stdout.split('\n');
@@ -79,5 +109,9 @@ jobs:
const { stdout: commitMessage } = await exec.getExecOutput('git show --pretty=format:%s -s HEAD');
await createChangeset(fileName, commitMessage, packageNames);
await exec.exec('git', ['add', fileName]);
- await exec.exec('git commit -C HEAD --amend --no-edit');
- await exec.exec('git push --force');
+ core.setOutput('changed', 'true');
+ - name: Commit and push
+ if: steps.verify.outputs.is_dependabot == 'true' && (steps.dedupe.outputs.changed == 'true' || steps.changeset.outputs.changed == 'true')
+ run: |
+ git commit -C HEAD --amend --no-edit --no-verify
+ git push --force
diff --git a/.github/workflows/sync_patch-release.yml b/.github/workflows/sync_patch-release.yml
index e126fe2ab9..3e96529e53 100644
--- a/.github/workflows/sync_patch-release.yml
+++ b/.github/workflows/sync_patch-release.yml
@@ -32,7 +32,7 @@ jobs:
token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }}
- name: Use Node.js 22.x
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
+ uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 22.x
registry-url: https://registry.npmjs.org/ # Needed for auth
diff --git a/.github/workflows/sync_release-manifest.yml b/.github/workflows/sync_release-manifest.yml
index 91dffe32c9..0fee5f17b5 100644
--- a/.github/workflows/sync_release-manifest.yml
+++ b/.github/workflows/sync_release-manifest.yml
@@ -19,7 +19,7 @@ jobs:
ref: v${{ github.event.client_payload.version }}
- name: Use Node.js 22.x
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
+ uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 22.x
registry-url: https://registry.npmjs.org/ # Needed for auth
@@ -81,9 +81,5 @@ jobs:
owner: 'backstage',
repo: 'upgrade-helper-diff',
workflow_id: 'release.yml',
- ref: 'master',
- inputs: {
- version: require('./packages/create-app/package.json').version,
- releaseVersion: require('./package.json').version
- },
+ ref: 'master'
});
diff --git a/.github/workflows/sync_renovate-changesets.yml b/.github/workflows/sync_renovate-changesets.yml
index 8575cab760..0940de9c55 100644
--- a/.github/workflows/sync_renovate-changesets.yml
+++ b/.github/workflows/sync_renovate-changesets.yml
@@ -15,6 +15,29 @@ jobs:
with:
egress-policy: audit
+ - name: Approve yarn.lock-only PRs
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
+ with:
+ github-token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }}
+ script: |
+ const { data: files } = await github.rest.pulls.listFiles({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ pull_number: context.payload.pull_request.number,
+ });
+
+ if (files.some(file => !file.filename.endsWith("yarn.lock"))) {
+ console.log("Skipping approval since some files are not yarn.lock");
+ return;
+ }
+
+ await github.rest.pulls.createReview({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ pull_number: context.payload.pull_request.number,
+ event: "APPROVE",
+ });
+
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
diff --git a/.github/workflows/sync_snyk-github-issues.yml b/.github/workflows/sync_snyk-github-issues.yml
index 97311c9096..4a067dbbd3 100644
--- a/.github/workflows/sync_snyk-github-issues.yml
+++ b/.github/workflows/sync_snyk-github-issues.yml
@@ -19,7 +19,7 @@ jobs:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Use Node.js 22.x
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
+ uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 22.x
registry-url: https://registry.npmjs.org/ # Needed for auth
diff --git a/.github/workflows/sync_snyk-monitor.yml b/.github/workflows/sync_snyk-monitor.yml
index a8b364fbb8..985ff6fe9a 100644
--- a/.github/workflows/sync_snyk-monitor.yml
+++ b/.github/workflows/sync_snyk-monitor.yml
@@ -58,6 +58,6 @@ jobs:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
NODE_OPTIONS: --max-old-space-size=7168
- name: Upload Snyk report
- uses: github/codeql-action/upload-sarif@f5c2471be782132e47a6e6f9c725e56730d6e9a3 # v3.32.3
+ uses: github/codeql-action/upload-sarif@820e3160e279568db735cee8ed8f8e77a6da7818 # v3.32.6
with:
sarif_file: snyk.sarif
diff --git a/.github/workflows/sync_version-packages.yml b/.github/workflows/sync_version-packages.yml
index 7df18100b0..6cdcddc8be 100644
--- a/.github/workflows/sync_version-packages.yml
+++ b/.github/workflows/sync_version-packages.yml
@@ -30,7 +30,7 @@ jobs:
token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }}
- name: Use Node.js 22.x
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
+ uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 22.x
registry-url: https://registry.npmjs.org/ # Needed for auth
diff --git a/.github/workflows/verify_accessibility.yml b/.github/workflows/verify_accessibility.yml
index 0e8f3b7eb7..312cdd2903 100644
--- a/.github/workflows/verify_accessibility.yml
+++ b/.github/workflows/verify_accessibility.yml
@@ -26,7 +26,7 @@ jobs:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Use Node.js 22.x
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
+ uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 22.x
- name: yarn install
diff --git a/.github/workflows/verify_chromatic.yml b/.github/workflows/verify_chromatic.yml
index e8905e995f..13be85fe97 100644
--- a/.github/workflows/verify_chromatic.yml
+++ b/.github/workflows/verify_chromatic.yml
@@ -34,7 +34,7 @@ jobs:
fetch-depth: 10000 # Required to retrieve git history
- name: Use node.js ${{ matrix.node-version }}
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
+ uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: ${{ matrix.node-version }}
registry-url: https://registry.npmjs.org/ # Needed for auth
diff --git a/.github/workflows/verify_codeql.yml b/.github/workflows/verify_codeql.yml
index a919dff7b0..628577e09d 100644
--- a/.github/workflows/verify_codeql.yml
+++ b/.github/workflows/verify_codeql.yml
@@ -55,7 +55,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
- uses: github/codeql-action/init@f5c2471be782132e47a6e6f9c725e56730d6e9a3 # v3.32.3
+ uses: github/codeql-action/init@820e3160e279568db735cee8ed8f8e77a6da7818 # v3.32.6
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -66,7 +66,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
- uses: github/codeql-action/autobuild@f5c2471be782132e47a6e6f9c725e56730d6e9a3 # v3.32.3
+ uses: github/codeql-action/autobuild@820e3160e279568db735cee8ed8f8e77a6da7818 # v3.32.6
# âšī¸ Command-line programs to run using the OS shell.
# đ https://git.io/JvXDl
@@ -80,4 +80,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@f5c2471be782132e47a6e6f9c725e56730d6e9a3 # v3.32.3
+ uses: github/codeql-action/analyze@820e3160e279568db735cee8ed8f8e77a6da7818 # v3.32.6
diff --git a/.github/workflows/verify_e2e-linux.yml b/.github/workflows/verify_e2e-linux.yml
index f959027d86..4e0f82dd2c 100644
--- a/.github/workflows/verify_e2e-linux.yml
+++ b/.github/workflows/verify_e2e-linux.yml
@@ -67,7 +67,7 @@ jobs:
git config --global user.name 'GitHub e2e user'
- name: use node.js ${{ matrix.node-version }}
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
+ uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: ${{ matrix.node-version }}
registry-url: https://registry.npmjs.org/ # Needed for auth
diff --git a/.github/workflows/verify_e2e-techdocs.yml b/.github/workflows/verify_e2e-techdocs.yml
index 0526df7d5c..f3786f19c3 100644
--- a/.github/workflows/verify_e2e-techdocs.yml
+++ b/.github/workflows/verify_e2e-techdocs.yml
@@ -42,7 +42,7 @@ jobs:
python-version: '3.9'
- name: use node.js ${{ matrix.node-version }}
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
+ uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: ${{ matrix.node-version }}
- name: yarn install
diff --git a/.github/workflows/verify_e2e-windows.yml b/.github/workflows/verify_e2e-windows.yml
index 709c20a201..2b0e3d47c3 100644
--- a/.github/workflows/verify_e2e-windows.yml
+++ b/.github/workflows/verify_e2e-windows.yml
@@ -52,7 +52,7 @@ jobs:
git config --global user.name 'GitHub e2e user'
- name: use node.js ${{ matrix.node-version }}
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
+ uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: ${{ matrix.node-version }}
registry-url: https://registry.npmjs.org/ # Needed for auth
diff --git a/.github/workflows/verify_microsite.yml b/.github/workflows/verify_microsite.yml
index 0d9f857740..4fb6a98f3e 100644
--- a/.github/workflows/verify_microsite.yml
+++ b/.github/workflows/verify_microsite.yml
@@ -64,7 +64,7 @@ jobs:
ref: refs/tags/${{ steps.find-release.outputs.result }}
- name: Use Node.js 22.x
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
+ uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 22.x
registry-url: https://registry.npmjs.org/ # Needed for auth
@@ -134,7 +134,7 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Use Node.js 22.x
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
+ uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 22.x
registry-url: https://registry.npmjs.org/ # Needed for auth
@@ -219,7 +219,7 @@ jobs:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Use Node.js 22.x
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
+ uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 22.x
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
diff --git a/.github/workflows/verify_microsite_accessibility.yml b/.github/workflows/verify_microsite_accessibility.yml
index 76862a9fa7..ff7a91c716 100644
--- a/.github/workflows/verify_microsite_accessibility.yml
+++ b/.github/workflows/verify_microsite_accessibility.yml
@@ -22,7 +22,7 @@ jobs:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Use Node.js 22.x
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
+ uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 22.x
diff --git a/.github/workflows/verify_windows.yml b/.github/workflows/verify_windows.yml
index 7651160795..26657cbcd3 100644
--- a/.github/workflows/verify_windows.yml
+++ b/.github/workflows/verify_windows.yml
@@ -36,7 +36,7 @@ jobs:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: use node.js ${{ matrix.node-version }}
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
+ uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: ${{ matrix.node-version }}
registry-url: https://registry.npmjs.org/ # Needed for auth
diff --git a/docs-ui/src/app/components/button-link/props-definition.tsx b/docs-ui/src/app/components/button-link/props-definition.tsx
index deae5364df..e85a363b5a 100644
--- a/docs-ui/src/app/components/button-link/props-definition.tsx
+++ b/docs-ui/src/app/components/button-link/props-definition.tsx
@@ -62,6 +62,11 @@ export const buttonLinkPropDefs: Record = {
>
),
},
+ noTrack: {
+ type: 'boolean',
+ description:
+ 'Suppresses the automatic analytics click event, e.g. if you already have custom tracking.',
+ },
onSurface: {
type: 'enum',
values: ['0', '1', '2', '3', 'danger', 'warning', 'success', 'auto'],
diff --git a/docs-ui/src/app/components/header-page/components.tsx b/docs-ui/src/app/components/header/components.tsx
similarity index 84%
rename from docs-ui/src/app/components/header-page/components.tsx
rename to docs-ui/src/app/components/header/components.tsx
index 791afc5bbe..dc32bdd6cb 100644
--- a/docs-ui/src/app/components/header-page/components.tsx
+++ b/docs-ui/src/app/components/header/components.tsx
@@ -1,6 +1,6 @@
'use client';
-import { HeaderPage } from '../../../../../packages/ui/src/components/HeaderPage/HeaderPage';
+import { Header } from '../../../../../packages/ui/src/components/Header/Header';
import { Button } from '../../../../../packages/ui/src/components/Button/Button';
import { ButtonIcon } from '../../../../../packages/ui/src/components/ButtonIcon/ButtonIcon';
import {
@@ -31,7 +31,7 @@ const breadcrumbs = [
export const WithEverything = () => (
- (
export const WithLongBreadcrumbs = () => (
-
+
);
export const WithTabs = () => (
-
+
);
export const WithCustomActions = () => (
- Custom action}
- />
+ Custom action} />
);
export const WithMenu = () => (
-
diff --git a/docs-ui/src/app/components/header-page/page.mdx b/docs-ui/src/app/components/header/page.mdx
similarity index 88%
rename from docs-ui/src/app/components/header-page/page.mdx
rename to docs-ui/src/app/components/header/page.mdx
index ac99fb1af0..65dd8f2ea8 100644
--- a/docs-ui/src/app/components/header-page/page.mdx
+++ b/docs-ui/src/app/components/header/page.mdx
@@ -19,11 +19,11 @@ import {
} from './snippets';
import { PageTitle } from '@/components/PageTitle';
import { Theming } from '@/components/Theming';
-import { HeaderPageDefinition } from '../../../utils/definitions';
+import { HeaderDefinition } from '../../../utils/definitions';
import { ChangelogComponent } from '@/components/ChangelogComponent';
@@ -61,6 +61,6 @@ Use `customActions` to add a dropdown menu.
} code={withMenu} />
-
+
-
+
diff --git a/docs-ui/src/app/components/header-page/props-definition.tsx b/docs-ui/src/app/components/header/props-definition.tsx
similarity index 97%
rename from docs-ui/src/app/components/header-page/props-definition.tsx
rename to docs-ui/src/app/components/header/props-definition.tsx
index 393141870f..1b7a309b17 100644
--- a/docs-ui/src/app/components/header-page/props-definition.tsx
+++ b/docs-ui/src/app/components/header/props-definition.tsx
@@ -50,7 +50,7 @@ export const headerPagePropDefs: Record = {
type: 'complex',
description: 'Breadcrumb trail displayed above the title.',
complexType: {
- name: 'HeaderPageBreadcrumb[]',
+ name: 'HeaderBreadcrumb[]',
properties: {
label: {
type: 'string',
diff --git a/docs-ui/src/app/components/header-page/snippets.ts b/docs-ui/src/app/components/header/snippets.ts
similarity index 78%
rename from docs-ui/src/app/components/header-page/snippets.ts
rename to docs-ui/src/app/components/header/snippets.ts
index 607675717c..8dfef0e69e 100644
--- a/docs-ui/src/app/components/header-page/snippets.ts
+++ b/docs-ui/src/app/components/header/snippets.ts
@@ -1,8 +1,8 @@
-export const usage = `import { HeaderPage } from '@backstage/ui';
+export const usage = `import { Header } from '@backstage/ui';
-`;
+`;
-export const defaultSnippet = ``;
-export const withBreadcrumbs = ``;
-export const withTabs = ``;
-export const withCustomActions = `Custom action}
/>`;
-export const withMenu = `
diff --git a/docs-ui/src/app/components/link/props-definition.tsx b/docs-ui/src/app/components/link/props-definition.tsx
index be805d4540..951d67e8b4 100644
--- a/docs-ui/src/app/components/link/props-definition.tsx
+++ b/docs-ui/src/app/components/link/props-definition.tsx
@@ -68,6 +68,11 @@ export const linkPropDefs: Record = {
'Truncates text with ellipsis when it overflows its container.',
default: 'false',
},
+ noTrack: {
+ type: 'boolean',
+ description:
+ 'Suppresses the automatic analytics click event, e.g. if you already have custom tracking.',
+ },
standalone: {
type: 'boolean',
description: 'Removes underline by default. Underline appears on hover.',
diff --git a/docs-ui/src/app/components/menu/props-definition.tsx b/docs-ui/src/app/components/menu/props-definition.tsx
index 5e11b22737..f6cb88b3e2 100644
--- a/docs-ui/src/app/components/menu/props-definition.tsx
+++ b/docs-ui/src/app/components/menu/props-definition.tsx
@@ -309,6 +309,11 @@ export const menuItemPropDefs: Record = {
type: 'boolean',
description: 'Whether the item is disabled.',
},
+ noTrack: {
+ type: 'boolean',
+ description:
+ 'Suppresses the automatic analytics click event, e.g. if you already have custom tracking.',
+ },
textValue: {
type: 'string',
description: 'Text used for typeahead and accessibility.',
diff --git a/docs-ui/src/app/components/plugin-header/components.tsx b/docs-ui/src/app/components/plugin-header/components.tsx
index b3d831e718..045d0956c4 100644
--- a/docs-ui/src/app/components/plugin-header/components.tsx
+++ b/docs-ui/src/app/components/plugin-header/components.tsx
@@ -1,7 +1,7 @@
'use client';
import { PluginHeader } from '../../../../../packages/ui/src/components/PluginHeader/PluginHeader';
-import { HeaderPage } from '../../../../../packages/ui/src/components/HeaderPage/HeaderPage';
+import { Header } from '../../../../../packages/ui/src/components/Header/Header';
import { ButtonIcon } from '../../../../../packages/ui/src/components/ButtonIcon/ButtonIcon';
import { Button } from '../../../../../packages/ui/src/components/Button/Button';
import { MemoryRouter } from 'react-router-dom';
@@ -58,11 +58,11 @@ export const WithAllOptions = () => (
);
-export const WithHeaderPage = () => (
+export const WithHeader = () => (
<>
- Custom action}
diff --git a/docs-ui/src/app/components/plugin-header/page.mdx b/docs-ui/src/app/components/plugin-header/page.mdx
index 5f8e02bfc4..cbe4dfe141 100644
--- a/docs-ui/src/app/components/plugin-header/page.mdx
+++ b/docs-ui/src/app/components/plugin-header/page.mdx
@@ -4,7 +4,7 @@ import { Snippet } from '@/components/Snippet';
import {
WithAllOptionsAndTabs,
WithAllOptions,
- WithHeaderPage,
+ WithHeader,
} from './components';
import { headerPropDefs } from './props-definition';
import {
@@ -12,7 +12,7 @@ import {
simple,
defaultSnippet,
withTabs,
- withHeaderPage,
+ withHeader,
} from './snippets';
import { PageTitle } from '@/components/PageTitle';
import { Theming } from '@/components/Theming';
@@ -46,11 +46,11 @@ Tabs use React Router and highlight automatically based on the current route.
} code={withTabs} open />
-### Plugin header with HeaderPage
+### Plugin header with Header
-Combine with [HeaderPage](/components/header-page) for multi-level navigation.
+Combine with [Header](/components/header) for multi-level navigation.
-} code={withHeaderPage} open />
+} code={withHeader} open />
diff --git a/docs-ui/src/app/components/plugin-header/snippets.ts b/docs-ui/src/app/components/plugin-header/snippets.ts
index 4e9518af73..874a16184a 100644
--- a/docs-ui/src/app/components/plugin-header/snippets.ts
+++ b/docs-ui/src/app/components/plugin-header/snippets.ts
@@ -43,7 +43,7 @@ export const withTabs = ``;
-export const withHeaderPage = `
- = {
description:
'Row content. Can be a render function receiving column config.',
},
+ noTrack: {
+ type: 'boolean',
+ description:
+ 'Suppresses the automatic analytics click event, e.g. if you already have custom tracking.',
+ },
...classNamePropDefs,
...stylePropDefs,
};
diff --git a/docs-ui/src/app/components/tabs/props-definition.ts b/docs-ui/src/app/components/tabs/props-definition.ts
index e1c1f056cb..92d1c3d258 100644
--- a/docs-ui/src/app/components/tabs/props-definition.ts
+++ b/docs-ui/src/app/components/tabs/props-definition.ts
@@ -68,6 +68,11 @@ export const tabPropDefs: Record = {
default: 'false',
description: 'Disables this tab. Use for temporarily unavailable options.',
},
+ noTrack: {
+ type: 'boolean',
+ description:
+ 'Suppresses the automatic analytics click event, e.g. if you already have custom tracking.',
+ },
...childrenPropDefs,
...classNamePropDefs,
};
diff --git a/docs-ui/src/app/components/tag-group/props-definition.tsx b/docs-ui/src/app/components/tag-group/props-definition.tsx
index 3f64b03e8c..dc10d5f7e7 100644
--- a/docs-ui/src/app/components/tag-group/props-definition.tsx
+++ b/docs-ui/src/app/components/tag-group/props-definition.tsx
@@ -84,6 +84,11 @@ export const tagPropDefs: Record = {
type: 'boolean',
description: 'Whether the tag is disabled.',
},
+ noTrack: {
+ type: 'boolean',
+ description:
+ 'Suppresses the automatic analytics click event, e.g. if you already have custom tracking.',
+ },
...childrenPropDefs,
...classNamePropDefs,
};
diff --git a/docs-ui/src/app/get-started/installation/page.mdx b/docs-ui/src/app/get-started/installation/page.mdx
index cdb14d5924..c5421ae9d7 100644
--- a/docs-ui/src/app/get-started/installation/page.mdx
+++ b/docs-ui/src/app/get-started/installation/page.mdx
@@ -1,6 +1,10 @@
import { CodeBlock } from '@/components/CodeBlock';
import { Banner } from '@/components/Banner';
-import { snippet } from './snippets';
+import {
+ snippet,
+ analyticsSetupSnippet,
+ analyticsNoTrackSnippet,
+} from './snippets';
# Installation
@@ -44,3 +48,25 @@ your plugin and import the components you need.
/>
+
+## Analytics
+
+BUI components with navigation behavior â Link, ButtonLink, Tab, MenuItem, Tag, and Row â can fire analytics events when clicked. To enable this, you need to connect BUI's analytics layer to Backstage's analytics system.
+
+### Setup
+
+If you're using the **new frontend system**, analytics is wired automatically via `@backstage/plugin-app` â no setup required.
+
+For the **old frontend system**, the `BUIProvider` is included in the app shell from `@backstage/core-app-api` and works out of the box.
+
+If you need to set up the provider manually (e.g. in a custom app shell), wrap your app content with the `BUIProvider` and pass in Backstage's `useAnalytics` hook:
+
+
+
+### How it works
+
+Once configured, BUI components fire a `click` event through Backstage's analytics system when a user navigates. Events include the link text as the subject and the destination URL in the attributes, along with any `AnalyticsContext` metadata (such as `pluginId`) from the component's position in the tree.
+
+To suppress tracking on an individual component, use the `noTrack` prop:
+
+
diff --git a/docs-ui/src/app/get-started/installation/snippets.ts b/docs-ui/src/app/get-started/installation/snippets.ts
index 7e63005172..12dfff4f44 100644
--- a/docs-ui/src/app/get-started/installation/snippets.ts
+++ b/docs-ui/src/app/get-started/installation/snippets.ts
@@ -4,3 +4,16 @@ export const snippet = `import { Flex, Button, Text } from '@backstage/ui';
Hello World
;`;
+
+export const analyticsSetupSnippet = `import { BUIProvider } from '@backstage/ui';
+import { useAnalytics } from '@backstage/core-plugin-api';
+
+// Wrap your app content with the provider
+
+
+`;
+
+export const analyticsNoTrackSnippet = `// Suppress analytics for a specific link
+
+ Skip tracking
+`;
diff --git a/docs-ui/src/components/Toolbar/Toolbar.tsx b/docs-ui/src/components/Toolbar/Toolbar.tsx
index 4a071bf45e..ea094b2a81 100644
--- a/docs-ui/src/components/Toolbar/Toolbar.tsx
+++ b/docs-ui/src/components/Toolbar/Toolbar.tsx
@@ -3,6 +3,7 @@
import { useState, useEffect } from 'react';
import {
RiArrowDownSLine,
+ RiDiscordLine,
RiGithubLine,
RiMoonLine,
RiSearchLine,
@@ -95,6 +96,7 @@ export const Toolbar = ({ version }: ToolbarProps) => {
@@ -103,11 +105,23 @@ export const Toolbar = ({ version }: ToolbarProps) => {
+
+
+ =18.2.0"
- checksum: 10/10241f2e07826ce7d595cf9687a35c96cc9cf9eb68a9431d7dfa1b9df479dbef302874d28c0502cee2a536cf34722de7c49ed12d10a2b071e4e42ba4a278c516
+ checksum: 10/3d8f1d86b2bb20ab5e44d15f18811e928b0886f7710eb7a1516afb9913ba72e46facec5dfee382825139d800bcbb6704c15d0c760d0f977c12257d4af8db3295
languageName: node
linkType: hard
@@ -1558,8 +1558,8 @@ __metadata:
linkType: hard
"@uiw/codemirror-themes@npm:^4.23.7":
- version: 4.25.4
- resolution: "@uiw/codemirror-themes@npm:4.25.4"
+ version: 4.25.7
+ resolution: "@uiw/codemirror-themes@npm:4.25.7"
dependencies:
"@codemirror/language": "npm:^6.0.0"
"@codemirror/state": "npm:^6.0.0"
@@ -1568,7 +1568,7 @@ __metadata:
"@codemirror/language": ">=6.0.0"
"@codemirror/state": ">=6.0.0"
"@codemirror/view": ">=6.0.0"
- checksum: 10/aab62e2c16a10dbde4592cef704d386c1a9e3caece4ff0eed85e9d9a5acdeaf3fd8717e2cb6a6795e12e890b8600956effb52d453aacbc618934e7ae8c3e59e3
+ checksum: 10/6910a41090611b608dfd16eaf82c8e9e9edbab528fe06edfff5947050de6d1363749099a7462ecd3a6544c093feb8d8f1e2c1c7b687b889134c0e59966b1ff1f
languageName: node
linkType: hard
@@ -2821,8 +2821,8 @@ __metadata:
linkType: hard
"eslint@npm:^9":
- version: 9.39.2
- resolution: "eslint@npm:9.39.2"
+ version: 9.39.3
+ resolution: "eslint@npm:9.39.3"
dependencies:
"@eslint-community/eslint-utils": "npm:^4.8.0"
"@eslint-community/regexpp": "npm:^4.12.1"
@@ -2830,7 +2830,7 @@ __metadata:
"@eslint/config-helpers": "npm:^0.4.2"
"@eslint/core": "npm:^0.17.0"
"@eslint/eslintrc": "npm:^3.3.1"
- "@eslint/js": "npm:9.39.2"
+ "@eslint/js": "npm:9.39.3"
"@eslint/plugin-kit": "npm:^0.4.1"
"@humanfs/node": "npm:^0.16.6"
"@humanwhocodes/module-importer": "npm:^1.0.1"
@@ -2865,7 +2865,7 @@ __metadata:
optional: true
bin:
eslint: bin/eslint.js
- checksum: 10/53ff0e9c8264e7e8d40d50fdc0c0df0b701cfc5289beedfb686c214e3e7b199702f894bbd1bb48653727bb1ecbd1147cf5f555a4ae71e1daf35020cdc9072d9f
+ checksum: 10/1c95c92983ddf435e7f7d54edd06d703a15773a7d189583d3388e5b5ac714f0a2450b91c0b3bb9b9ccec9bd20994fd8e48d231ed6dabca0be56ef314b32820ff
languageName: node
linkType: hard
@@ -3103,11 +3103,11 @@ __metadata:
languageName: node
linkType: hard
-"framer-motion@npm:^12.34.3":
- version: 12.34.3
- resolution: "framer-motion@npm:12.34.3"
+"framer-motion@npm:^12.35.0":
+ version: 12.35.0
+ resolution: "framer-motion@npm:12.35.0"
dependencies:
- motion-dom: "npm:^12.34.3"
+ motion-dom: "npm:^12.35.0"
motion-utils: "npm:^12.29.2"
tslib: "npm:^2.4.0"
peerDependencies:
@@ -3121,7 +3121,7 @@ __metadata:
optional: true
react-dom:
optional: true
- checksum: 10/4565dc7f35c631c07ade3b77b19c14946ca37cc1125176e4b8c3a6b7d6994207867f9d9befcb2885d5bc8b6b4ea82ff8ee2cfa869f676cc28d18656acb33ff88
+ checksum: 10/9c2dd8a44efcf15d787ea1d1a24dbb2352b44824c4c33273f176f3feabe602278b9571541c89cc5673b3590b483daf9e0761889412feaafd4feba758cfdc1c96
languageName: node
linkType: hard
@@ -4500,12 +4500,12 @@ __metadata:
languageName: node
linkType: hard
-"motion-dom@npm:^12.34.3":
- version: 12.34.3
- resolution: "motion-dom@npm:12.34.3"
+"motion-dom@npm:^12.35.0":
+ version: 12.35.0
+ resolution: "motion-dom@npm:12.35.0"
dependencies:
motion-utils: "npm:^12.29.2"
- checksum: 10/17abb91f87020f00470f886cced6c6ebd58b9d5848c9bb12eb38f029dc7077344cf6ac2ccbe0adf1a8996191c17a98abfe91eaa99a1723909d7dd25a4f2b1101
+ checksum: 10/1a50cd2600d04dc8243c193af45b067aa65d853213f14aea15858a94fd3e901511ff258a91b4dffc1585eb43b61706a6f73fb98fb39dedd87e4b58a48ed8f593
languageName: node
linkType: hard
@@ -4517,10 +4517,10 @@ __metadata:
linkType: hard
"motion@npm:^12.4.1":
- version: 12.34.3
- resolution: "motion@npm:12.34.3"
+ version: 12.35.0
+ resolution: "motion@npm:12.35.0"
dependencies:
- framer-motion: "npm:^12.34.3"
+ framer-motion: "npm:^12.35.0"
tslib: "npm:^2.4.0"
peerDependencies:
"@emotion/is-prop-valid": "*"
@@ -4533,7 +4533,7 @@ __metadata:
optional: true
react-dom:
optional: true
- checksum: 10/1465fdee135e792f753a8ac5eb3ebdfb547165686f7a896ba947ecf2d02443f11ced9b3933aec773d4531758a9159dd24e48bd2e02c0d94754649645eac5121c
+ checksum: 10/ef7f4df7337147a0012ba2bfe3fd1f23d76081b4094ab94a7bc9f3f8338074e7a290873a9ea94427aea1aa9c63021804972f62d6c4289e011ddf5ef59865fa01
languageName: node
linkType: hard
diff --git a/docs/auth/auth0/provider.md b/docs/auth/auth0/provider.md
index b836bf01f6..1a560d4f62 100644
--- a/docs/auth/auth0/provider.md
+++ b/docs/auth/auth0/provider.md
@@ -5,13 +5,6 @@ sidebar_label: Auth0
description: Adding Auth0 as an authentication provider in Backstage
---
-:::info
-This documentation is written for [the new backend system](../../backend-system/index.md) which is the default since Backstage
-[version 1.24](../../releases/v1.24.0.md). If you are still on the old backend
-system, you may want to read [its own article](https://github.com/backstage/backstage/blob/v1.37.0/docs/auth/auth0/provider--old.md)
-instead, and [consider migrating](../../backend-system/building-backends/08-migrating.md)!
-:::
-
The Backstage `core-plugin-api` package comes with an Auth0 authentication
provider that can authenticate users using OAuth.
diff --git a/docs/auth/bitbucketServer/provider.md b/docs/auth/bitbucketServer/provider.md
index 89b8be3ff6..0beaa08f18 100644
--- a/docs/auth/bitbucketServer/provider.md
+++ b/docs/auth/bitbucketServer/provider.md
@@ -5,13 +5,6 @@ sidebar_label: Bitbucket Server
description: Adding Bitbucket Server OAuth as an authentication provider in Backstage
---
-:::info
-This documentation is written for [the new backend system](../../backend-system/index.md) which is the default since Backstage
-[version 1.24](../../releases/v1.24.0.md). If you are still on the old backend
-system, you may want to read [its own article](https://github.com/backstage/backstage/blob/v1.37.0/docs/auth/bitbucketServer/provider--old.md)
-instead, and [consider migrating](../../backend-system/building-backends/08-migrating.md)!
-:::
-
The Backstage `core-plugin-api` package comes with a Bitbucket Server authentication provider that can authenticate
users using Bitbucket Server. This does **NOT** work with Bitbucket Cloud.
diff --git a/docs/auth/guest/provider.md b/docs/auth/guest/provider.md
index 5072aabe50..f2ebfff8d6 100644
--- a/docs/auth/guest/provider.md
+++ b/docs/auth/guest/provider.md
@@ -19,10 +19,6 @@ This provider should only ever be enabled for `development`. To prevent unauthor
### Backend
-:::note
-This will only work with the new backend system. There is no support for this in the old backend.
-:::
-
Add the `@backstage/plugin-auth-backend-module-guest-provider` to your backend installation.
```sh title="From your Backstage root directory"
diff --git a/docs/auth/identity-resolver.md b/docs/auth/identity-resolver.md
index 0d4b50dcbe..26b48dec69 100644
--- a/docs/auth/identity-resolver.md
+++ b/docs/auth/identity-resolver.md
@@ -4,13 +4,6 @@ title: Sign-in Identities and Resolvers
description: An introduction to Backstage user identities and sign-in resolvers
---
-:::info
-This documentation is written for [the new backend system](../backend-system/index.md) which is the default since Backstage
-[version 1.24](../releases/v1.24.0.md). If you are still on the old backend
-system, you may want to read [its own article](https://github.com/backstage/backstage/blob/v1.37.0/docs/auth/identity-resolver--old.md)
-instead, and [consider migrating](../backend-system/building-backends/08-migrating.md)!
-:::
-
By default, every Backstage auth provider is configured only for the use-case of
access delegation. This enables Backstage to request resources and actions from
external systems on behalf of the user, for example re-triggering a build in CI.
diff --git a/docs/auth/index.md b/docs/auth/index.md
index fb85eb999b..389f824be3 100644
--- a/docs/auth/index.md
+++ b/docs/auth/index.md
@@ -12,7 +12,7 @@ access to external resources.
:::note Note
-Identity management and the Sign-In page in Backstage will only block external access when using the new backend system, without setting `backend.auth.dangerouslyDisableDefaultAuthPolicy` in configuration. Even so, the frontend bundle is not protected from external access, protecting it requires the use of the [experimental public entry point](https://backstage.io/docs/tutorials/enable-public-entry/). You can learn more about this in the [Threat Model](../overview/threat-model.md#operator-responsibilities).
+Identity management and the Sign-In page in Backstage will block external access by default, without setting `backend.auth.dangerouslyDisableDefaultAuthPolicy` in configuration. Even so, the frontend bundle is not protected from external access, protecting it requires the use of the [experimental public entry point](https://backstage.io/docs/tutorials/enable-public-entry/). You can learn more about this in the [Threat Model](../overview/threat-model.md#operator-responsibilities).
:::
@@ -461,7 +461,7 @@ providerFactories: {
},
```
-In the new backend system you can leverage the `authProvidersExtensionPoint` for this:
+You can leverage the `authProvidersExtensionPoint` for this:
```ts
// your-auth-plugin-module.ts
diff --git a/docs/auth/oidc.md b/docs/auth/oidc.md
index a55719e564..194eb08d05 100644
--- a/docs/auth/oidc.md
+++ b/docs/auth/oidc.md
@@ -4,13 +4,6 @@ title: OIDC provider from scratch
description: This section shows how to enable and use the Backstage OIDC provider.
---
-:::info
-This documentation is written for [the new backend system](../backend-system/index.md) which is the default since Backstage
-[version 1.24](../releases/v1.24.0.md). If you are still on the old backend
-system, you may want to read [its own article](https://github.com/backstage/backstage/blob/v1.37.0/docs/auth/oidc--old.md)
-instead, and [consider migrating](../backend-system/building-backends/08-migrating.md)!
-:::
-
This section shows how to enable and use the Backstage OIDC provider.
## Summary
diff --git a/docs/auth/service-to-service-auth.md b/docs/auth/service-to-service-auth.md
index 1423fa92f7..6655c76b29 100644
--- a/docs/auth/service-to-service-auth.md
+++ b/docs/auth/service-to-service-auth.md
@@ -4,13 +4,6 @@ title: Service to Service Auth
description: This section describes service to service authentication works, both internally within Backstage plugins and when external callers want to make requests.
---
-:::info
-This documentation is written for [the new backend system](../backend-system/index.md) which is the default since Backstage
-[version 1.24](../releases/v1.24.0.md). If you are still on the old backend
-system, you may want to read [its own article](https://github.com/backstage/backstage/blob/v1.37.0/docs/auth/service-to-service-auth--old.md)
-instead, and [consider migrating](../backend-system/building-backends/08-migrating.md)!
-:::
-
This article describes how _service-to-service auth_ works in Backstage, both
between Backstage backend plugins and for external callers who want to make
requests to them. This is in contrast to _user and user-to-service auth_ which
@@ -20,7 +13,7 @@ Each section describes one distinct type of auth flow.
## Standard Plugin-to-Plugin Auth
-Backstage plugins that use the new backend system and handle credentials using
+Backstage plugins that use the backend system and handle credentials using
the `auth` and `httpAuth` service APIs are secure by default, without requiring
any configuration. They generate self-signed tokens automatically for making
requests to other Backstage backend plugins, and the receivers use the caller's
@@ -228,96 +221,6 @@ calling Backstage plugins:
Authorization: Bearer eyJhbG...
```
-## Legacy Tokens
-
-Plugins and backends that are _not_ on the new backend system use a legacy token
-flow, where shared static secrets in your app-config are used for signing and
-verification. If you are on the new backend system and are not using legacy
-plugins using the compatibility wrapper, you can skip this section.
-
-### Configuration (legacy)
-
-In local development, there is no need to configure anything for this auth
-method. But in production, you must configure at least one legacy type external
-access method:
-
-```yaml title="in e.g. app-config.production.yaml"
-backend:
- auth:
- externalAccess:
- - type: legacy
- options:
- secret: my-secret-key-catalog
- subject: legacy-catalog
- - type: legacy
- options:
- secret: my-secret-key-scaffolder
- subject: legacy-scaffolder
-```
-
-The old style keys config is also supported as an alternative, but please
-consider using the new style above instead:
-
-```yaml title="in e.g. app-config.production.yaml"
-backend:
- auth:
- keys:
- - secret: my-secret-key-catalog
- - secret: my-secret-key-scaffolder
-```
-
-The secrets must be any base64-encoded random data, but for security reasons
-should be sufficiently long so as not to be easy to guess by brute force. You
-can for example generate them on the command line:
-
-```shell
-node -p 'require("crypto").randomBytes(24).toString("base64")'
-```
-
-The subjects must be strings without whitespace. They are used for identifying
-each caller, and become part of the credentials object that request recipient
-plugins get.
-
-In both of the examples we showed two secrets being specified, but the minimum
-is one. The order is significant: the first one is always used for signing of
-outgoing requests to other backend plugins, while all of the keys are used for
-verification. This is useful if you want to be able to have unique keys per
-deployment if you are using split deployments of Backstage. Then each deployment
-lists its own signing secret at the top, and only adds the secrets for those
-other deployments that it wants to permit to call it.
-
-For most organizations, we recommend leaving it at just one key and
-[migrating](../backend-system/building-backends/08-migrating.md) to the new
-backend system as soon as possible instead of experimenting with multiple legacy
-secrets.
-
-### External Callers (legacy)
-
-For legacy Backstage backend plugins, the above configuration is enough. But
-external callers who wish to make requests using this flow must generate tokens
-according to the following rules.
-
-The token must be a JWT with a `HS256` signature, using the raw base64 decoded
-value of the configured key as the secret. It must also have the following
-payload:
-
-- `sub`: the exact string "backstage-server"
-- `exp`: one hour from the time it was generated, in epoch seconds
-
-:::note Note
-
-The JWT must encode the `alg` header as a protected header, such as with
-[setProtectedHeader](https://github.com/panva/jose/blob/main/docs/classes/jwt_sign.SignJWT.md#setprotectedheader).
-
-:::
-
-The caller then passes along the JWT token with requests in the `Authorization`
-header:
-
-```yaml
-Authorization: Bearer eZv5o+fW3KnR3kVabMW4ZcDNLPl8nmMW
-```
-
## Access Restrictions
Each `externalAccess` entry may optionally have an `accessRestrictions` key,
diff --git a/docs/backend-system/architecture/01-index.md b/docs/backend-system/architecture/01-index.md
index 293a46b7ca..6e1012dce0 100644
--- a/docs/backend-system/architecture/01-index.md
+++ b/docs/backend-system/architecture/01-index.md
@@ -2,12 +2,12 @@
id: index
title: Backend System Architecture
sidebar_label: Overview
-description: The structure and architecture of the new Backend System and its component parts
+description: The structure and architecture of the Backend System and its component parts
---
## Building Blocks
-This section introduces the high-level building blocks upon which this new
+This section introduces the high-level building blocks upon which this
system is built. These are all concepts that exist in our current system in one
way or another, but they have all been lifted up to be first class concerns in
the new system. Regardless of whether you are setting up your own backstage
diff --git a/docs/backend-system/building-backends/01-index.md b/docs/backend-system/building-backends/01-index.md
index a38c1d44e5..3fb9ea60a9 100644
--- a/docs/backend-system/building-backends/01-index.md
+++ b/docs/backend-system/building-backends/01-index.md
@@ -2,7 +2,7 @@
id: index
title: Building Backends
sidebar_label: Overview
-description: Building backends using the new backend system
+description: Building backends using the backend system
---
:::note Note
diff --git a/docs/backend-system/building-plugins-and-modules/01-index.md b/docs/backend-system/building-plugins-and-modules/01-index.md
index 53bf4af8ef..3b0696aa8e 100644
--- a/docs/backend-system/building-plugins-and-modules/01-index.md
+++ b/docs/backend-system/building-plugins-and-modules/01-index.md
@@ -2,16 +2,9 @@
id: index
title: Building Backend Plugins and Modules
sidebar_label: Overview
-description: Building backend plugins and modules using the new backend system
+description: Building backend plugins and modules using the backend system
---
-:::note Note
-
-If you have an existing backend and/or backend plugins that are not yet
-using the new backend system, see [migrating](./08-migrating.md).
-
-:::
-
This section covers how to build your own backend [plugins](../architecture/04-plugins.md) and
[modules](../architecture/06-modules.md). They are sometimes collectively referred to as
backend _features_, and are the building blocks that adopters add to their
diff --git a/docs/backend-system/core-services/auditor.md b/docs/backend-system/core-services/auditor.md
index fe4ecd196c..2d0864eeca 100644
--- a/docs/backend-system/core-services/auditor.md
+++ b/docs/backend-system/core-services/auditor.md
@@ -146,8 +146,8 @@ To clarify how to utilize the Auditor feature effectively, we recommend explorin
- **Code Implementation Example (createRouter.ts):**
- The [`createRouter.ts`](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend/src/service/createRouter.ts) file within the Catalog Backend showcases a practical integration of the `AuditorService` within a Backstage backend plugin.
- Specifically, the lines that demonstrate the creation of an audit event. This includes setting critical parameters such as `eventId` and `severityLevel`, as well as incorporating relevant metadata like `queryType` and `entityRef`.
-- **Documentation Example (README.md):**
- - The "Audit Events" section of the Catalog Backend's [`README.md`](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend/README.md#audit-events) provides a well-structured example of documenting emitted audit events.
+- **Documentation Example:**
+ - The "Audit Events" section of the Software Catalog [Audit Documentation](../../features/software-catalog/audit-events.md) provides a well-structured example of documenting emitted audit events.
- It illustrates how to detail various `eventId` values and their corresponding `meta` fields (e.g., `queryType`, `actionType`) for different plugin operations.
These examples provide both a code-level demonstration and a documentation guideline for effectively utilizing the `AuditorService` to manage audit events within your Backstage plugins.
diff --git a/docs/features/kubernetes/authenticationstrategy.md b/docs/features/kubernetes/authenticationstrategy.md
index e39201aaeb..5c20965bde 100644
--- a/docs/features/kubernetes/authenticationstrategy.md
+++ b/docs/features/kubernetes/authenticationstrategy.md
@@ -157,7 +157,7 @@ export class AwsIamStrategy implements AuthenticationStrategy {
Sometimes you need to add a new way to authenticate against a kubernetes cluster not support by default by Backstage. This is how integrators can bring their own kubernetes auth strategies through the use of the [`addAuthStrategy`](https://github.com/backstage/backstage/blob/57397e7d6d2d725712c439f4ab93f2ac6aa27bf8/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts#L211) method on `KubernetesBuilder` or through the [AuthStrategyExtensionPoint](https://github.com/backstage/backstage/blob/57397e7d6d2d725712c439f4ab93f2ac6aa27bf8/plugins/kubernetes-backend/src/plugin.ts#L112). So, on the following sections, we are going to introduce a new AuthStrategy for [Pinniped][1], an authentication service for Kubernetes clusters.
-### Custom Pinniped auth strategy in the new backend system
+### Custom Pinniped auth strategy in the backend system
To add a new AuthStrategy, we need to create a new Pinniped [backend module](../../backend-system/building-plugins-and-modules/01-index.md#modules) to extend the Kubernetes-Backend plugin. The Pinniped module will interact with the Kubernetes-Backend plugin through the [extension points](../../backend-system/architecture/05-extension-points.md) registered by the plugin. The Kubernetes-Backend plugin [registers](https://github.com/backstage/backstage/blob/ebe7afad9d19f279469168ca0d4feceb92c1ad36/plugins/kubernetes-backend/src/plugin.ts#L155) multiple extension points like `kubernetesObjectsProvider`, `kubernetesClusterSupplier`, `kubernetesFetcher`, `kubernetesServiceLocator` and the `kubernetesAuthStrategy`.
diff --git a/docs/features/software-catalog/configuration.md b/docs/features/software-catalog/configuration.md
index 3ed027a0a4..8c9241eb36 100644
--- a/docs/features/software-catalog/configuration.md
+++ b/docs/features/software-catalog/configuration.md
@@ -366,3 +366,39 @@ Now install your module.
```ts title="packages/backend/src/index.ts"
backend.add(eventsModuleCatalogErrors);
```
+
+## OpenAPI and AsyncAPI Placeholder Support
+
+The **OpenAPI Catalog Backend Module** registers a JSON Schema placeholder resolver for the `openapi` (and `asyncapi`) placeholder keys. This enables you to use `$openapi` and `$asyncapi` references in your catalog entities, while having all underlying `$ref` pointers resolved and bundled as part of the schema processing.
+
+### Installation
+
+1. Add the package to your backend:
+
+```bash title="From your Backstage root directory"
+yarn --cwd packages/backend add @backstage/plugin-catalog-backend-module-openapi
+```
+
+2. Register the module in your backend:
+
+```ts title="packages/backend/src/index.ts"
+backend.add(import('@backstage/plugin-catalog-backend-module-openapi'));
+```
+
+### Usage
+
+To trigger the `$ref` resolution, use the `$openapi` (or `$asyncapi`) placeholder in your catalog entity definition:
+
+```yaml
+apiVersion: backstage.io/v1alpha1
+kind: API
+metadata:
+ name: example
+ description: Example API
+spec:
+ type: openapi
+ lifecycle: production
+ owner: team
+ definition:
+ $openapi: ./spec/openapi.yaml # by using $openapi Backstage will now resolve all $ref instances
+```
diff --git a/docs/features/software-templates/authorizing-scaffolder-template-details.md b/docs/features/software-templates/authorizing-scaffolder-template-details.md
index 7ff2cd9377..e35d81d260 100644
--- a/docs/features/software-templates/authorizing-scaffolder-template-details.md
+++ b/docs/features/software-templates/authorizing-scaffolder-template-details.md
@@ -6,7 +6,13 @@ description: How to authorize parts of a template and authorize scaffolder task
The scaffolder plugin integrates with the Backstage [permission framework](../../permissions/overview.md), which allows you to control access to certain parameters and steps in your templates based on the user executing the template. It also allows you to control access to scaffolder tasks.
-### Authorizing parameters and steps
+:::tip
+
+To better understand the following examples make sure to review the [Writing a permission policy](../../permissions/writing-a-policy.md)) documentation before moving forward.
+
+:::
+
+## Authorizing parameters and steps
To mark specific parameters or steps as requiring permission, add the `backstage:permissions` property to the parameter or step with one or more tags. For example:
@@ -288,62 +294,3 @@ All other users are granted permissions to perform/access the following actions/
- Read scaffolder tasks and their associated events/logs for tasks created by the user.
Although the rules exported by the scaffolder are simple, combining them can help you achieve more complex use cases.
-
-### Authorizing in the New Backend System
-
-Instead of the changes in `permission.ts` noted in the above example you will make them in your `index.ts`. You will need to create a module where your permission policy will get added. Here is a very simplified example of how to do that:
-
-```ts title="packages/backend/src/index.ts"
-import { createBackendModule } from '@backstage/backend-plugin-api';
-import {
- PolicyDecision,
- AuthorizeResult,
-} from '@backstage/plugin-permission-common';
-import {
- PermissionPolicy,
- PolicyQuery,
- PolicyQueryUser,
-} from '@backstage/plugin-permission-node';
-import { policyExtensionPoint } from '@backstage/plugin-permission-node/alpha';
-
-class ExamplePermissionPolicy implements PermissionPolicy {
- async handle(
- request: PolicyQuery,
- user?: PolicyQueryUser,
- ): Promise {
- // Various scaffolder permission checks ...
-
- return {
- result: AuthorizeResult.ALLOW,
- };
- }
-}
-
-const customPermissionBackendModule = createBackendModule({
- pluginId: 'permission',
- moduleId: 'allow-all-policy',
- register(reg) {
- reg.registerInit({
- deps: { policy: policyExtensionPoint },
- async init({ policy }) {
- policy.setPolicy(new ExamplePermissionPolicy());
- },
- });
- },
-});
-
-const backend = createBackend();
-
-// Other plugins...
-
-/* highlight-add-start */
-backend.add(import('@backstage/plugin-permission-backend'));
-backend.add(customPermissionBackendModule);
-/* highlight-add-end */
-```
-
-:::note Note
-
-The `ExamplePermissionPolicy` here could be the one from the [Authorizing parameters and steps](#authorizing-parameters-and-steps) example or from the [Authorizing actions](#authorizing-actions) example. It would work the same way for both of them.
-
-:::
diff --git a/docs/features/software-templates/builtin-actions.md b/docs/features/software-templates/builtin-actions.md
index 22d8ef6454..378c15e18f 100644
--- a/docs/features/software-templates/builtin-actions.md
+++ b/docs/features/software-templates/builtin-actions.md
@@ -32,7 +32,7 @@ Here's how to add an action module, first you need to run this command:
yarn --cwd packages/backend add @backstage/plugin-scaffolder-backend-module-github
```
-Then you need to add it to your backend, this is a simplified new backend system for example purposes:
+Then you need to add it to your backend, this is a simplified backend system for example purposes:
```ts title="/packages/backend/src/index.ts"
import { createBackend } from '@backstage/backend-defaults';
diff --git a/docs/features/software-templates/writing-templates.md b/docs/features/software-templates/writing-templates.md
index 5d9fcba603..64c1acc67d 100644
--- a/docs/features/software-templates/writing-templates.md
+++ b/docs/features/software-templates/writing-templates.md
@@ -325,6 +325,57 @@ spec:
token: ${{ each.value.token }}
```
+### Defining a Secrets Schema
+
+You can define a JSON Schema for secrets that will be validated when a task is created. This is useful when secrets are passed programmatically (e.g., via CI/CD pipelines or API calls) rather than through the UI form. The schema ensures that required secrets are provided before task execution begins.
+
+```yaml
+apiVersion: scaffolder.backstage.io/v1beta3
+kind: Template
+metadata:
+ name: publish-to-npm
+ title: Publish to NPM
+spec:
+ owner: backstage/techdocs-core
+ type: service
+
+ # Define required secrets with a JSON Schema
+ secrets:
+ schema:
+ required:
+ - NPM_TOKEN
+ properties:
+ NPM_TOKEN:
+ type: string
+ description: NPM authentication token for publishing
+
+ parameters:
+ - title: Package Details
+ properties:
+ packageName:
+ type: string
+ title: Package Name
+
+ steps:
+ - id: publish
+ action: npm:publish
+ input:
+ packageName: ${{ parameters.packageName }}
+ token: ${{ secrets.NPM_TOKEN }}
+```
+
+When a task is created without the required secrets, the API returns a `400` error with a descriptive message:
+
+```json
+{
+ "errors": [
+ {
+ "message": "secrets.NPM_TOKEN is required"
+ }
+ ]
+}
+```
+
### Custom step layouts
If you find that the default layout of the form used in a particular step does not meet your needs then you can supply your own [custom step layout](./writing-custom-step-layouts.md).
diff --git a/docs/features/techdocs/addons--new.md b/docs/features/techdocs/addons--new.md
index cbafcbe127..af7f4d2893 100644
--- a/docs/features/techdocs/addons--new.md
+++ b/docs/features/techdocs/addons--new.md
@@ -93,7 +93,7 @@ discover available Addons, we've compiled a list of them here:
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`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.techDocsReportIssueAddonModule.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. |
+| [`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`). |
Got an Addon to contribute? Feel free to add a row above!
diff --git a/docs/features/techdocs/getting-started.md b/docs/features/techdocs/getting-started.md
index 1246600683..76c231ff0e 100644
--- a/docs/features/techdocs/getting-started.md
+++ b/docs/features/techdocs/getting-started.md
@@ -95,9 +95,6 @@ That's it! Now, we need the TechDocs Backend plugin for the frontend to work.
## Adding TechDocs Backend plugin
-:::note
-These instructions are for the new backend system. For setting this up in the old backend system, see [here](https://github.com/backstage/backstage/blob/v1.36.1/docs/features/techdocs/getting-started.md)
-:::
First we need to install the `@backstage/plugin-techdocs-backend` package.
```bash title="From your Backstage root directory"
diff --git a/docs/features/techdocs/how-to-guides.md b/docs/features/techdocs/how-to-guides.md
index 755d88b163..33faf44841 100644
--- a/docs/features/techdocs/how-to-guides.md
+++ b/docs/features/techdocs/how-to-guides.md
@@ -852,9 +852,9 @@ and publish the documentation for them. If the value of the `company.com/techdoc
annotation is anything other than `'local'`, the user is responsible for publishing
documentation to the appropriate location in the TechDocs external storage.
-### Hybrid build strategy using the New Backend System
+### Hybrid build strategy using the Backend System
-To setup a hybrid build strategy using the New Backend System you'll follow the same steps as above but for Step 4 you will need to do the following:
+To setup a hybrid build strategy using the Backend System you'll follow the same steps as above but for Step 4 you will need to do the following:
```ts title="packages/backend/src/index.ts"
const backend = createBackend();
diff --git a/docs/integrations/aws-s3/discovery.md b/docs/integrations/aws-s3/discovery.md
index fcba5ca04f..74e2fde6a5 100644
--- a/docs/integrations/aws-s3/discovery.md
+++ b/docs/integrations/aws-s3/discovery.md
@@ -5,10 +5,6 @@ sidebar_label: Discovery
description: Automatically discovering catalog entities from an AWS S3 Bucket
---
-:::info
-This documentation is written for [the new backend system](../../backend-system/index.md) which is the default since Backstage [version 1.24](../../releases/v1.24.0.md). If you are still on the old backend system, you may want to read [its own article](https://github.com/backstage/backstage/blob/v1.37.0/docs/integrations/aws-s3/discovery--old.md) instead, and [consider migrating](../../backend-system/building-backends/08-migrating.md)!
-:::
-
The AWS S3 integration has a special entity provider for discovering catalog
entities located in an S3 Bucket. If you have a bucket that contains multiple
catalog files, and you want to automatically discover them, you can use this
diff --git a/docs/integrations/azure-blobStorage/discovery.md b/docs/integrations/azure-blobStorage/discovery.md
index bed97441f9..f0953815c2 100644
--- a/docs/integrations/azure-blobStorage/discovery.md
+++ b/docs/integrations/azure-blobStorage/discovery.md
@@ -5,10 +5,6 @@ sidebar_label: Discovery
description: Automatically discovering catalog entities from an Azure Blob Storage account
---
-:::info
-This documentation is written for [the new backend system](../../backend-system/index.md) which is the default since Backstage [version 1.24](../../releases/v1.24.0.md).
-:::
-
The Azure Blob Storage account integration has a special entity provider for discovering catalog
entities located in a storage account container. If you have a container that contains multiple
catalog files, and you want to automatically discover them, you can use this
diff --git a/docs/integrations/azure/discovery.md b/docs/integrations/azure/discovery.md
index 7e4d376a7d..0eafc938a2 100644
--- a/docs/integrations/azure/discovery.md
+++ b/docs/integrations/azure/discovery.md
@@ -5,10 +5,6 @@ sidebar_label: Discovery
description: Automatically discovering catalog entities from repositories in an Azure DevOps organization
---
-:::info
-This documentation is written for [the new backend system](../../backend-system/index.md) which is the default since Backstage [version 1.24](../../releases/v1.24.0.md). If you are still on the old backend system, you may want to read [its own article](https://github.com/backstage/backstage/blob/v1.37.0/docs/integrations/azure/discovery--old.md) instead, and [consider migrating](../../backend-system/building-backends/08-migrating.md)!
-:::
-
The Azure DevOps integration has a special entity provider for discovering catalog entities within an Azure DevOps. The provider will crawl your Azure DevOps organization and register entities matching the configured path. This can be useful as an alternative to static locations or manually adding things to the catalog.
This guide explains how to install and configure the Azure DevOps Entity Provider (recommended) or the Azure DevOps Processor.
diff --git a/docs/integrations/azure/org.md b/docs/integrations/azure/org.md
index efcd8ae612..92f3f9c12a 100644
--- a/docs/integrations/azure/org.md
+++ b/docs/integrations/azure/org.md
@@ -5,10 +5,6 @@ sidebar_label: Org Data
description: Importing users and groups from Microsoft Entra ID into Backstage
---
-:::info
-This documentation is written for [the new backend system](../../backend-system/index.md) which is the default since Backstage [version 1.24](../../releases/v1.24.0.md). If you are still on the old backend system, you may want to read [its own article](https://github.com/backstage/backstage/blob/v1.37.0/docs/integrations/azure/org--old.md) instead, and [consider migrating](../../backend-system/building-backends/08-migrating.md)!
-:::
-
The Backstage catalog can be set up to ingest organizational data - users and
teams - directly from a tenant in Microsoft Entra ID via the
Microsoft Graph API.
diff --git a/docs/integrations/bitbucketCloud/discovery.md b/docs/integrations/bitbucketCloud/discovery.md
index 3f5920be5d..21b896e072 100644
--- a/docs/integrations/bitbucketCloud/discovery.md
+++ b/docs/integrations/bitbucketCloud/discovery.md
@@ -39,9 +39,9 @@ package.
yarn --cwd packages/backend add @backstage/plugin-catalog-backend-module-bitbucket-cloud
```
-### Installation with New Backend System
+Then add the following to your backend:
-```ts
+```ts title="packages/backend/src/index.ts"
// optional if you want HTTP endpoints to receive external events
// backend.add(import('@backstage/plugin-events-backend'));
// optional if you want to use AWS SQS instead of HTTP endpoints to receive external events
@@ -63,59 +63,6 @@ Further documentation:
-
-
-### Installation with Legacy Backend System
-
-Please follow the installation instructions at
-
--
--
-
-Additionally, you need to decide how you want to receive events from external sources like
-
-- [via HTTP endpoint](https://github.com/backstage/backstage/tree/master/plugins/events-backend/README.md)
-- [via an AWS SQS queue](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-aws-sqs/README.md)
-- [via Google Pub/Sub](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-google-pubsub/README.md)
-- [via a Kafka topic](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-kafka/README.md)
-
-Set up your provider
-
-```ts title="packages/backend/src/plugins/catalog.ts"
-import { CatalogBuilder } from '@backstage/plugin-catalog-backend';
-/* highlight-add-start */
-import { BitbucketCloudEntityProvider } from '@backstage/plugin-catalog-backend-module-bitbucket-cloud';
-/* highlight-add-end */
-
-import { ScaffolderEntitiesProcessor } from '@backstage/plugin-scaffolder-backend';
-import { Router } from 'express';
-import { PluginEnvironment } from '../types';
-
-export default async function createPlugin(
- env: PluginEnvironment,
-): Promise {
- const builder = await CatalogBuilder.create(env);
- /* highlight-add-start */
- const bitbucketCloudProvider = BitbucketCloudEntityProvider.fromConfig(
- env.config,
- {
- auth: env.auth,
- catalogApi: new CatalogClient({ discoveryApi: env.discovery }),
- events: env.events,
- logger: env.logger,
- scheduler: env.scheduler,
- },
- );
- builder.addEntityProvider(bitbucketCloudProvider);
- /* highlight-add-end */
- const { processingEngine, router } = await builder.build();
- await processingEngine.start();
- return router;
-}
-```
-
-**Attention:**
-`catalogApi` and `tokenManager` are required at this variant
-compared to the one without events support.
-
## Configuration
To use the entity provider, you'll need a [Bitbucket Cloud integration set up](locations.md).
diff --git a/docs/integrations/bitbucketServer/discovery.md b/docs/integrations/bitbucketServer/discovery.md
index bbdd105af4..ee96118f2a 100644
--- a/docs/integrations/bitbucketServer/discovery.md
+++ b/docs/integrations/bitbucketServer/discovery.md
@@ -5,10 +5,6 @@ sidebar_label: Discovery
description: Automatically discovering catalog entities from repositories in Bitbucket Server
---
-:::info
-This documentation is written for [the new backend system](../../backend-system/index.md) which is the default since Backstage [version 1.24](../../releases/v1.24.0.md). If you are still on the old backend system, you may want to read [its own article](https://github.com/backstage/backstage/blob/v1.37.0/docs/integrations/bitbucketServer/discovery--old.md) instead, and [consider migrating](../../backend-system/building-backends/08-migrating.md)!
-:::
-
The Bitbucket Server integration has a special entity provider for discovering
catalog files located in Bitbucket Server.
The provider will search your Bitbucket Server account and register catalog files matching the configured path
@@ -25,9 +21,9 @@ dependency to `@backstage/plugin-catalog-backend-module-bitbucket-server` to you
yarn --cwd packages/backend add @backstage/plugin-catalog-backend-module-bitbucket-server
```
-### Installation with New Backend System
+Then add the following to your backend:
-```ts
+```ts title="packages/backend/src/index.ts"
// optional if you want HTTP endpojnts to receive external events
// backend.add(import('@backstage/plugin-events-backend'));
// optional if you want to use AWS SQS instead of HTTP endpoints to receive external events
diff --git a/docs/integrations/gerrit/discovery.md b/docs/integrations/gerrit/discovery.md
index 06fb144e50..a9ea80e088 100644
--- a/docs/integrations/gerrit/discovery.md
+++ b/docs/integrations/gerrit/discovery.md
@@ -5,10 +5,6 @@ sidebar_label: Discovery
description: Automatically discovering catalog entities from Gerrit repositories
---
-:::info
-This documentation is written for [the new backend system](../../backend-system/index.md) which is the default since Backstage [version 1.24](../../releases/v1.24.0.md). If you are still on the old backend system, you may want to read [its own article](https://github.com/backstage/backstage/blob/v1.37.0/docs/integrations/gerrit/discovery--old.md) instead, and [consider migrating](../../backend-system/building-backends/08-migrating.md)!
-:::
-
The Gerrit integration has a special entity provider for discovering catalog entities
from Gerrit repositories. The provider uses the "List Projects" API in Gerrit to get
a list of repositories and will automatically ingest all `catalog-info.yaml` files
diff --git a/docs/integrations/github/discovery.md b/docs/integrations/github/discovery.md
index 66fdaa503b..c4dbc2e10b 100644
--- a/docs/integrations/github/discovery.md
+++ b/docs/integrations/github/discovery.md
@@ -5,10 +5,6 @@ sidebar_label: Discovery
description: Automatically discovering catalog entities from repositories in a GitHub organization or App
---
-:::info
-This documentation is written for [the new backend system](../../backend-system/index.md) which is the default since Backstage [version 1.24](../../releases/v1.24.0.md). If you are still on the old backend system, you may want to read [its own article](https://github.com/backstage/backstage/blob/v1.37.0/docs/integrations/github/discovery--old.md) instead, and [consider migrating](../../backend-system/building-backends/08-migrating.md)!
-:::
-
## GitHub Provider
The GitHub integration has a discovery provider for discovering catalog
diff --git a/docs/integrations/github/org.md b/docs/integrations/github/org.md
index 5321423432..1d5eac1581 100644
--- a/docs/integrations/github/org.md
+++ b/docs/integrations/github/org.md
@@ -5,10 +5,6 @@ sidebar_label: Org Data
description: Importing users and groups from a GitHub organization into Backstage
---
-:::info
-This documentation is written for [the new backend system](../../backend-system/index.md) which is the default since Backstage [version 1.24](../../releases/v1.24.0.md). If you are still on the old backend system, you may want to read [its own article](https://github.com/backstage/backstage/blob/v1.37.0/docs/integrations/github/org--old.md) instead, and [consider migrating](../../backend-system/building-backends/08-migrating.md)!
-:::
-
The Backstage catalog can be set up to ingest organizational data - users and
teams - directly from an organization in GitHub or GitHub Enterprise. The result
is a hierarchy of
diff --git a/docs/integrations/gitlab/discovery.md b/docs/integrations/gitlab/discovery.md
index 4d801bdd77..315cc9a4a7 100644
--- a/docs/integrations/gitlab/discovery.md
+++ b/docs/integrations/gitlab/discovery.md
@@ -23,8 +23,6 @@ the gitlab catalog plugin:
yarn --cwd packages/backend add @backstage/plugin-catalog-backend-module-gitlab
```
-### Installation with New Backend System
-
Then add the following to your backend initialization:
```ts title="packages/backend/src/index.ts"
@@ -51,87 +49,6 @@ Further documentation:
- [Events Plugin](https://github.com/backstage/backstage/tree/master/plugins/events-backend/README.md)
- [GitLab Module for the Events Plugin](https://github.com/backstage/backstage/blob/master/plugins/events-backend-module-gitlab/README.md)
-### Installation with Legacy Backend System (skip if you are using Backstage v1.31.0 or later)
-
-#### Installation without Events Support
-
-Add the segment below to `packages/backend/src/plugins/catalog.ts`:
-
-```ts title="packages/backend/src/plugins/catalog.ts"
-/* highlight-add-next-line */
-import { GitlabDiscoveryEntityProvider } from '@backstage/plugin-catalog-backend-module-gitlab';
-
-export default async function createPlugin(
- env: PluginEnvironment,
-): Promise {
- const builder = await CatalogBuilder.create(env);
- /* highlight-add-start */
- builder.addEntityProvider(
- ...GitlabDiscoveryEntityProvider.fromConfig(env.config, {
- logger: env.logger,
- // optional: alternatively, use scheduler with schedule defined in app-config.yaml
- schedule: env.scheduler.createScheduledTaskRunner({
- frequency: { minutes: 30 },
- timeout: { minutes: 3 },
- }),
- // optional: alternatively, use schedule
- scheduler: env.scheduler,
- }),
- );
- /* highlight-add-end */
- // ..
-}
-```
-
-#### Installation with Events Support
-
-Please follow the installation instructions at
-
-- [Events Plugin](https://github.com/backstage/backstage/tree/master/plugins/events-backend/README.md)
-- [GitLab Module for the Events Plugin](https://github.com/backstage/backstage/blob/master/plugins/events-backend-module-gitlab/README.md)
-
-Additionally, you need to decide how you want to receive events from external sources like
-
-- [via HTTP endpoint](https://github.com/backstage/backstage/tree/master/plugins/events-backend/README.md)
-- [via an AWS SQS queue](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-aws-sqs/README.md)
-- [via Google Pub/Sub](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-google-pubsub/README.md)
-- [via a Kafka topic](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-kafka/README.md)
-
-Set up your provider
-
-```ts title="packages/backend/src/plugins/catalog.ts"
-import { CatalogBuilder } from '@backstage/plugin-catalog-backend';
-/* highlight-add-next-line */
-import { GitlabDiscoveryEntityProvider } from '@backstage/plugin-catalog-backend-module-gitlab';
-import { ScaffolderEntitiesProcessor } from '@backstage/plugin-scaffolder-backend';
-import { Router } from 'express';
-import { PluginEnvironment } from '../types';
-
-export default async function createPlugin(
- env: PluginEnvironment,
-): Promise {
- const builder = await CatalogBuilder.create(env);
- builder.addProcessor(new ScaffolderEntitiesProcessor());
- /* highlight-add-start */
- const gitlabProvider = GitlabDiscoveryEntityProvider.fromConfig(env.config, {
- logger: env.logger,
- // optional: alternatively, use scheduler with schedule defined in app-config.yaml
- schedule: env.scheduler.createScheduledTaskRunner({
- frequency: { minutes: 30 },
- timeout: { minutes: 3 },
- }),
- // optional: alternatively, use schedule
- scheduler: env.scheduler,
- events: env.events,
- });
- builder.addEntityProvider(gitlabProvider);
- /* highlight-add-end */
- const { processingEngine, router } = await builder.build();
- await processingEngine.start();
- return router;
-}
-```
-
## Configuration
To use the discovery provider, you'll need a GitLab integration
@@ -140,7 +57,7 @@ to the catalog configuration.
:::note Note
-If you are using the New Backend System, the `schedule` has to be setup in the config, as shown below.
+The `schedule` has to be setup in the config, as shown below.
:::
diff --git a/docs/integrations/gitlab/org.md b/docs/integrations/gitlab/org.md
index bddd1c13a1..6c5641924d 100644
--- a/docs/integrations/gitlab/org.md
+++ b/docs/integrations/gitlab/org.md
@@ -29,8 +29,6 @@ As this provider is not one of the default providers, you will first need to ins
yarn --cwd packages/backend add @backstage/plugin-catalog-backend-module-gitlab @backstage/plugin-catalog-backend-module-gitlab-org
```
-### Installation with New Backend System
-
Then add the following to your backend initialization:
```ts title="packages/backend/src/index.ts
@@ -58,92 +56,6 @@ Further documentation:
- [Events Plugin](https://github.com/backstage/backstage/tree/master/plugins/events-backend/README.md)
- [GitLab Module for the Events Plugin](https://github.com/backstage/backstage/blob/master/plugins/events-backend-module-gitlab/README.md)
-### Installation with Legacy Backend System
-
-#### Installation without Events Support
-
-Add the plugin to the plugin catalog `packages/backend/src/plugins/catalog.ts`:
-
-```ts
-/* packages/backend/src/plugins/catalog.ts */
-/* highlight-add-next-line */
-import { GitlabOrgDiscoveryEntityProvider } from '@backstage/plugin-catalog-backend-module-gitlab';
-
-export default async function createPlugin(
- env: PluginEnvironment,
-): Promise {
- const builder = await CatalogBuilder.create(env);
- /** ... other processors and/or providers ... */
- /* highlight-add-start */
- builder.addEntityProvider(
- ...GitlabOrgDiscoveryEntityProvider.fromConfig(env.config, {
- logger: env.logger,
- // optional: alternatively, use scheduler with schedule defined in app-config.yaml
- schedule: env.scheduler.createScheduledTaskRunner({
- frequency: { minutes: 30 },
- timeout: { minutes: 3 },
- }),
- // optional: alternatively, use schedule
- scheduler: env.scheduler,
- }),
- );
- /* highlight-add-end */
- // ..
-}
-```
-
-#### Installation with Events Support
-
-Please follow the installation instructions at
-
-- [Events Plugin](https://github.com/backstage/backstage/tree/master/plugins/events-backend/README.md)
-- [GitLab Module for the Events Plugin](https://github.com/backstage/backstage/blob/master/plugins/events-backend-module-gitlab/README.md)
-
-Additionally, you need to decide how you want to receive events from external sources like
-
-- [via HTTP endpoint](https://github.com/backstage/backstage/tree/master/plugins/events-backend/README.md)
-- [via an AWS SQS queue](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-aws-sqs/README.md)
-- [via Google Pub/Sub](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-google-pubsub/README.md)
-- [via a Kafka topic](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-kafka/README.md)
-
-Set up your provider
-
-```ts title="packages/backend/src/plugins/catalog.ts"
-import { CatalogBuilder } from '@backstage/plugin-catalog-backend';
-/* highlight-add-next-line */
-import { GitlabOrgDiscoveryEntityProvider } from '@backstage/plugin-catalog-backend-module-gitlab';
-import { ScaffolderEntitiesProcessor } from '@backstage/plugin-scaffolder-backend';
-import { Router } from 'express';
-import { PluginEnvironment } from '../types';
-
-export default async function createPlugin(
- env: PluginEnvironment,
-): Promise {
- const builder = await CatalogBuilder.create(env);
- builder.addProcessor(new ScaffolderEntitiesProcessor());
- /* highlight-add-start */
- const gitlabOrgProvider = GitlabOrgDiscoveryEntityProvider.fromConfig(
- env.config,
- {
- logger: env.logger,
- // optional: alternatively, use scheduler with schedule defined in app-config.yaml
- schedule: env.scheduler.createScheduledTaskRunner({
- frequency: { minutes: 30 },
- timeout: { minutes: 3 },
- }),
- // optional: alternatively, use schedule
- scheduler: env.scheduler,
- events: env.events,
- },
- );
- builder.addEntityProvider(gitlabOrgProvider);
- /* highlight-add-end */
- const { processingEngine, router } = await builder.build();
- await processingEngine.start();
- return router;
-}
-```
-
## Configuration
To use the entity provider, you'll need a [Gitlab integration set up](https://backstage.io/docs/integrations/gitlab/locations).
@@ -163,7 +75,7 @@ will be those visible to the account which provisioned the token.
:::note Note
-If you are using the New Backend System, the `schedule` has to be setup in the config, as shown below.
+The `schedule` has to be setup in the config, as shown below.
:::
diff --git a/docs/overview/threat-model.md b/docs/overview/threat-model.md
index 6acba915d5..60f22a374c 100644
--- a/docs/overview/threat-model.md
+++ b/docs/overview/threat-model.md
@@ -25,7 +25,7 @@ An **external user** is a user that does not belong to the other three groups, f
:::info
This section assumes that you are using the
-[new backend system](../backend-system/index.md) and at least Backstage release [version 1.24](../releases/v1.24.0.md). Before that Backstage did not come with built-in protection against unauthorized access and you were required to deploy it in a protected environment.
+[backend system](../backend-system/index.md) and at least Backstage release [version 1.24](../releases/v1.24.0.md). Before that Backstage did not come with built-in protection against unauthorized access and you were required to deploy it in a protected environment.
:::
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 AWSâs ALB, GCPâs IAP, or Cloudflare Access.
diff --git a/docs/permissions/custom-rules.md b/docs/permissions/custom-rules.md
index b4ca86adf5..4b188ce7f9 100644
--- a/docs/permissions/custom-rules.md
+++ b/docs/permissions/custom-rules.md
@@ -4,10 +4,6 @@ title: Defining custom permission rules
description: How to define custom permission rules for existing resources
---
-:::info
-This documentation is written for [the new backend system](../backend-system/index.md) which is the default since Backstage [version 1.24](../releases/v1.24.0.md). If you are still on the old backend system, you may want to read [its own article](https://github.com/backstage/backstage/blob/v1.37.0/docs/permissions/custom-rules--old.md) instead, and [consider migrating](../backend-system/building-backends/08-migrating.md)!
-:::
-
For some use cases, you may want to define custom [rules](../references/glossary.md#rule-permission-plugin) in addition to the ones provided by a plugin. In the [previous section](./writing-a-policy.md) we used the `isEntityOwner` rule to control access for catalog entities. Let's extend this policy with a custom rule that checks what [system](https://backstage.io/docs/features/software-catalog/system-model#system) an entity is part of.
## Define a custom rule
diff --git a/docs/permissions/getting-started.md b/docs/permissions/getting-started.md
index f5b9092ec5..3e40b4597c 100644
--- a/docs/permissions/getting-started.md
+++ b/docs/permissions/getting-started.md
@@ -4,10 +4,6 @@ title: Getting Started
description: How to get started with the permission framework as an integrator
---
-:::info
-This documentation is written for [the new backend system](../backend-system/index.md) which is the default since Backstage [version 1.24](../releases/v1.24.0.md). If you are still on the old backend system, you may want to read [its own article](https://github.com/backstage/backstage/blob/v1.37.0/docs/permissions/getting-started--old.md) instead, and [consider migrating](../backend-system/building-backends/08-migrating.md)!
-:::
-
Backstage integrators control permissions by writing a policy. In general terms, a policy is simply an async function which receives a request to authorize a specific action for a user and (optional) resource, and returns a decision on whether to authorize that permission. Integrators can implement their own policies from scratch, or adopt reusable policies written by others.
## Prerequisites
diff --git a/docs/permissions/plugin-authors/01-setup.md b/docs/permissions/plugin-authors/01-setup.md
index 743c5c9718..4ed348dae6 100644
--- a/docs/permissions/plugin-authors/01-setup.md
+++ b/docs/permissions/plugin-authors/01-setup.md
@@ -4,10 +4,6 @@ title: 1. Tutorial setup
description: How to get started with the permission framework as a plugin author
---
-:::info
-This documentation is written for [the new backend system](../../backend-system/index.md) which is the default since Backstage [version 1.24](../../releases/v1.24.0.md). If you are still on the old backend system, you may want to read [its own article](https://github.com/backstage/backstage/blob/v1.37.0/docs/permissions/plugin-authors/01-setup--old.md) instead, and [consider migrating](../../backend-system/building-backends/08-migrating.md)!
-:::
-
The following tutorial is designed to help plugin authors add support for permissions to their plugins. We'll add support for permissions to example `todo-list` and `todo-list-backend` plugins, but the process should be similar for other plugins!
The rest of this page is focused on adding the `todo-list` and `todo-list-backend` plugins to your Backstage instance. If you want to add support for permissions to your own plugin instead, feel free to skip to the [next section](./02-adding-a-basic-permission-check.md).
diff --git a/docs/permissions/plugin-authors/02-adding-a-basic-permission-check.md b/docs/permissions/plugin-authors/02-adding-a-basic-permission-check.md
index 8ba3ac3152..3790fc8577 100644
--- a/docs/permissions/plugin-authors/02-adding-a-basic-permission-check.md
+++ b/docs/permissions/plugin-authors/02-adding-a-basic-permission-check.md
@@ -4,10 +4,6 @@ title: 2. Adding a basic permission check
description: Explains how to add a basic permission check to a Backstage plugin
---
-:::info
-This documentation is written for [the new backend system](../../backend-system/index.md) which is the default since Backstage [version 1.24](../../releases/v1.24.0.md). If you are still on the old backend system, you may want to read [its own article](https://github.com/backstage/backstage/blob/v1.37.0/docs/permissions/plugin-authors/02-adding-a-basic-permission-check--old.md) instead, and [consider migrating](../../backend-system/building-backends/08-migrating.md)!
-:::
-
If the outcome of a permission check doesn't need to change for different [resources](../../references/glossary.md#resource-permission-plugin), you can use a _basic permission check_. For this kind of check, we simply need to define a permission, and call `authorize` with it.
For this tutorial, we'll use a basic permission check to authorize the `create` endpoint in our todo-backend. This will allow Backstage integrators to control whether each of their users is authorized to create todos by adjusting their [permission policy](../../references/glossary.md#policy-permission-plugin).
diff --git a/docs/permissions/plugin-authors/03-adding-a-resource-permission-check.md b/docs/permissions/plugin-authors/03-adding-a-resource-permission-check.md
index afa56307ce..1e1a73607b 100644
--- a/docs/permissions/plugin-authors/03-adding-a-resource-permission-check.md
+++ b/docs/permissions/plugin-authors/03-adding-a-resource-permission-check.md
@@ -4,10 +4,6 @@ title: 3. Adding a resource permission check
description: Explains how to add a resource permission check to a Backstage plugin
---
-:::info
-This documentation is written for [the new backend system](../../backend-system/index.md) which is the default since Backstage [version 1.24](../../releases/v1.24.0.md). If you are still on the old backend system, you may want to read [its own article](https://github.com/backstage/backstage/blob/v1.37.0/docs/permissions/plugin-authors/03-adding-a-resource-permission-check--old.md) instead, and [consider migrating](../../backend-system/building-backends/08-migrating.md)!
-:::
-
When performing updates (or other operations) on specific [resources](../../references/glossary.md#resource-permission-plugin), the permissions framework allows for the decision to be based on characteristics of the resource itself. This means that it's possible to write policies that (for example) allow the operation for users that own a resource, and deny the operation otherwise.
## Creating the update permission
diff --git a/docs/permissions/plugin-authors/04-authorizing-access-to-paginated-data.md b/docs/permissions/plugin-authors/04-authorizing-access-to-paginated-data.md
index 9b79cec042..28ed56608c 100644
--- a/docs/permissions/plugin-authors/04-authorizing-access-to-paginated-data.md
+++ b/docs/permissions/plugin-authors/04-authorizing-access-to-paginated-data.md
@@ -4,10 +4,6 @@ title: 4. Authorizing access to paginated data
description: Explains how to authorize access to paginated data in a Backstage plugin
---
-:::info
-This documentation is written for [the new backend system](../../backend-system/index.md) which is the default since Backstage [version 1.24](../../releases/v1.24.0.md). If you are still on the old backend system, you may want to read [its own article](https://github.com/backstage/backstage/blob/v1.37.0/docs/permissions/plugin-authors/04-authorizing-access-to-paginated-data--old.md) instead, and [consider migrating](../../backend-system/building-backends/08-migrating.md)!
-:::
-
Authorizing `GET /todos` is similar to the update endpoint, in that it should be possible to authorize access based on the characteristics of each resource. However, we'll need to authorize a list of resources for this endpoint.
One possible solution may leverage the batching functionality to authorize all of the todos, and then returning only the ones for which the decision was `ALLOW`:
diff --git a/docs/permissions/writing-a-policy.md b/docs/permissions/writing-a-policy.md
index 2bf2bcade9..652c698be2 100644
--- a/docs/permissions/writing-a-policy.md
+++ b/docs/permissions/writing-a-policy.md
@@ -4,10 +4,6 @@ title: Writing a permission policy
description: How to write your own permission policy as a Backstage integrator
---
-:::info
-This documentation is written for [the new backend system](../backend-system/index.md) which is the default since Backstage [version 1.24](../releases/v1.24.0.md). If you are still on the old backend system, you may want to read [its own article](https://github.com/backstage/backstage/blob/v1.37.0/docs/permissions/writing-a-policy--old.md) instead, and [consider migrating](../backend-system/building-backends/08-migrating.md)!
-:::
-
In the [previous section](./getting-started.md), we were able to set up the permission framework and make a simple change to our `TestPermissionPolicy` to confirm that policy is indeed wired up correctly.
That policy looked like this:
diff --git a/docs/plugins/backend-plugin.md b/docs/plugins/backend-plugin.md
index 9b8b63fc89..2872fdcda9 100644
--- a/docs/plugins/backend-plugin.md
+++ b/docs/plugins/backend-plugin.md
@@ -38,12 +38,6 @@ cd plugins/carmen-backend
yarn start
```
-:::note Note
-
-This documentation assumes you are using the latest version of Backstage and the new backend system. If you are not, please upgrade and migrate your backend using the [Migration Guide](../backend-system/building-backends/08-migrating.md)
-
-:::
-
This will think for a bit, and then say `Listening on :7007`. In a different
terminal window, now run
diff --git a/docs/plugins/feature-flags.md b/docs/plugins/feature-flags.md
index e9e000df0d..2d0e34ba4b 100644
--- a/docs/plugins/feature-flags.md
+++ b/docs/plugins/feature-flags.md
@@ -19,11 +19,18 @@ import { createPlugin } from '@backstage/core-plugin-api';
export const examplePlugin = createPlugin({
// ...
- featureFlags: [{ name: 'show-example-feature' }],
+ featureFlags: [
+ {
+ name: 'show-example-feature',
+ description: 'Enables the new beta dashboard view',
+ },
+ ],
// ...
});
```
+Note that the `description` property is optional. If not provided, the default "Registered in {pluginId} plugin" message is shown.
+
### In the application
Defining a feature flag in the application is done by adding feature flags in `featureFlags` array in the
diff --git a/docs/plugins/integrating-search-into-plugins.md b/docs/plugins/integrating-search-into-plugins.md
index fd80e0a1eb..7a7201d9e6 100644
--- a/docs/plugins/integrating-search-into-plugins.md
+++ b/docs/plugins/integrating-search-into-plugins.md
@@ -4,10 +4,6 @@ title: Integrating Search into a plugin
description: How to integrate Search into a Backstage plugin
---
-:::info
-This documentation is written for [the new backend system](../backend-system/index.md) which is the default since Backstage [version 1.24](../releases/v1.24.0.md). If you are still on the old backend system, you may want to read [its own article](https://github.com/backstage/backstage/blob/v1.37.0/docs/plugins/integrating-search-into-plugins--old.md) instead, and [consider migrating](../backend-system/building-backends/08-migrating.md)!
-:::
-
The Backstage Search Platform was designed to give plugin developers the APIs
and interfaces needed to offer search experiences within their plugins, while
abstracting away (and instead empowering application integrators to choose) the
diff --git a/docs/tutorials/enable-public-entry.md b/docs/tutorials/enable-public-entry.md
index e430768785..a1321dca05 100644
--- a/docs/tutorials/enable-public-entry.md
+++ b/docs/tutorials/enable-public-entry.md
@@ -107,10 +107,11 @@ If your app uses the new frontend system, you can still use the public entry poi
```tsx title="in packages/app/src/index-public-experimental.tsx"
import ReactDOM from 'react-dom/client';
import { signInPageModule } from './overrides/SignInPage';
-import { createPublicSignInApp } from '@backstage/frontend-defaults';
+import { appModulePublicSignIn } from '@backstage/plugin-app/alpha';
+import { createApp } from '@backstage/frontend-defaults';
-const app = createPublicSignInApp({
- features: [signInPageModule],
+const app = createApp({
+ features: [signInPageModule, appModulePublicSignIn],
});
ReactDOM.createRoot(document.getElementById('root')!).render(app.createRoot());
diff --git a/microsite/data/plugins/github-actions.yaml b/microsite/data/plugins/github-actions.yaml
index 6b1af3fe36..55503f4fbb 100644
--- a/microsite/data/plugins/github-actions.yaml
+++ b/microsite/data/plugins/github-actions.yaml
@@ -4,7 +4,7 @@ author: Spotify
authorUrl: https://github.com/spotify
category: CI/CD
description: GitHub Actions makes it easy to automate all your software workflows, now with world-class CI/CD. Build, test, and deploy your code right from GitHub.
-documentation: https://github.com/backstage/community-plugins/tree/main/workspaces/github-actions/plugins/github-actions
+documentation: https://github.com/backstage/community-plugins/tree/main/workspaces/github/plugins/github-actions
iconUrl: https://avatars2.githubusercontent.com/u/44036562?s=400&v=4
npmPackageName: '@backstage-community/plugin-github-actions'
addedDate: '2021-01-20'
diff --git a/microsite/data/plugins/graphiql.yaml b/microsite/data/plugins/graphiql.yaml
index 12c2f106a5..8d0a37cb65 100644
--- a/microsite/data/plugins/graphiql.yaml
+++ b/microsite/data/plugins/graphiql.yaml
@@ -5,7 +5,7 @@ authorUrl: https://github.com/spotify
category: Debugging
description: Integrates GraphiQL as a tool to browse GraphQL API endpoints inside Backstage.
documentation: https://github.com/backstage/community-plugins/tree/main/workspaces/graphiql/plugins/graphiql
-iconUrl: https://upload.wikimedia.org/wikipedia/commons/thumb/1/17/GraphQL_Logo.svg/1024px-GraphQL_Logo.svg.png
+iconUrl: https://upload.wikimedia.org/wikipedia/commons/1/17/GraphQL_Logo.svg
npmPackageName: '@backstage-community/plugin-graphiql'
addedDate: '2020-11-03'
status: active
diff --git a/microsite/package.json b/microsite/package.json
index 0da6c2c8be..51e1284668 100644
--- a/microsite/package.json
+++ b/microsite/package.json
@@ -20,8 +20,8 @@
},
"prettier": "@backstage/cli/config/prettier",
"resolutions": {
- "@swc/core": "1.15.3",
- "@swc/html": "1.15.3",
+ "@swc/core": "1.15.18",
+ "@swc/html": "1.15.18",
"node-polyfill-webpack-plugin": "^3.0.0"
},
"dependencies": {
diff --git a/microsite/yarn.lock b/microsite/yarn.lock
index 4cd9f95851..0935b07949 100644
--- a/microsite/yarn.lock
+++ b/microsite/yarn.lock
@@ -4053,90 +4053,90 @@ __metadata:
languageName: node
linkType: hard
-"@swc/core-darwin-arm64@npm:1.15.3":
- version: 1.15.3
- resolution: "@swc/core-darwin-arm64@npm:1.15.3"
+"@swc/core-darwin-arm64@npm:1.15.18":
+ version: 1.15.18
+ resolution: "@swc/core-darwin-arm64@npm:1.15.18"
conditions: os=darwin & cpu=arm64
languageName: node
linkType: hard
-"@swc/core-darwin-x64@npm:1.15.3":
- version: 1.15.3
- resolution: "@swc/core-darwin-x64@npm:1.15.3"
+"@swc/core-darwin-x64@npm:1.15.18":
+ version: 1.15.18
+ resolution: "@swc/core-darwin-x64@npm:1.15.18"
conditions: os=darwin & cpu=x64
languageName: node
linkType: hard
-"@swc/core-linux-arm-gnueabihf@npm:1.15.3":
- version: 1.15.3
- resolution: "@swc/core-linux-arm-gnueabihf@npm:1.15.3"
+"@swc/core-linux-arm-gnueabihf@npm:1.15.18":
+ version: 1.15.18
+ resolution: "@swc/core-linux-arm-gnueabihf@npm:1.15.18"
conditions: os=linux & cpu=arm
languageName: node
linkType: hard
-"@swc/core-linux-arm64-gnu@npm:1.15.3":
- version: 1.15.3
- resolution: "@swc/core-linux-arm64-gnu@npm:1.15.3"
+"@swc/core-linux-arm64-gnu@npm:1.15.18":
+ version: 1.15.18
+ resolution: "@swc/core-linux-arm64-gnu@npm:1.15.18"
conditions: os=linux & cpu=arm64 & libc=glibc
languageName: node
linkType: hard
-"@swc/core-linux-arm64-musl@npm:1.15.3":
- version: 1.15.3
- resolution: "@swc/core-linux-arm64-musl@npm:1.15.3"
+"@swc/core-linux-arm64-musl@npm:1.15.18":
+ version: 1.15.18
+ resolution: "@swc/core-linux-arm64-musl@npm:1.15.18"
conditions: os=linux & cpu=arm64 & libc=musl
languageName: node
linkType: hard
-"@swc/core-linux-x64-gnu@npm:1.15.3":
- version: 1.15.3
- resolution: "@swc/core-linux-x64-gnu@npm:1.15.3"
+"@swc/core-linux-x64-gnu@npm:1.15.18":
+ version: 1.15.18
+ resolution: "@swc/core-linux-x64-gnu@npm:1.15.18"
conditions: os=linux & cpu=x64 & libc=glibc
languageName: node
linkType: hard
-"@swc/core-linux-x64-musl@npm:1.15.3":
- version: 1.15.3
- resolution: "@swc/core-linux-x64-musl@npm:1.15.3"
+"@swc/core-linux-x64-musl@npm:1.15.18":
+ version: 1.15.18
+ resolution: "@swc/core-linux-x64-musl@npm:1.15.18"
conditions: os=linux & cpu=x64 & libc=musl
languageName: node
linkType: hard
-"@swc/core-win32-arm64-msvc@npm:1.15.3":
- version: 1.15.3
- resolution: "@swc/core-win32-arm64-msvc@npm:1.15.3"
+"@swc/core-win32-arm64-msvc@npm:1.15.18":
+ version: 1.15.18
+ resolution: "@swc/core-win32-arm64-msvc@npm:1.15.18"
conditions: os=win32 & cpu=arm64
languageName: node
linkType: hard
-"@swc/core-win32-ia32-msvc@npm:1.15.3":
- version: 1.15.3
- resolution: "@swc/core-win32-ia32-msvc@npm:1.15.3"
+"@swc/core-win32-ia32-msvc@npm:1.15.18":
+ version: 1.15.18
+ resolution: "@swc/core-win32-ia32-msvc@npm:1.15.18"
conditions: os=win32 & cpu=ia32
languageName: node
linkType: hard
-"@swc/core-win32-x64-msvc@npm:1.15.3":
- version: 1.15.3
- resolution: "@swc/core-win32-x64-msvc@npm:1.15.3"
+"@swc/core-win32-x64-msvc@npm:1.15.18":
+ version: 1.15.18
+ resolution: "@swc/core-win32-x64-msvc@npm:1.15.18"
conditions: os=win32 & cpu=x64
languageName: node
linkType: hard
-"@swc/core@npm:1.15.3":
- version: 1.15.3
- resolution: "@swc/core@npm:1.15.3"
+"@swc/core@npm:1.15.18":
+ version: 1.15.18
+ resolution: "@swc/core@npm:1.15.18"
dependencies:
- "@swc/core-darwin-arm64": "npm:1.15.3"
- "@swc/core-darwin-x64": "npm:1.15.3"
- "@swc/core-linux-arm-gnueabihf": "npm:1.15.3"
- "@swc/core-linux-arm64-gnu": "npm:1.15.3"
- "@swc/core-linux-arm64-musl": "npm:1.15.3"
- "@swc/core-linux-x64-gnu": "npm:1.15.3"
- "@swc/core-linux-x64-musl": "npm:1.15.3"
- "@swc/core-win32-arm64-msvc": "npm:1.15.3"
- "@swc/core-win32-ia32-msvc": "npm:1.15.3"
- "@swc/core-win32-x64-msvc": "npm:1.15.3"
+ "@swc/core-darwin-arm64": "npm:1.15.18"
+ "@swc/core-darwin-x64": "npm:1.15.18"
+ "@swc/core-linux-arm-gnueabihf": "npm:1.15.18"
+ "@swc/core-linux-arm64-gnu": "npm:1.15.18"
+ "@swc/core-linux-arm64-musl": "npm:1.15.18"
+ "@swc/core-linux-x64-gnu": "npm:1.15.18"
+ "@swc/core-linux-x64-musl": "npm:1.15.18"
+ "@swc/core-win32-arm64-msvc": "npm:1.15.18"
+ "@swc/core-win32-ia32-msvc": "npm:1.15.18"
+ "@swc/core-win32-x64-msvc": "npm:1.15.18"
"@swc/counter": "npm:^0.1.3"
"@swc/types": "npm:^0.1.25"
peerDependencies:
@@ -4165,7 +4165,7 @@ __metadata:
peerDependenciesMeta:
"@swc/helpers":
optional: true
- checksum: 10/280330d82328818138ed64fdcf9ea9abde6b6f16eca65a9d4db27dde06a8dfffd2649f3447d2243387277513c7430fa4142cafcfd64e943d682ce6a713cb8c2d
+ checksum: 10/ef198b9feb6eee034e3a912c37988ece2885fec35419e8245d467adbc1fc47a5c3e61869d1bdbe6fff76cbd9186ef278120cbb9746d5f7446576f4a7f15c2dcd
languageName: node
linkType: hard
@@ -4176,91 +4176,91 @@ __metadata:
languageName: node
linkType: hard
-"@swc/html-darwin-arm64@npm:1.15.3":
- version: 1.15.3
- resolution: "@swc/html-darwin-arm64@npm:1.15.3"
+"@swc/html-darwin-arm64@npm:1.15.18":
+ version: 1.15.18
+ resolution: "@swc/html-darwin-arm64@npm:1.15.18"
conditions: os=darwin & cpu=arm64
languageName: node
linkType: hard
-"@swc/html-darwin-x64@npm:1.15.3":
- version: 1.15.3
- resolution: "@swc/html-darwin-x64@npm:1.15.3"
+"@swc/html-darwin-x64@npm:1.15.18":
+ version: 1.15.18
+ resolution: "@swc/html-darwin-x64@npm:1.15.18"
conditions: os=darwin & cpu=x64
languageName: node
linkType: hard
-"@swc/html-linux-arm-gnueabihf@npm:1.15.3":
- version: 1.15.3
- resolution: "@swc/html-linux-arm-gnueabihf@npm:1.15.3"
+"@swc/html-linux-arm-gnueabihf@npm:1.15.18":
+ version: 1.15.18
+ resolution: "@swc/html-linux-arm-gnueabihf@npm:1.15.18"
conditions: os=linux & cpu=arm
languageName: node
linkType: hard
-"@swc/html-linux-arm64-gnu@npm:1.15.3":
- version: 1.15.3
- resolution: "@swc/html-linux-arm64-gnu@npm:1.15.3"
+"@swc/html-linux-arm64-gnu@npm:1.15.18":
+ version: 1.15.18
+ resolution: "@swc/html-linux-arm64-gnu@npm:1.15.18"
conditions: os=linux & cpu=arm64 & libc=glibc
languageName: node
linkType: hard
-"@swc/html-linux-arm64-musl@npm:1.15.3":
- version: 1.15.3
- resolution: "@swc/html-linux-arm64-musl@npm:1.15.3"
+"@swc/html-linux-arm64-musl@npm:1.15.18":
+ version: 1.15.18
+ resolution: "@swc/html-linux-arm64-musl@npm:1.15.18"
conditions: os=linux & cpu=arm64 & libc=musl
languageName: node
linkType: hard
-"@swc/html-linux-x64-gnu@npm:1.15.3":
- version: 1.15.3
- resolution: "@swc/html-linux-x64-gnu@npm:1.15.3"
+"@swc/html-linux-x64-gnu@npm:1.15.18":
+ version: 1.15.18
+ resolution: "@swc/html-linux-x64-gnu@npm:1.15.18"
conditions: os=linux & cpu=x64 & libc=glibc
languageName: node
linkType: hard
-"@swc/html-linux-x64-musl@npm:1.15.3":
- version: 1.15.3
- resolution: "@swc/html-linux-x64-musl@npm:1.15.3"
+"@swc/html-linux-x64-musl@npm:1.15.18":
+ version: 1.15.18
+ resolution: "@swc/html-linux-x64-musl@npm:1.15.18"
conditions: os=linux & cpu=x64 & libc=musl
languageName: node
linkType: hard
-"@swc/html-win32-arm64-msvc@npm:1.15.3":
- version: 1.15.3
- resolution: "@swc/html-win32-arm64-msvc@npm:1.15.3"
+"@swc/html-win32-arm64-msvc@npm:1.15.18":
+ version: 1.15.18
+ resolution: "@swc/html-win32-arm64-msvc@npm:1.15.18"
conditions: os=win32 & cpu=arm64
languageName: node
linkType: hard
-"@swc/html-win32-ia32-msvc@npm:1.15.3":
- version: 1.15.3
- resolution: "@swc/html-win32-ia32-msvc@npm:1.15.3"
+"@swc/html-win32-ia32-msvc@npm:1.15.18":
+ version: 1.15.18
+ resolution: "@swc/html-win32-ia32-msvc@npm:1.15.18"
conditions: os=win32 & cpu=ia32
languageName: node
linkType: hard
-"@swc/html-win32-x64-msvc@npm:1.15.3":
- version: 1.15.3
- resolution: "@swc/html-win32-x64-msvc@npm:1.15.3"
+"@swc/html-win32-x64-msvc@npm:1.15.18":
+ version: 1.15.18
+ resolution: "@swc/html-win32-x64-msvc@npm:1.15.18"
conditions: os=win32 & cpu=x64
languageName: node
linkType: hard
-"@swc/html@npm:1.15.3":
- version: 1.15.3
- resolution: "@swc/html@npm:1.15.3"
+"@swc/html@npm:1.15.18":
+ version: 1.15.18
+ resolution: "@swc/html@npm:1.15.18"
dependencies:
"@swc/counter": "npm:^0.1.3"
- "@swc/html-darwin-arm64": "npm:1.15.3"
- "@swc/html-darwin-x64": "npm:1.15.3"
- "@swc/html-linux-arm-gnueabihf": "npm:1.15.3"
- "@swc/html-linux-arm64-gnu": "npm:1.15.3"
- "@swc/html-linux-arm64-musl": "npm:1.15.3"
- "@swc/html-linux-x64-gnu": "npm:1.15.3"
- "@swc/html-linux-x64-musl": "npm:1.15.3"
- "@swc/html-win32-arm64-msvc": "npm:1.15.3"
- "@swc/html-win32-ia32-msvc": "npm:1.15.3"
- "@swc/html-win32-x64-msvc": "npm:1.15.3"
+ "@swc/html-darwin-arm64": "npm:1.15.18"
+ "@swc/html-darwin-x64": "npm:1.15.18"
+ "@swc/html-linux-arm-gnueabihf": "npm:1.15.18"
+ "@swc/html-linux-arm64-gnu": "npm:1.15.18"
+ "@swc/html-linux-arm64-musl": "npm:1.15.18"
+ "@swc/html-linux-x64-gnu": "npm:1.15.18"
+ "@swc/html-linux-x64-musl": "npm:1.15.18"
+ "@swc/html-win32-arm64-msvc": "npm:1.15.18"
+ "@swc/html-win32-ia32-msvc": "npm:1.15.18"
+ "@swc/html-win32-x64-msvc": "npm:1.15.18"
dependenciesMeta:
"@swc/html-darwin-arm64":
optional: true
@@ -4282,7 +4282,7 @@ __metadata:
optional: true
"@swc/html-win32-x64-msvc":
optional: true
- checksum: 10/753ddec5a5fb53a5245b4e5ab990c8dc9e6aff2c3da99ab671be2535d3fc566953dac4aa30c9a435e78a80901384fbc8f43c603c379abe2d21a11303dd804393
+ checksum: 10/5fdef26fa88693c2913d2ee147332ab366bc6d41726ea2b57db31d3992fbf47aa5b881537f32a077535a64f896a7f7af8f0092343d74256fd8c290431e1a8407
languageName: node
linkType: hard
@@ -4311,13 +4311,6 @@ __metadata:
languageName: node
linkType: hard
-"@trysound/sax@npm:0.2.0":
- version: 0.2.0
- resolution: "@trysound/sax@npm:0.2.0"
- checksum: 10/7379713eca480ac0d9b6c7b063e06b00a7eac57092354556c81027066eb65b61ea141a69d0cc2e15d32e05b2834d4c9c2184793a5e36bbf5daf05ee5676af18c
- languageName: node
- linkType: hard
-
"@tybys/wasm-util@npm:^0.10.1":
version: 0.10.1
resolution: "@tybys/wasm-util@npm:0.10.1"
@@ -8555,9 +8548,9 @@ __metadata:
linkType: hard
"immutable@npm:^5.0.2":
- version: 5.0.2
- resolution: "immutable@npm:5.0.2"
- checksum: 10/89b1117c610024b7a9214eade8b9f1ed38b00c82235f119515cfa5eaf26270eccbc803296d4c3c12f53e50802f042f84d811998910b866363913720da768472e
+ version: 5.1.5
+ resolution: "immutable@npm:5.1.5"
+ checksum: 10/7aec2740239772ec8e92e793c991bd809203a97694f4ff3a18e50e28f9a6b02393ad033d87b458037bdf8c0ea37d4446d640e825f6171df3405cf6cf300ce028
languageName: node
linkType: hard
@@ -13312,10 +13305,10 @@ __metadata:
languageName: node
linkType: hard
-"sax@npm:^1.2.4":
- version: 1.2.4
- resolution: "sax@npm:1.2.4"
- checksum: 10/09b79ff6dc09689a24323352117c94593c69db348997b2af0edbd82fa08aba47d778055bf9616b57285bb73d25d790900c044bf631a8f10c8252412e3f3fe5dd
+"sax@npm:^1.2.4, sax@npm:^1.5.0":
+ version: 1.5.0
+ resolution: "sax@npm:1.5.0"
+ checksum: 10/9012ff37dda7a7ac5da45db2143b04036103e8bef8d586c3023afd5df6caf0ebd7f38017eee344ad2e2247eded7d38e9c42cf291d8dd91781352900ac0fd2d9f
languageName: node
linkType: hard
@@ -14132,19 +14125,19 @@ __metadata:
linkType: hard
"svgo@npm:^3.0.2, svgo@npm:^3.2.0":
- version: 3.3.2
- resolution: "svgo@npm:3.3.2"
+ version: 3.3.3
+ resolution: "svgo@npm:3.3.3"
dependencies:
- "@trysound/sax": "npm:0.2.0"
commander: "npm:^7.2.0"
css-select: "npm:^5.1.0"
css-tree: "npm:^2.3.1"
css-what: "npm:^6.1.0"
csso: "npm:^5.0.5"
picocolors: "npm:^1.0.0"
+ sax: "npm:^1.5.0"
bin:
svgo: ./bin/svgo
- checksum: 10/82fdea9b938884d808506104228e4d3af0050d643d5b46ff7abc903ff47a91bbf6561373394868aaf07a28f006c4057b8fbf14bbd666298abdd7cc590d4f7700
+ checksum: 10/f3c1b4d05d1704483e53515d5995af5f06a2718df85e3a8320f57bb256b8dc926b84c87a1a9b98e9d3ca1224314cc0676a803bdd03163508292f2d45c7077096
languageName: node
linkType: hard
diff --git a/package.json b/package.json
index ac79d5976c..d356805b05 100644
--- a/package.json
+++ b/package.json
@@ -138,7 +138,7 @@
"@storybook/addon-a11y": "^10.3.0-alpha.1",
"@storybook/addon-docs": "^10.3.0-alpha.1",
"@storybook/addon-links": "^10.3.0-alpha.1",
- "@storybook/addon-mcp": "^0.2.2",
+ "@storybook/addon-mcp": "^0.3.0",
"@storybook/addon-themes": "^10.3.0-alpha.1",
"@storybook/addon-vitest": "^10.3.0-alpha.1",
"@storybook/react-vite": "^10.3.0-alpha.1",
diff --git a/packages/app-example-plugin/report.api.md b/packages/app-example-plugin/report.api.md
index 70b3446a2b..432174da68 100644
--- a/packages/app-example-plugin/report.api.md
+++ b/packages/app-example-plugin/report.api.md
@@ -87,7 +87,6 @@ const examplePlugin: OverridableFrontendPlugin<
>;
};
params: {
- defaultPath?: [Error: `Use the 'path' param instead`];
path: string;
title?: string;
icon?: IconElement;
diff --git a/packages/app-legacy/src/components/catalog/EntityPage.tsx b/packages/app-legacy/src/components/catalog/EntityPage.tsx
index 32249cb84a..7c42b62542 100644
--- a/packages/app-legacy/src/components/catalog/EntityPage.tsx
+++ b/packages/app-legacy/src/components/catalog/EntityPage.tsx
@@ -170,7 +170,7 @@ const overviewContent = (
-
+
@@ -299,7 +299,7 @@ const apiPage = (
-
+
@@ -333,10 +333,7 @@ const userPage = (
-
+
@@ -352,10 +349,7 @@ const groupPage = (
-
+
@@ -377,7 +371,7 @@ const systemPage = (
-
+
@@ -392,7 +386,6 @@ const systemPage = (
-
+
@@ -440,7 +433,7 @@ const resourcePage = (
-
+
diff --git a/packages/backend-defaults/package.json b/packages/backend-defaults/package.json
index 4aaf0408b4..95df1407ad 100644
--- a/packages/backend-defaults/package.json
+++ b/packages/backend-defaults/package.json
@@ -164,7 +164,7 @@
"cron": "^3.0.0",
"express": "^4.22.0",
"express-promise-router": "^4.1.0",
- "express-rate-limit": "^7.5.0",
+ "express-rate-limit": "^8.2.2",
"fs-extra": "^11.2.0",
"git-url-parse": "^15.0.0",
"helmet": "^6.0.0",
diff --git a/packages/backend-defaults/src/entrypoints/scheduler/lib/LocalTaskWorker.test.ts b/packages/backend-defaults/src/entrypoints/scheduler/lib/LocalTaskWorker.test.ts
index 14fedfb3c0..04c2b17ad3 100644
--- a/packages/backend-defaults/src/entrypoints/scheduler/lib/LocalTaskWorker.test.ts
+++ b/packages/backend-defaults/src/entrypoints/scheduler/lib/LocalTaskWorker.test.ts
@@ -16,6 +16,7 @@
import { LocalTaskWorker } from './LocalTaskWorker';
import { mockServices } from '@backstage/backend-test-utils';
+import { ConflictError } from '@backstage/errors';
import waitFor from 'wait-for-expect';
jest.setTimeout(10_000);
@@ -110,6 +111,54 @@ describe('LocalTaskWorker', () => {
controller.abort();
});
+ it('can cancel a running task', async () => {
+ let receivedSignal: AbortSignal | undefined;
+ const fn = jest.fn(async (signal: AbortSignal) => {
+ receivedSignal = signal;
+ await new Promise(r => setTimeout(r, 5000));
+ });
+ const controller = new AbortController();
+
+ const worker = new LocalTaskWorker('a', fn, logger);
+ worker.start(
+ {
+ version: 2,
+ cadence: 'PT10S',
+ timeoutAfterDuration: 'PT10S',
+ },
+ { signal: controller.signal },
+ );
+
+ await waitFor(() => {
+ expect(fn).toHaveBeenCalledTimes(1);
+ });
+
+ expect(receivedSignal?.aborted).toBe(false);
+ worker.cancel();
+ expect(receivedSignal?.aborted).toBe(true);
+
+ controller.abort();
+ });
+
+ it('cannot cancel a task that is not running', async () => {
+ const fn = jest.fn();
+ const controller = new AbortController();
+
+ const worker = new LocalTaskWorker('a', fn, logger);
+ worker.start(
+ {
+ version: 2,
+ initialDelayDuration: 'PT1000S',
+ cadence: 'PT10S',
+ timeoutAfterDuration: 'PT10S',
+ },
+ { signal: controller.signal },
+ );
+
+ expect(() => worker.cancel()).toThrow(ConflictError);
+ controller.abort();
+ });
+
it('goes through the expected states', async () => {
const fn = jest
.fn()
diff --git a/packages/backend-defaults/src/entrypoints/scheduler/lib/LocalTaskWorker.ts b/packages/backend-defaults/src/entrypoints/scheduler/lib/LocalTaskWorker.ts
index efecb1c0ed..168649436c 100644
--- a/packages/backend-defaults/src/entrypoints/scheduler/lib/LocalTaskWorker.ts
+++ b/packages/backend-defaults/src/entrypoints/scheduler/lib/LocalTaskWorker.ts
@@ -29,6 +29,7 @@ import { delegateAbortController, serializeError, sleep } from './util';
*/
export class LocalTaskWorker {
private abortWait: AbortController | undefined;
+ private taskAbortController: AbortController | undefined;
#taskState: Exclude = {
status: 'idle',
};
@@ -93,6 +94,13 @@ export class LocalTaskWorker {
this.abortWait.abort();
}
+ cancel(): void {
+ if (!this.taskAbortController) {
+ throw new ConflictError(`Task ${this.taskId} is not running`);
+ }
+ this.taskAbortController.abort();
+ }
+
taskState(): TaskApiTasksResponse['taskState'] {
return this.#taskState;
}
@@ -134,10 +142,10 @@ export class LocalTaskWorker {
): Promise {
// Abort the task execution either if the worker is stopped, or if the
// task timeout is hit
- const taskAbortController = delegateAbortController(signal);
+ this.taskAbortController = delegateAbortController(signal);
const timeoutDuration = Duration.fromISO(settings.timeoutAfterDuration);
const timeoutHandle = setTimeout(() => {
- taskAbortController.abort();
+ this.taskAbortController?.abort();
}, timeoutDuration.as('milliseconds'));
this.#taskState = {
@@ -152,7 +160,7 @@ export class LocalTaskWorker {
};
try {
- await this.fn(taskAbortController.signal);
+ await this.fn(this.taskAbortController.signal);
this.#taskState.lastRunEndedAt = DateTime.utc().toISO()!;
this.#taskState.lastRunError = undefined;
} catch (e) {
@@ -162,7 +170,8 @@ export class LocalTaskWorker {
// release resources
clearTimeout(timeoutHandle);
- taskAbortController.abort();
+ this.taskAbortController.abort();
+ this.taskAbortController = undefined;
}
/**
diff --git a/packages/backend-defaults/src/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.test.ts b/packages/backend-defaults/src/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.test.ts
index 2148148c9e..cc8aac5f51 100644
--- a/packages/backend-defaults/src/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.test.ts
+++ b/packages/backend-defaults/src/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.test.ts
@@ -399,6 +399,100 @@ describe('PluginTaskManagerImpl', () => {
);
});
+ describe('cancelTask with local scope', () => {
+ it('can cancel a running task', async () => {
+ const { manager } = await init('SQLITE_3');
+
+ const promise = createDeferred();
+
+ await manager.scheduleTask({
+ id: 'task1',
+ timeout: Duration.fromMillis(5000),
+ frequency: Duration.fromObject({ years: 1 }),
+ fn: async () => {
+ promise.resolve();
+ await new Promise(r => setTimeout(r, 20000));
+ },
+ scope: 'local',
+ });
+
+ await promise;
+ await expect(manager.cancelTask('task1')).resolves.toBeUndefined();
+ }, 60_000);
+
+ it('cannot cancel a task that is not running', async () => {
+ const { manager } = await init('SQLITE_3');
+
+ const fn = jest.fn();
+ await manager.scheduleTask({
+ id: 'task1',
+ timeout: Duration.fromMillis(5000),
+ frequency: Duration.fromObject({ years: 1 }),
+ initialDelay: Duration.fromObject({ years: 1 }),
+ fn,
+ scope: 'local',
+ });
+
+ await expect(manager.cancelTask('task1')).rejects.toThrow(ConflictError);
+ }, 60_000);
+ });
+
+ describe('cancelTask with global scope', () => {
+ it.each(databases.eachSupportedId())(
+ 'can cancel a running task, %p',
+ async databaseId => {
+ const { manager } = await init(databaseId);
+
+ const promise = createDeferred();
+
+ await manager.scheduleTask({
+ id: 'task1',
+ timeout: Duration.fromMillis(5000),
+ frequency: Duration.fromObject({ years: 1 }),
+ fn: async () => {
+ promise.resolve();
+ await new Promise(r => setTimeout(r, 20000));
+ },
+ scope: 'global',
+ });
+
+ await promise;
+ await expect(manager.cancelTask('task1')).resolves.toBeUndefined();
+ },
+ );
+
+ it.each(databases.eachSupportedId())(
+ 'cannot cancel a non-existent task, %p',
+ async databaseId => {
+ const { manager } = await init(databaseId);
+
+ await expect(manager.cancelTask('nonexistent')).rejects.toThrow(
+ NotFoundError,
+ );
+ },
+ );
+
+ it.each(databases.eachSupportedId())(
+ 'cannot cancel a task that is not running, %p',
+ async databaseId => {
+ const { manager } = await init(databaseId);
+
+ await manager.scheduleTask({
+ id: 'task1',
+ timeout: Duration.fromMillis(5000),
+ frequency: Duration.fromObject({ years: 1 }),
+ initialDelay: Duration.fromObject({ years: 1 }),
+ fn: jest.fn(),
+ scope: 'global',
+ });
+
+ await expect(manager.cancelTask('task1')).rejects.toThrow(
+ ConflictError,
+ );
+ },
+ );
+ });
+
describe('parseDuration', () => {
it('should parse durations', () => {
expect(parseDuration({ milliseconds: 5000 })).toEqual('PT5S');
diff --git a/packages/backend-defaults/src/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.ts b/packages/backend-defaults/src/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.ts
index e711744123..2aad8647fe 100644
--- a/packages/backend-defaults/src/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.ts
+++ b/packages/backend-defaults/src/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.ts
@@ -107,6 +107,17 @@ export class PluginTaskSchedulerImpl implements SchedulerService {
await TaskWorker.trigger(knex, id);
}
+ async cancelTask(id: string): Promise {
+ const localTask = this.localWorkersById.get(id);
+ if (localTask) {
+ localTask.cancel();
+ return;
+ }
+
+ const knex = await this.databaseFactory();
+ await TaskWorker.cancel(knex, id);
+ }
+
async scheduleTask(
task: SchedulerServiceTaskScheduleDefinition &
SchedulerServiceTaskInvocationDefinition,
@@ -206,6 +217,15 @@ export class PluginTaskSchedulerImpl implements SchedulerService {
},
);
+ router.post(
+ '/.backstage/scheduler/v1/tasks/:id/cancel',
+ async (req, res) => {
+ const { id } = req.params;
+ await this.cancelTask(id);
+ res.status(200).end();
+ },
+ );
+
return router;
}
diff --git a/packages/backend-defaults/src/entrypoints/scheduler/lib/TaskWorker.test.ts b/packages/backend-defaults/src/entrypoints/scheduler/lib/TaskWorker.test.ts
index 5bd3fb38cb..3446d635d1 100644
--- a/packages/backend-defaults/src/entrypoints/scheduler/lib/TaskWorker.test.ts
+++ b/packages/backend-defaults/src/entrypoints/scheduler/lib/TaskWorker.test.ts
@@ -15,6 +15,7 @@
*/
import { TestDatabases, mockServices } from '@backstage/backend-test-utils';
+import { ConflictError, NotFoundError } from '@backstage/errors';
import { DateTime, Duration } from 'luxon';
import waitForExpect from 'wait-for-expect';
import { migrateBackendTasks } from '../database/migrateBackendTasks';
@@ -584,4 +585,79 @@ describe('TaskWorker', () => {
await knex.destroy();
},
);
+
+ it.each(databases.eachSupportedId())(
+ 'can cancel a running task, %p',
+ async databaseId => {
+ const knex = await databases.init(databaseId);
+ await migrateBackendTasks(knex);
+
+ const fn = jest.fn(async () => {});
+ const settings: TaskSettingsV2 = {
+ version: 2,
+ cadence: '* * * * * *',
+ initialDelayDuration: undefined,
+ timeoutAfterDuration: Duration.fromObject({ minutes: 1 }).toISO()!,
+ };
+
+ const worker = new TaskWorker('task1', fn, knex, logger);
+ await worker.persistTask(settings);
+ await worker.tryClaimTask('ticket', settings);
+
+ // Verify the task is running
+ let row = (await knex(DB_TASKS_TABLE))[0];
+ expect(row.current_run_ticket).toBe('ticket');
+
+ await TaskWorker.cancel(knex, 'task1');
+
+ // Verify the task is now idle with a cancellation error recorded
+ row = (await knex(DB_TASKS_TABLE))[0];
+ expect(row.current_run_ticket).toBeNull();
+ expect(row.current_run_started_at).toBeNull();
+ expect(row.current_run_expires_at).toBeNull();
+ expect(row.last_run_ended_at).not.toBeNull();
+ expect(row.last_run_error_json).toContain('Task was cancelled');
+
+ await knex.destroy();
+ },
+ );
+
+ it.each(databases.eachSupportedId())(
+ 'cannot cancel a non-existent task, %p',
+ async databaseId => {
+ const knex = await databases.init(databaseId);
+ await migrateBackendTasks(knex);
+
+ await expect(TaskWorker.cancel(knex, 'nonexistent')).rejects.toThrow(
+ NotFoundError,
+ );
+
+ await knex.destroy();
+ },
+ );
+
+ it.each(databases.eachSupportedId())(
+ 'cannot cancel a task that is not running, %p',
+ async databaseId => {
+ const knex = await databases.init(databaseId);
+ await migrateBackendTasks(knex);
+
+ const fn = jest.fn(async () => {});
+ const settings: TaskSettingsV2 = {
+ version: 2,
+ cadence: '* * * * * *',
+ initialDelayDuration: undefined,
+ timeoutAfterDuration: Duration.fromObject({ minutes: 1 }).toISO()!,
+ };
+
+ const worker = new TaskWorker('task1', fn, knex, logger);
+ await worker.persistTask(settings);
+
+ await expect(TaskWorker.cancel(knex, 'task1')).rejects.toThrow(
+ ConflictError,
+ );
+
+ await knex.destroy();
+ },
+ );
});
diff --git a/packages/backend-defaults/src/entrypoints/scheduler/lib/TaskWorker.ts b/packages/backend-defaults/src/entrypoints/scheduler/lib/TaskWorker.ts
index e47967de90..4f32dc6863 100644
--- a/packages/backend-defaults/src/entrypoints/scheduler/lib/TaskWorker.ts
+++ b/packages/backend-defaults/src/entrypoints/scheduler/lib/TaskWorker.ts
@@ -152,6 +152,36 @@ export class TaskWorker {
}
}
+ static async cancel(knex: Knex, taskId: string): Promise {
+ const [row] = await knex(DB_TASKS_TABLE)
+ .where('id', '=', taskId)
+ .select('settings_json', 'current_run_ticket');
+ if (!row) {
+ throw new NotFoundError(`Task ${taskId} does not exist`);
+ }
+ if (!row.current_run_ticket) {
+ throw new ConflictError(`Task ${taskId} is not running`);
+ }
+
+ const settings = taskSettingsV2Schema.parse(JSON.parse(row.settings_json));
+ const nextRun = TaskWorker.computeNextRunStartAt(knex, settings);
+
+ const updatedRows = await knex(DB_TASKS_TABLE)
+ .where('id', '=', taskId)
+ .where('current_run_ticket', '=', row.current_run_ticket)
+ .update({
+ next_run_start_at: nextRun,
+ current_run_ticket: knex.raw('null'),
+ current_run_started_at: knex.raw('null'),
+ current_run_expires_at: knex.raw('null'),
+ last_run_ended_at: knex.fn.now(),
+ last_run_error_json: serializeError(new Error('Task was cancelled')),
+ });
+ if (updatedRows < 1) {
+ throw new ConflictError(`Task ${taskId} is not running`);
+ }
+ }
+
static async taskStates(
knex: Knex,
): Promise