docs/releases/v1.36.0-changelog.md
Upgrade Helper: https://backstage.github.io/upgrade-helper/?to=1.36.0
featureDiscoveryServiceFactory. Existing usage can be replaced with discoveryFeatureLoader from @backstage/backend-defaults.ad9aba2: The log message written when plugins fail to initialize now includes the error that caused the plugin startup to fail.
5622362: Added a configuration to permit backend plugin failures on startup:
backend:
...
startup:
plugins:
plugin-x:
onPluginBootFailure: continue
This configuration permits plugin-x to fail on startup. Omitting the
onPluginBootFailure configuration matches the previous behavior, wherein any
individual plugin failure aborts backend startup.
The default can also be changed, so that continuing on failure is the default unless otherwise specified:
backend:
startup:
default:
onPluginBootFailure: continue
plugins:
catalog:
onPluginBootFailure: abort
Updated dependencies
auditor service implementation details.require for lazy-loading dependency.FeatureDiscoveryService from @backstage/backend-plugin-api.PermissionsRegistryService.etag or If-Modified-Since headers for gitlab artifact urlsUrlReadersService, the search method have been updated to use the readUrl if the given URL doesn't contain a pattern.
For UrlReaders that didn't implement the search method, readUrl is now called internally and throws if the given URL doesn't contain a pattern.PermissionsRegistryService to use PermissionResourceRefs and added the getPermissionRuleset method.dynamicPluginsFeatureDiscoveryServiceFactory.700d32b: BREAKING: The wrapInOpenApiTestServer and wrapServer functions are now exported via /testUtils subpath. If you were importing these functions directly from the root of the package, you will need to update your imports to use the /testUtils subpath:
- import { wrapInOpenApiTestServer } from '@backstage/backend-openapi-utils';
+ import { wrapInOpenApiTestServer } from '@backstage/backend-openapi-utils/testUtils';
or
- import { wrapServer } from '@backstage/backend-openapi-utils';
+ import { wrapServer } from '@backstage/backend-openapi-utils/testUtils';
featureDiscoveryServiceRef and FeatureDiscoveryService.auditor service definition.PermissionsRegistryService that is used by plugins to register permissions, resource types, and rules into the permission system. This replaces the existing createPermissionIntegrationRouter from @backstage/plugin-permission-node.PermissionsRegistryService to use PermissionResourceRefs and added the getPermissionRuleset method.PermissionsRegistryService.auditor service.require for lazy-loading dependency.@backstage/backend-app-api.getPermissionRuleset method to mockServices.permissionsRegistry.cb76663: BREAKING: Add support for native ESM in Node.js code. This changes the behavior of dynamic import expressions in Node.js code. Typically this can be fixed by replacing import(...) with require(...), with an as typeof import(...) cast if needed for types. This is because dynamic imports will no longer be transformed to require(...) calls, but instead be left as-is. This in turn allows you to load ESM modules from CommonJS code using import(...).
This change adds support for the following in Node.js packages, across type checking, package builds, runtime transforms and Jest tests:
.mjs and .mts files as explicit ESM files, as well as .cjs and .cts as explicit CommonJS files."type": "module" field in package.json to indicate that the package is an ESM package.There are a few caveats to be aware of:
--experimental-vm-modules flag enabled, typically via NODE_OPTIONS='--experimental-vm-modules'."type": "module" in package.json is supported, but in tests it will cause all local transitive dependencies to also be treated as ESM, regardless of whether they declare "type": "module" or not..cts or .cjs extension. This is because the interoperability layer is not fully compatible with the NPM ecosystem, and would break package if it was enabled for .js files.require, or to use the explicit CommonJS extensions as mentioned above. If you do need to dynamically import CommonJS packages, avoid using default exports, as the shape of them vary across different environments and you would otherwise need to manually unwrap the import based on the shape of the module object.b30e788: The new command is now powered by a new template system that allows you to define your own templates in a declarative way, as well as import existing templates from external sources. See the CLI templates documentation for more information.
The following flags for the new command have been deprecated and will be removed in a future release:
--license=<license>: Configure the global license instead.--no-private: Configure the global private instead.--baseVersion=<version>: Configure the global version instead.--npmRegistry=<url>: Configure the global publishRegistry instead.--scope=<scope>: Configure the global namePrefix and/or namePluginInfix instead.As part of this change the template IDs and their options have changed. The following backwards compatibility mappings for the --select and --option flags are enabled when using the default set of templates, but they will also be removed in the future:
--select=plugin is mapped to --select=frontend-plugin instead.--option=id=<id> is mapped to --option=pluginId=<id> instead.versions:bump command will now reject * as a pattern.build-workspace with the --alwaysYarnPack flag now respects the BACKSTAGE_CLI_BUILD_PARALLEL environment variable, defaulting parallel work limits based on CPU availability.--link option for the start command is a valid workspace.. before the extension, leading to names like image-af7946b..png..mjs in Jest transform if static ESM is supported.node-libs-browser with node-stdlib-browserpackage.json when using yarn new templatespackage-docs for generating API documentation. This is currently only intended for use in the Backstage main repository.api-reports command is now also able to generate SQL reports, enabled by the --sql-reports flag.auth.providers.<providerId>.sessionDuration config for auth providers to allow the lifespan of user sessions to be configured.auth.providers.<providerId>.sessionDuration config for auth providers to allow the lifespan of user sessions to be configured.auth.providers.<providerId>.sessionDuration config for auth providers to allow the lifespan of user sessions to be configured.auth.providers.<providerId>.sessionDuration config for auth providers to allow the lifespan of user sessions to be configured.auth.providers.<providerId>.sessionDuration config for auth providers to allow the lifespan of user sessions to be configured.auth.providers.<providerId>.sessionDuration config for auth providers to allow the lifespan of user sessions to be configured.auth.providers.<providerId>.sessionDuration config for auth providers to allow the lifespan of user sessions to be configured.auth.providers.<providerId>.sessionDuration config for auth providers to allow the lifespan of user sessions to be configured.b40af03: Fixed a bug where the requested scope was ignored when refreshing sessions for a GitHub OAuth App. This would lead to access tokens being returned that didn't have the requested scope, and in turn errors when trying to use these tokens.
As part of this fix all existing sessions are being revoked in order to ensure that they receive the correct scope.
Updated dependencies
auth.providers.<providerId>.sessionDuration config for auth providers to allow the lifespan of user sessions to be configured.auth.providers.<providerId>.sessionDuration config for auth providers to allow the lifespan of user sessions to be configured.auth.providers.<providerId>.sessionDuration config for auth providers to allow the lifespan of user sessions to be configured.auth.providers.<providerId>.sessionDuration config for auth providers to allow the lifespan of user sessions to be configured.auth.providers.<providerId>.sessionDuration config for auth providers to allow the lifespan of user sessions to be configured.start method in the authenticator to just return the helper promiseauth.providers.<providerId>.sessionDuration config for auth providers to allow the lifespan of user sessions to be configured.auth.providers.<providerId>.sessionDuration config for auth providers to allow the lifespan of user sessions to be configured.auth.providers.<providerId>.sessionDuration config for auth providers to allow the lifespan of user sessions to be configured.auth.providers.<providerId>.sessionDuration config for auth providers to allow the lifespan of user sessions to be configured.auth.providers.<providerId>.sessionDuration config for auth providers to allow the lifespan of user sessions to be configured.error handler to the strategy to reject the executeRedirectStrategyscopeAlreadyGranted property to OAuthAuthenticatorRefreshInput, signaling to the provider whether the requested scope has already been granted when persisting session scope.9b9737c: Added support for emitting entities with an explicit location key during processing.
8805f93: The catalog backend now supports the new PermissionsRegistryService, which can be used to add custom permission rules.
5aebc13: The UrlReaderProccessor accepts a new config flag catalog.useUrlReadersSearch to always call the search method of UrlReaders.
This flag currently defaults to false, but adopters are encouraged to enable it as this behavior will be the default in a future release.
Previous behavior was to call the search method only if the parsed Git URL's filename contained a wildcard and use readUrl otherwise. UrlReaderService must implement this logic in the search method instead.
This allows each UrlReaderService implementation to check whether it's a search URL (that contains a wildcard pattern) or not using logic that is specific to each provider.
a4aa244: This change integrates the auditor service into the Catalog plugin.
refresh_state_references for entity processors and providers that are no longer in control of a refresh_state row for entitycatalogEntityPermissionResourceRef export via the /alpha sub-path.locationKey option to processingResult.entity(...).catalogPermissionExtensionPoint and related types, since the same functionality is now available via the new PermissionsRegistryService.TaskLogStream to take up all space in a running task, and also show the last line of the log by defaultonChange handler when using GitLab autocompletemakeFieldSchema function returnoneOf output schemas on the Installed Actions page for scaffolder actionsdc8dd4b: Added new createTemplateFilter, createTemplateGlobalFunction, createTemplateGlobalValue for template extensions.
a4aa244: This change integrates the auditor service into the Scaffolder plugin.
3d6ef79: Support file globbing in fs:delete
91f3313: Added experimental flag for scaffolder to wait for running tasks to complete on shutdown
Enabling the EXPERIMENTAL_gracefulShutdown flag in the scaffolder config will make the
scaffolder block the shutdown process until all running tasks have completed. This is useful
when there is a need to ensure that all tasks have completed before the scaffolder is shut down.
Please note, that the TaskWorker stop method is now asynchronous and awaited for the
tasks to complete when the experimental flag is enabled.
step.each caused an error.oneOf output schemas on the Installed Actions page for scaffolder actionsremoteUrl output is no longer required, it can be empty only when using the new createWhenEmpty boolean flag.5c187f9: DEPRECATION: The getOctokitOptions function signature with repoUrl option has been deprecated in favour of a function signature with individual host, owner, and repo parameters:
const octokitOptions = await getOctokitOptions({
integrations,
credentialsProvider,
token,
- repoUrl,
+ host,
+ owner,
+ repo,
});
b98d511: clean up github action schemas
5d469c9: Added support for autocompletion of GitHub branches in scaffolder
8e67e4a: Added support for autocompletion to GithubRepoPicker component
Updated dependencies
createGitlabProjectMigrateAction can now output the migrationIdonChange handler when using GitLab autocompletecreateTemplateFilter, createTemplateGlobalFunction, createTemplateGlobalValue for template extensions.taskId property to TaskContext.type field to BackstagePackageJson type.require for lazy-loading dependency.nestedValuesAsYaml option to StructuredMetadataTable to render data as yaml.dagre to @dagrejs/dagreTaskLogStream to take up all space in a running task, and also show the last line of the log by default132173b: Bumped create-app version.
84fdc40: Bumped create-app version.
5aa499b: Bumped create-app version.
bfa4ea9: Enable catalog.useUrlReadersSearch configuration by default in newly created Backstage installations.
This parameter makes UrlReaderProcessor always use the search method.
New adopters are encouraged to enable it as this behavior will be the default in a future release.
Updated dependencies
getNodesByRoutePath method to the AppTreeApi.getNodesByRoutePath method to the AppTreeApi.GitlabOrgDiscoveryEntityProvider group path not being encoded causing 404 when using a subgroup in config.groupldapOrg config key optionalresolveUrl for split openapi definition relative pathPermissionsRegistryService instead of the deprecated catalogPermissionExtensionPoint.CatalogGraphCard to redraw its content whenever the parent component re-renders, resulting in flickering.aff6b47: feat: add cancel button for WidgetSettingsOverlay
8e86f96: Enable collision prevention by default in custom home page.
This change ensures that items in the home page will not collide with each other making the user experience better.
58ec9e7: Removed older versions of React packages as a preparatory step for upgrading to React 19. This commit does not introduce any functional changes, but removes dependencies on previous React versions, allowing for a cleaner upgrade path in subsequent commits.
Updated dependencies
/clusters endpoint is now protected by the kubernetes.clusters.read permission.
The /services/:serviceId endpoint is now protected by the kubernetes.resources.read permission.
The /resources endpoints are now protected by the kubernetes.resources.read permission.secrets to fetch from the kubernetes api by adding option to specify additional Objects which are not part of Default Objects/clusters endpoint is now protected by the kubernetes.clusters.read permission.
The /services/:serviceId endpoint is now protected by the kubernetes.resources.read permission.
The /resources endpoints are now protected by the kubernetes.resources.read permission./clusters endpoint is now protected by the kubernetes.clusters.read permission.
The /services/:serviceId endpoint is now protected by the kubernetes.resources.read permission.
The /resources endpoints are now protected by the kubernetes.resources.read permission.secrets to fetch from the kubernetes api by adding option to specify additional Objects which are not part of Default Objects/clusters endpoint is now protected by the kubernetes.clusters.read permission.
The /services/:serviceId endpoint is now protected by the kubernetes.resources.read permission.
The /resources endpoints are now protected by the kubernetes.resources.read permission.secrets to fetch from the kubernetes api by adding option to specify additional Objects which are not part of Default Objects/alpha export.spec.profile.displayName to be used in the MyGroupsSidebarItem component via the EntityDisplayName component when you are a member of multiple Groups.createPermissionIntegrationRouter is now mutable, allowing for permissions and resources to be added after creation of the router.PermissionRuleset type that encapsulates a lookup function for permission rules, which can be created by the new PermissionsRegistryService via the getPermissionRuleset method. The createConditionTransformer and createConditionAuthorizer functions have been adapted to receive these accessors as arguments, with their older counterparts being deprecated.createPermissionResourceRef utility that encapsulates the constants and types related to a permission resource types. The createConditionExports and createPermissionRule functions have also been adapted to accept these references as arguments, deprecating their older counterparts.immer from 8.0.4 to 9.0.6ajv and immer dependencies to @backstage/plugin-scaffolder-reactmakeFieldSchema function returnSearchFilterBlueprint and SearchFilterResultTypeBlueprintencodeURIComponent. This enhancement improves the safety and reliability of the URL.SearchFilterBlueprint and SearchFilterResultTypeBlueprint/alpha export.eb3d91a: Use the custom error page if provided for displaying errors instead of the default error page
524f0af: Add missing route ref to the /alpha entity content extension.
f4be934: Changed the base URL in addLinkClickListener from window.location.origin to app.baseUrl for improved path handling. This fixes an issue where Backstage, when running on a subpath, was unable to handle non-Backstage URLs of the same origin correctly.
1f40e6b: Add optional props to TechDocCustomHome to allow for more flexibility:
import { TechDocsCustomHome } from '@backstage/plugin-techdocs';
//...
const options = { emptyRowsWhenPaging: false };
const linkDestination = (entity: Entity): string | undefined => {
return entity.metadata.annotations?.['external-docs'];
};
const techDocsTabsConfig = [
{
label: 'Recommended Documentation',
panels: [
{
title: 'Golden Path',
description: 'Documentation about standards to follow',
panelType: 'DocsCardGrid',
panelProps: { CustomHeader: () => <ContentHeader title='Golden Path'/> },
filterPredicate: entity =>
entity?.metadata?.tags?.includes('golden-path') ?? false,
},
{
title: 'Recommended',
description: 'Useful documentation',
panelType: 'InfoCardGrid',
panelProps: {
CustomHeader: () => <ContentHeader title='Recommended' />
linkDestination: linkDestination,
},
filterPredicate: entity =>
entity?.metadata?.tags?.includes('recommended') ?? false,
},
],
},
{
label: 'Browse All',
panels: [
{
description: 'Browse all docs',
filterPredicate: filterEntity,
panelType: 'TechDocsIndexPage',
title: 'All',
panelProps: { PageWrapper: React.Fragment, CustomHeader: React.Fragment, options: options },
},
],
},
];
const AppRoutes = () => {
<FlatRoutes>
<Route
path="/docs"
element={
<TechDocsCustomHome
tabsConfig={techDocsTabsConfig}
filter={{
kind: ['Location', 'Resource', 'Component'],
'metadata.annotations.featured-docs': CATALOG_FILTER_EXISTS,
}}
CustomPageWrapper={({ children }: React.PropsWithChildren<{}>) => (<PageWithHeader title="Docs" themeId="documentation">{children}</PageWithHeader>)}
/>
}
/>
</FlatRoutes>;
};
Add new Grid option called InfoCardGrid which is a more customizable card option for the Docs grid.
<InfoCardGrid
entities={entities}
linkContent="Learn more"
linkDestination={entity => entity.metadata['external-docs']}
/>
Expose existing CustomDocsPanel so that it can be used independently if desired.
const panels: PanelConfig[] = [
{
description: '',
filterPredicate: entity => {},
panelType: 'InfoCardGrid',
title: 'Standards',
panelProps: {
CustomHeader: () => <ContentHeader title='Recommended' />
linkDestination: linkDestination,
},
},
{
description: '',
filterPredicate: entity => {},
panelType: 'DocsCardGrid',
title: 'Contribute',
},
];
{
panels.map((config, index) => (
<CustomDocsPanel
key={index}
config={config}
entities={!!entities ? entities : []}
index={index}
/>
));
}
58ec9e7: Removed older versions of React packages as a preparatory step for upgrading to React 19. This commit does not introduce any functional changes, but removes dependencies on previous React versions, allowing for a cleaner upgrade path in subsequent commits.
Updated dependencies
syncEntityDocs that would cause the /sync endpoint to be continuously called if the request fails