docs/releases/v1.42.0-changelog.md
Upgrade Helper: https://backstage.github.io/upgrade-helper/?to=1.42.0
Infinispan Data Gridbetter-sqlite3 to v12express-openapi-validator to 5.5.8 to fix security vulnerability in transitive dependency multermockServices.scheduler to use a mocked implementation instead of the default scheduler implementation. This implementation runs any scheduled tasks immediately on startup, as long as they don't have an initial delay or a manual trigger. After the initial run, the tasks are never run again unless manually triggered.279e1f7: Updated the type definition of mockErrorHandler to ensure that it is used correctly.
// This is wrong and will now result in a type error
app.use(mockErrorHandler);
// This is the correct usage
app.use(mockErrorHandler());
3a7dad9: Updated better-sqlite3 to v12
Updated dependencies
38b4243: Added plugin and module templates for the new frontend system. These templates are not included by default, but can be included by adding @backstage/cli/templates/new-frontend-plugin and @backstage/cli/templates/new-frontend-plugin-module as custom templates.
923ceb2: BREAKING: The new app build based on Rspack is now the default, and the EXPERIMENTAL_RSPACK flag has been removed. To revert to the old behavior, set the LEGACY_WEBPACK_BUILD environment flag and install the following optional dependencies:
{
"dependencies": {
"@module-federation/enhanced": "^0.9.0",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.7",
"esbuild-loader": "^4.0.0",
"eslint-webpack-plugin": "^4.2.0",
"fork-ts-checker-webpack-plugin": "^9.0.0",
"mini-css-extract-plugin": "^2.4.2",
"terser-webpack-plugin": "^5.1.3",
"webpack": "^5.96.0",
"webpack-dev-server": "^5.0.0"
}
}
If you do encounter a blocking issue that forces you to use the old WebPack build, please open an issue explaining the problem. The WebPack build will be removed in a future release.
eda80c7: BREAKING: Removed support for .icon.svg imports, which have been deprecated since the 1.19 release.
app.experimental.packages to just app.packages. The old config will continue working for the time being, but may be removed in a future release.@backstage/cli/config/nodeTransformHooks.mjs now supports the built-in type stripping in Node.js, which is enabled by default from v22.18.0.createLegacyApp to createLegacyAppRoot as it better refers to the purpose of the function.defaultPath override of convertLegacyPageExtension has been renamed to path, in order to align with the same update that was made to the PageBlueprint.ApiBlueprint.compatWrapper has been switched to use the new SwappableComponentsApi instead of the old ComponentsApi in its bridging to the old frontend system.RouterBlueprint and AppRootWrapperBlueprint to use the lowercase component parameter8e21c4d: Use an app plugin for built-in extension app node specs.
df7bd3b: BREAKING: Removed the deprecated FrontendFeature type, import it from @backstage/frontend-plugin-api instead.
8e21c4d: The AppNodeSpec.plugin property is now required.
5e12252: BREAKING: Restructured some of option fields of createApp and createSpecializedApp.
createApp, all option fields except features and bindRoutes have been moved into a new advanced object field.createSpecializedApp, all option fields except features, config, and bindRoutes have been moved into a new advanced object field.This helps highlight that some options are meant to rarely be needed or used, and simplifies the usage of those options that are almost always required.
As an example, if you used to supply a custom config loader, you would update your code as follows:
createApp({
features: [...],
- configLoader: new MyCustomLoader(),
+ advanced: {
+ configLoader: new MyCustomLoader(),
+ },
})
d9e00e3: Add support for a new aliasFor option for createRouteRef. This allows for the creation of a new route ref that acts as an alias for an existing route ref that is installed in the app. This is particularly useful when creating modules that override existing plugin pages, without referring to the existing plugin. For example:
export default createFrontendModule({
pluginId: 'catalog',
extensions: [
PageBlueprint.make({
params: {
defaultPath: '/catalog',
routeRef: createRouteRef({ aliasFor: 'catalog.catalogIndex' }),
loader: () =>
import('./CustomCatalogIndexPage').then(m => (
<m.CustomCatalogIndexPage />
)),
},
}),
],
});
f2f133c: Internal update to use the new variant of ApiBlueprint.
ef54427: Internal cleanup of routing system data.
391f0ca: External route references are no longer required to be exported via a plugin instance to function. The default target will still be resolved even if the external route reference is not included in externalRoutes of a plugin, but users of the plugin will not be able to configure the target of the route. This is particularly useful when building modules or overrides for existing plugins, allowing you add external routes both within and out from the plugin.
f3f9d57: Renaming the getNodesByRoutePath parameter from sourcePath to routePath
8b1bf6e: Deprecated new frontend system config setting app.experimental.packages to just app.packages. The old config will continue working for the time being, but may be removed in a future release.
fda1bbc: Added a default implementation of the SwappableComponentsApi and removing the legacy ComponentsApi implementation
1c2cc37: Improved runtime error message clarity when extension factories don't return an iterable object.
3d2499f: Moved createSpecializedApp options to a new CreateSpecializedAppOptions type.
Updated dependencies
76832a9: BREAKING: Removed the deprecated CreateAppFeatureLoader and support for it in other APIs. Switch existing usage to use the newer createFrontendFeatureLoader from @backstage/frontend-plugin-api instead.
5e12252: BREAKING: Restructured some of option fields of createApp and createSpecializedApp.
createApp, all option fields except features and bindRoutes have been moved into a new advanced object field.createSpecializedApp, all option fields except features, config, and bindRoutes have been moved into a new advanced object field.This helps highlight that some options are meant to rarely be needed or used, and simplifies the usage of those options that are almost always required.
As an example, if you used to supply a custom config loader, you would update your code as follows:
createApp({
features: [...],
- configLoader: new MyCustomLoader(),
+ advanced: {
+ configLoader: new MyCustomLoader(),
+ },
})
createPublicSignInApp, which has been replaced by the new appModulePublicSignIn from @backstage/plugin-app/alpha instead.app.experimental.packages to just app.packages. The old config will continue working for the time being, but may be removed in a future release.allowUnknownExtensionConfig as a flagloadingComponent option has been renamed to loadingElement, which is now found under advanced.loadingElement. The default loading element has also been switched to <Progress /> from @backstage/core-components. This is of course an improvement over the previous "Loading..." text, but also helps prevent flicker when the app loading is fast.c5f88b5: BREAKING: Remove deprecated source property from the AppNodeSpec type, use AppNodeSpec.plugin instead.
e4ddf22: BREAKING: The defaultPath param of PageBlueprint has been renamed to path. This change does not affect the compatibility of extensions created with older versions of this blueprint.
fda1bbc: BREAKING: The component system has been overhauled to use SwappableComponent instead of ComponentRef. Several APIs have been removed and replaced:
createComponentRef, createComponentExtension, ComponentRef, ComponentsApi, componentsApiRef, useComponentRef, coreComponentRefscreateSwappableComponent, SwappableComponentBlueprint, SwappableComponentRef, SwappableComponentsApi, swappableComponentsApiRefBREAKING: The default componentRefs and exported Core*Props have been removed and have replacement SwappableComponents and revised type names instead.
errorBoundaryFallback component and CoreErrorBoundaryFallbackProps type have been replaced with ErrorDisplay swappable component and CoreErrorDisplayProps respectively.progress component and CoreProgressProps type have been replaced with Progress swappable component and ProgressProps respectively.notFoundErrorPage component and CoreNotFoundErrorPageProps type have been replaced with NotFoundErrorPage swappable component and NotFoundErrorPageProps respectively.Migration for creating swappable components:
// OLD: Using createComponentRef and createComponentExtension
import {
createComponentRef,
createComponentExtension,
} from '@backstage/frontend-plugin-api';
const myComponentRef = createComponentRef<{ title: string }>({
id: 'my-plugin.my-component',
});
const myComponentExtension = createComponentExtension({
ref: myComponentRef,
loader: {
lazy: () => import('./MyComponent').then(m => m.MyComponent),
},
});
// NEW: Using createSwappableComponent and SwappableComponentBlueprint
import {
createSwappableComponent,
SwappableComponentBlueprint,
} from '@backstage/frontend-plugin-api';
const MySwappableComponent = createSwappableComponent({
id: 'my-plugin.my-component',
loader: () => import('./MyComponent').then(m => m.MyComponent),
});
const myComponentExtension = SwappableComponentBlueprint.make({
name: 'my-component',
params: {
component: MySwappableComponent,
loader: () => import('./MyComponent').then(m => m.MyComponent),
},
});
Migration for using components:
// OLD: Using ComponentsApi and useComponentRef
import {
useComponentRef,
componentsApiRef,
useApi,
coreComponentRefs,
} from '@backstage/frontend-plugin-api';
const MyComponent = useComponentRef(myComponentRef);
const ProgressComponent = useComponentRef(coreComponentRefs.progress);
// NEW: Direct component usage import { Progress } from '@backstage/frontend-plugin-api';
// Use directly as React Component <Progress /> <MySwappableComponent title="Hello World" />
**Migration for core component references:**
```tsx
// OLD: Core component refs
import { coreComponentRefs } from '@backstage/frontend-plugin-api';
coreComponentRefs.progress
coreComponentRefs.notFoundErrorPage
coreComponentRefs.errorBoundaryFallback
// NEW: Direct swappable component imports
import { Progress, NotFoundErrorPage, ErrorDisplay } from '@backstage/frontend-plugin-api';
// Use directly as React components
<Progress />
<NotFoundErrorPage />
<ErrorDisplay plugin={plugin} error={error} resetError={resetError} />
6a75e00: BREAKING: Removed the deprecated createFrontendPlugin variant where the plugin ID is passed via an id option. To update existing code, switch to using the pluginId option instead.
12b6db7: BREAKING: Added a new OverridableFrontendPlugin type that is used as the return value of createFrontendPlugin. This type includes the withOverrides and .getExtension methods that are helpful when creating plugin overrides, while the base FrontendPlugin type no longer includes these methods. This is a breaking change for the AppTreeApi and some other places where the FrontendPlugin type is still used, but also fixes some cases where the extra plugin methods were causing issues.
37f2989: BREAKING: Removed the routable property from ExtensionBoundary. This property was never needed in practice and is instead inferred from whether or not the extension outputs a route reference. It can be safely removed.
1e6410b: BREAKING: The ResolveInputValueOverrides type is no longer exported.
29786f6: BREAKING: The NavLogoBlueprint has been removed and replaced by NavContentBlueprint, which instead replaces the entire navbar. The default navbar has also been switched to a more minimal implementation.
To use NavContentBlueprint to install new logos, you can use it as follows:
NavContentBlueprint.make({
params: {
component: ({ items }) => {
return compatWrapper(
<Sidebar>
<SidebarLogo />
<SidebarScrollWrapper>
{items.map((item, index) => (
<SidebarItem {...item} key={index} />
))}
</SidebarScrollWrapper>
</Sidebar>,
);
},
},
});
3243fa6: BREAKING: Removed the ability to define a default extension name in blueprints. This option had no practical purpose as blueprints already use the kind to identity the source of the extension.
a082429: BREAKING: The separate RouteResolutionApiResolveOptions type has been removed.
5d31d66: BREAKING: In an attempt to align some of the API's around providing components to Blueprints, we've renamed the parameters for both the RouterBlueprint and AppRootWrapperBlueprint from Component to component.
// old
RouterBlueprint.make({
params: {
Component: ({ children }) => <div>{children}</div>,
},
});
// new
RouterBlueprint.make({
params: {
component: ({ children }) => <div>{children}</div>,
},
});
// old
AppRootWrapperBlueprint.make({
params: {
Component: ({ children }) => <div>{children}</div>,
},
});
// new
AppRootWrapperBlueprint.make({
params: {
component: ({ children }) => <div>{children}</div>,
},
});
As part of this change, the type for component has also changed from ComponentType<PropsWithChildren<{}>> to (props: { children: ReactNode }) => JSX.Element | null which is not breaking, just a little more reflective of the actual expected component.
45ead4a: BREAKING: The AnyRoutes and AnyExternalRoutes types have been removed and their usage has been inlined instead.
Existing usage can be replaced according to their previous definitions:
type AnyRoutes = { [name in string]: RouteRef | SubRouteRef };
type AnyExternalRoutes = { [name in string]: ExternalRouteRef };
805c298: BREAKING: The ApiBlueprint has been updated to use the new advanced type parameters through the new defineParams blueprint option. This is an immediate breaking change that requires all existing usages of ApiBlueprint to switch to the new callback format. Existing extensions created with the old format are still compatible with the latest version of the plugin API however, meaning that this does not break existing plugins.
To update existing usages of ApiBlueprint, you remove the outer level of the params object and replace createApiFactory(...) with defineParams => defineParams(...).
For example, the following old usage:
ApiBlueprint.make({
name: 'error',
params: {
factory: createApiFactory({
api: errorApiRef,
deps: { alertApi: alertApiRef },
factory: ({ alertApi }) => {
return ...;
},
})
},
})
is migrated to the following:
ApiBlueprint.make({
name: 'error',
params: defineParams =>
defineParams({
api: errorApiRef,
deps: { alertApi: alertApiRef },
factory: ({ alertApi }) => {
return ...;
},
}),
})
805c298: Added support for advanced parameter types in extension blueprints. The primary purpose of this is to allow extension authors to use type inference in the definition of the blueprint parameters. This often removes the need for extra imports and improves discoverability of blueprint parameters.
This feature is introduced through the new defineParams option of createExtensionBlueprint, along with accompanying createExtensionBlueprintParams function to help implement the new format.
The following is an example of how to create an extension blueprint that uses the new option:
const ExampleBlueprint = createExtensionBlueprint({
kind: 'example',
attachTo: { id: 'example', input: 'example' },
output: [exampleComponentDataRef, exampleFetcherDataRef],
defineParams<T>(params: {
component(props: ExampleProps<T>): JSX.Element | null;
fetcher(options: FetchOptions): Promise<FetchResult<T>>;
}) {
// The returned params must be wrapped with `createExtensionBlueprintParams`
return createExtensionBlueprintParams(params);
},
*factory(params) {
// These params are now inferred
yield exampleComponentDataRef(params.component);
yield exampleFetcherDataRef(params.fetcher);
},
});
Usage of the above example looks as follows:
const example = ExampleBlueprint.make({
params: defineParams => defineParams({
component: ...,
fetcher: ...,
}),
});
This defineParams => defineParams(<params>) is also known as the "callback syntax" and is required if a blueprint is created with the new defineParams option. The callback syntax can also optionally be used for other blueprints too, which means that it is not a breaking change to remove the defineParams option, as long as the external parameter types remain compatible.
121899a: BREAKING: The element param for AppRootElementBlueprint no longer accepts a component. If you are currently passing a component such as element: () => <MyComponent /> or element: MyComponent, simply switch to element: <MyComponent />.
a321f3b: BREAKING: The CommonAnalyticsContext has been removed, and inlined into AnalyticsContextValue instead.
d9e00e3: Add support for a new aliasFor option for createRouteRef. This allows for the creation of a new route ref that acts as an alias for an existing route ref that is installed in the app. This is particularly useful when creating modules that override existing plugin pages, without referring to the existing plugin. For example:
export default createFrontendModule({
pluginId: 'catalog',
extensions: [
PageBlueprint.make({
params: {
defaultPath: '/catalog',
routeRef: createRouteRef({ aliasFor: 'catalog.catalogIndex' }),
loader: () =>
import('./CustomCatalogIndexPage').then(m => (
<m.CustomCatalogIndexPage />
)),
},
}),
],
});
93b5e38: Plugins should now use the new AnalyticsImplementationBlueprint to define and provide concrete analytics implementations. For example:
import { AnalyticsImplementationBlueprint } from '@backstage/frontend-plugin-api';
const AcmeAnalytics = AnalyticsImplementationBlueprint.make({
name: 'acme-analytics',
params: define =>
define({
deps: { config: configApiRef },
factory: ({ config }) => AcmeAnalyticsImpl.fromConfig(config),
}),
});
948de17: Tweaked the return types from createExtension and createExtensionBlueprint to avoid the forwarding of ConfigurableExtensionDataRef into exported types.
147482b: Updated the recommended naming of the blueprint param callback from define to defineParams, making the syntax defineParams => defineParams(...).
3c3c882: Added added defaults for all type parameters of ExtensionDataRef and deprecated AnyExtensionDataRef, as it is now redundant.
9831f4e: Adjusted the dialog API types to have more sensible defaults
1c2cc37: Improved runtime error message clarity when extension factories don't return an iterable object.
24558f0: Added inline documentation for createExtension, createExtensionBlueprint, createFrontendPlugin, and createFrontendModule.
Updated dependencies
Text component to support all font sizes making the Heading component redundant. The new Text component introduces 4 sizes for title and 4 sizes for body text. All of these work in multiple colors and font weights. We improved the as prop to include all possible values. The Link component has also been updated to match the new Text component.HeaderPage instead of the Header in Backstage UI.motion to use gsap instead to make Backstage UI backward compatible with React 17.startCollapsed prop on the SearchField component in BUI.fda1bbc: BREAKING: The componentsApi implementation has been removed from the plugin and replaced with the new SwappableComponentsApi instead.
If you were overriding the componentsApi implementation, you can now use the new SwappableComponentsApi instead.
// old
appPlugin.getExtension('api:app/components').override(...)
// new
appPlugin.getExtension('api:app/swappable-components').override(...)
29786f6: Updated the app/nav extension to use the new NavContentBlueprint, and removed support for extensions created with the now removed NavLogoBlueprint.
121899a: BREAKING: The app-root-element extension now only accepts JSX.Element in its element param, meaning overrides need to be updated.
91cbdf4: Log a warning when SwappableComponent extensions are installed outside of using the app plugin
fda1bbc: Default implementations of core components are now provided by this package.
A backwards compatible componentsApi implementation is also provided from this package which uses the SwappableComponentsApi as the implementation. This backwards compatible wrapper will be removed in the future.
f2f133c: Internal update to use the new variant of ApiBlueprint.
a08f95f: Added a new module for implementing public sign-in apps, exported as appModulePublicSignIn via the /alpha sub-path export. This replaces the createPublicSignInApp export from @backstage/frontend-defaults, which is now deprecated.
5d31d66: Updated the usage of the RouterBlueprint and AppRootWrapperBlueprint to use the lowercase component parameter
93b5e38: The default implementation of the Analytics API now collects and instantiates analytics implementations exposed via AnalyticsImplementationBlueprint extensions. If no such extensions are discovered, the API continues to do nothing with analytics events fired within Backstage. If multiple such extensions are discovered, every discovered implementation automatically receives analytics events.
9831f4e: Adjusted the dialog API types to have more sensible defaults
Updated dependencies
analyzeLocation method to catalogApiMockdefaultPath, defaultTitle, and defaultGroup params of PageBlueprint has been renamed to path, title, and group. The convertLegacyEntityContentExtension utility has also received the same change. This change does not affect the compatibility of extensions created with older versions of this blueprint.filter parameter on the EntityHeaderBlueprinttype as an override to the convertLegacyEntityCardExtensionqueryparams if pagination mode is set to none759568d: BREAKING CHANGE: Removed support for the legacy backend system. This means that the deprecated createRouter and KubernetesBuilder and related types have been removed. Please refer to the relevant documentation to configure the Kubernetes plugin.
BREAKING CHANGE: The deprecated types AuthenticationStrategy, AuthMetadata, ClusterDetails, CustomResource, CustomResourcesByEntity, FetchResponseWrapper, KubernetesBuilder, KubernetesBuilderReturn, KubernetesClustersSupplier, KubernetesCredential, KubernetesEnvironment, KubernetesFetcher, KubernetesObjectsProvider, KubernetesObjectTypes, KubernetesServiceLocator,ObjectFetchParams, ObjectToFetch,RouterOptions and ServiceLocatorRequestContext should all now be imported from @backstage/plugin-kubernetes-node.
loggerToWinstonLogger from @backstage/backend-common.metadata field to NotificationPayload. Metadata can be used to store additional unstructured data for the notification and are available to use by processors.ApiBlueprint.FormField type from /alpha in -react package, and internal refactor.getResources method to permissionIntegrationRouter for frontend task permission checksSPLAT twice in logs4f99e10: DEPRECATION: The following types have been deprecated from this package and moved into @backstage/plugin-scaffolder-common and should be imported from there instead.
Action, ListActionsResponse, LogEvent, ScaffolderApi, ScaffolderDryRunOptions, ScaffolderDryRunResponse, ScaffolderGetIntegrationsListOptions, ScaffolderGetIntegrationsListResponse,
ScaffolderOutputLink, ScaffolderOutputText, ScaffolderScaffoldOptions, ScaffolderScaffoldResponse, ScaffolderStreamLogsOptions, ScaffolderTask, ScaffolderTaskOutput, ScaffolderTaskStatus,
ScaffolderUsageExample, TemplateFilter, TemplateGlobalFunction, TemplateGlobalValue, TemplateParameterSchema.
c08cbc4: Move Scaffolder API to OpenAPI
ApiBlueprint.FormField type from /alpha in -react package, and internal refactor.additionalAllowedURIProtocols to sanitizer configApiBlueprint.get and keys methods to Lockfile classlinkifyjs to 4.3.2.FavoriteToggleProps.d7a3d04: Created a flag for scaffolding apps using the new frontend system.
4704160: Bumped create-app version.
1e8a013: Bumped create-app version.
e33fce1: Added Notifications and Signals to be installed by default
8b1bf6e: Updated the app.packages config setting now that it no longer is experimental
2a156e0: Updated the better-sqlite dependency from v9.0.0 to v13.0.0. You can apply this change to your instance by applying the following change to your packages/backend/package.json and running yarn install.
"dependencies": {
"app": "link:../app",
- "better-sqlite3": "^9.0.0",
+ "better-sqlite3": "^12.0.0",
"node-gyp": "^10.0.0",
"pg": "^8.11.3"
}
FrontendFeature type.RouterBlueprint and AppRootWrapperBlueprint to use the lowercase component parameterpackages/canon package for knip reports.stringEnums to mustache templatesbody to support Backstage UI (BUI) new theming system.ApiBlueprint.@davidzemon/passport-okta-oauth to ^0.0.7.ApiBlueprint.1752be6: Attempt to circumvent event listener memory leak in compression middleware
9658703: Sort built-in relation fields for more stable entity hash in the processing engine
9dd213c: Make the processing hash calculation not care about the order of the processors.
This change does not affect the behavior of the catalog, but it will make the processing hash calculation more robust against changes in the order of processors. This should lead to more stable processing hashes, which in turn should lead to fewer unnecessary reprocessing of entities.
After deploying this fix, you may see a period of increased processing and stitching, but this should stabilize over time as the processing hashes become more consistent.
fa6fa60: Fixed getLocationByEntity to use original_value instead of value when querying search table
3a7dad9: Updated better-sqlite3 to v12
Updated dependencies
host should be optional in config schemaauthProvider and owner to be set for the GKE cluster entities.ApiBlueprint.ApiBlueprint.ApiBlueprint.ApiBlueprint.app-root-element extension now only accepts JSX.Element in its element param, meaning overrides need to be updated.clearAll did not respect the deletable flag on widgetsApiBlueprint.e4ddf22: Internal update to align with new blueprint parameter naming in the new frontend system.
f2f133c: Internal update to use the new variant of ApiBlueprint.
5a70981: Fix duplicate notification origins with multiple channels
8a24e0f: Improve customization of the notification snackbar.
Users can now customize the notification snackbar by providing custom components and icons for different severity levels. Additionally, the location of the snackbar notifications can be modified, the density of the snackbar can be changed, and the number of snacks can be limited.
Updated dependencies
metadata field to NotificationPayload. Metadata can be used to store additional unstructured data for the notification and are available to use by processors.overridableComponents.customProperties type which was preventing it being used to set a list of values against a key (e.g. for multi-select fields)description property in publish:gitlab:merge-request has been made optional again to comply with the GitLab API.ApiBlueprint.@backstage-community/plugin-explore-common to ^0.5.0.ApiBlueprint.app-root-element extension now only accepts JSX.Element in its element param, meaning overrides need to be updated.