v1.56.0
These are the release notes for the v1.56.0 release of Backstage.
A huge thanks to the whole team of maintainers and contributors as well as the amazing Backstage Community for the hard work in getting this release developed and done.
Highlights
BREAKING: Filter predicates must be objects at the root
The FilterPredicate type, its zod schemas, and parseFilterPredicate in @backstage/filter-predicates now only accept objects at the root of a predicate. Primitive values such as "component" or true were previously accepted at the root, but no API that accepts filter predicates could match them in a meaningful way. Primitive values are still allowed as values to match against properties, and as the operand of $contains to match arrays of primitive values, for example { "metadata.tags": { "$contains": "java" } }.
A new AnyFilterPredicate type describes predicates that may also be primitive values at the root, equivalent to the previous FilterPredicate type. The catalog backend now rejects entity and location queries with a primitive root value with an "Invalid query" error.
BREAKING: Removed the Atlassian usernameMatchingUserEntityName sign-in resolver
The usernameMatchingUserEntityName sign-in resolver has been removed from @backstage/plugin-auth-backend-module-atlassian-provider, along with the atlassianSignInResolvers export that only contained it. Atlassian user profiles do not contain a username, so the resolver could never work. Use the emailMatchingUserEntityProfileEmail or emailLocalPartMatchingUserEntityName resolvers instead.
BREAKING PRODUCERS: Backend instance IDs
The root instance metadata service now exposes an instance ID that is globally unique and stable for the lifetime of a running backend instance. Custom implementations and mocks of the service must now provide one. Each backend instance uses a random UUID by default, and you can supply your own through the new instanceId option of createBackend and createSpecializedBackend. The signals backend uses this ID to identify its event subscription, which lets deployments control how events fan out across instances.
BREAKING: Incremental ingestion mark table upsert
The ingestion_mark_entities table in @backstage/plugin-catalog-backend-module-incremental-ingestion has a new source_key column and a unique constraint, so ingestion marks are now written with a single native upsert. This significantly reduces the number of database round trips during ingestion. The table's ref column is renamed to entity_ref as part of this change, which means the migration cannot be applied as part of a rolling, zero-downtime upgrade.
Contributed by @Teo-ShaoWei in #35177
Catalog filters with predicate queries
EntityFilter in @backstage/plugin-catalog-react has a new getCatalogQuery method, which lets filters express their backend constraints as a filter predicate. This supports logical operators such as $any and $not, as well as matchers like $hasPrefix, which could not be expressed with getCatalogFilters. All built-in filters now implement it, and getCatalogFilters is deprecated. The EntityListProvider combines the predicates of all active filters into a single query, and the catalog export button and TechDocsPicker respect them too.
This requires a catalog backend from Backstage release 1.49 or later. Note that when not paginating, entities are now fetched using streamEntities instead of getEntities, so tests that mock getEntities for an EntityListProvider need to mock streamEntities instead. An EntityOrderFilter that orders by a field that some entities lack now excludes those entities, consistent with paginated mode. EntityTagFilter with multiple tags now requires all of them, and EntityUserFilter.starred matches full entity refs.
The InMemoryCatalogClient test utility in @backstage/catalog-client now matches entities the same way as the catalog backend, which may change the outcome of existing tests. For example, relation shorthand now works in query, and field keys are matched case-insensitively.
New CLI modules for catalog, scaffolder, and search
Three new CLI modules provide domain-oriented commands that talk directly to the corresponding plugin APIs:
@backstage/cli-module-catalog:catalog list,catalog get,catalog validate,catalog register,catalog unregister@backstage/cli-module-scaffolder:template list,template execute,template dry-run@backstage/cli-module-search:search,docs search
Commands that list results support --output human or --output json, along with --limit and --cursor for paging. catalog validate and template dry-run exit with a non-zero code when the input is invalid, making them a good fit for CI pipelines.
Contributed by @yangcao77 in #34952
TechDocs engine abstraction
TechDocs now has an engine abstraction layer that paves the way for documentation engines other than MkDocs. This introduces an --engine flag in the TechDocs CLI, an engine configuration map, a generator registry with support for the backstage.io/techdocs-engine annotation, an engine field in techdocs_metadata.json, and a serve:raw command. MkDocs remains the default with no change in behavior. The built-in generator is now registered as mkdocs, with techdocs kept as an alias, and serve:mkdocs and the --mkdocs-parameter-* flags now print deprecation warnings.
Contributed by @byan1197 in #35781
TechDocs improvements
TechDocs now uses the app's NotFoundErrorPage when documentation is missing, so any override you have provided is used there as well. Contributed by @brentswisher in #34523
A new withoutFeedbackLink option on the page:techdocs/reader and entity-content:techdocs extensions lets you hide the feedback button. Contributed by @benjidotsh in #35011
The TechDocs backend now registers a get-techdocs-metadata action with the actions registry, controlled by a new techdocs.actions.read permission. Contributed by @thenmozhi-loganathan in #33412
TechDocs addons now render in apps using the new frontend system, contributed by @GabDug in #35770. Addons also load in individual Suspense boundaries, content no longer flashes before styles load, and Material UI styles for addons work in module-federated apps.
Catalog backend reliability and performance
The catalog backend has received a number of reliability fixes for stitching. Successfully processed entities no longer remain unavailable if stitch scheduling is interrupted, pending stitching work is no longer lost when entities are deleted and re-added, and failing entities are retried with increasing delays. Non-positive stitching polling intervals and lease durations are now rejected at startup.
Entities no longer disappear from filtered and sorted catalog queries after a database error during stitching, since the final entity and its search index rows are now written together in one transaction. Contributed by @bitflicker64 in #35815
Orphan entity cleanup is faster and more stable on large PostgreSQL catalogs, large entity provider mutations and projected list reads now yield to the event loop, and LDAP organization ingestion is faster for large directories.
Database connection pool defaults
The backend no longer issues periodic per-plugin database keepalive queries by default, and the default minimum PostgreSQL and MySQL connection pool size is now zero. Idle connections can now be retired after the configured timeout, while explicitly configured pool minimums are preserved. Set backend.database.keepalive: true to keep the previous behavior.
Contributed by @hudsonb in #35366
Experimental connections service
Backends created with createBackend now provide the experimental connections service by default. Plugins and modules can declare connection dependencies using declareConnection and request the service via connectionsServiceRef, both from @backstage/backend-plugin-api/alpha. Test backends also provide the service.
Contributed by @neoreddog in #36050
Signals WebSocket authentication
The signals WebSocket endpoint now requires a valid user identity token. Connections without a token, with an invalid token, or with a service token are rejected, and unauthenticated guest connections are no longer accepted. On the frontend, the signals client now shares one WebSocket connection across simultaneous subscriptions, and does not connect when no identity token is available.
Contributed by @ciiay in #34898
Featured templates home page widget
The scaffolder plugin now provides a Featured Templates home page widget that displays templates tagged with a configurable catalog tag, defaulting to featured.
Contributed by @benjidotsh in #35572
Swappable user avatar
The org plugin now has a swappable UserAvatar component, used for user profile pictures across the org plugin.
Contributed by @nikolarAutodesk in #34748
Secure GitLab token actions
The gitlab:projectAccessToken:create and gitlab:projectDeployToken:create scaffolder actions have a new variableKey input. When provided, the generated token is stored directly as a masked GitLab CI/CD variable instead of being exposed in task outputs and checkpoint state. The raw token outputs are now deprecated when variableKey is not used.
Contributed by @djanickova in #35769
Backstage UI updates
Backstage UI has updated to React Aria Components 1.22.0. MenuSection no longer accepts disabledKeys, so move it to Menu or set isDisabled on the affected MenuItem components. Programmatic clicks on Checkbox and Switch labels no longer toggle their selection. Contributed by @Naycon in #36090
A new theme CSS cascade layer sits between components and utilities, giving apps a place for brand overrides that win over component styles without raising specificity. Contributed by @serahkiburu in #36138
Combobox keyboard selection while filtering has been fixed, contributed by @antony-bouyon in #35970. The --bui-bg-app token now follows the page's color-scheme until a theme mode is set, contributed by @carlerikjohan in #36165.
Check the BUI Changelog for more details.
Additional fixes and improvements
- Added
AppLifecycleApi, which lets you check whether the app has been finalized and subscribe to changes in its lifecycle.useRouteRefnow resolves routes again after finalization, so elements rendered before it, such asapp/root.elementsextensions, can link to pages. Contributed by @benjidotsh in #36008. - The permission check for extension
ifpredicates during app startup now retries network failures and 5xx responses for up to about 15 seconds, instead of failing the whole app. - Improved link resolution performance in the new frontend system by reusing route matches for recently visited locations.
- The catalog graph and catalog import pages in the new frontend system now use the page header provided by the app. Contributed by @denesbeck in #36067 and #36068.
- Fixed the catalog entity list rewriting the URL on every render, which crashed Safari with a
SecurityError. Contributed by @greym0uth in #34942. - The BUI entity header now shows entity titles in hierarchy links. Contributed by @ErikMinekus in #34958.
streamEntitiesno longer asks the catalog backend to compute the total number of matching items, and itstotalItemsoption is deprecated.- Fixed catalog processing error messages to report stable processor names in minified builds. Contributed by @vinzscam in #35760.
- Fixed the Gitea entity provider registering locations against a hardcoded
mainbranch instead of each repository's default branch. Contributed by @karthikchundi-commits in #35314. @backstage/catalog-modelnow uses version 4 ofzod. If your own packages usezodwithout declaring it as a dependency, make sure to add it to theirpackage.json.- Config schemas now compile in roughly half the time, which speeds up backend startup.
- Reading a number from an empty or whitespace-only config value now fails with a clear error instead of returning
0. Contributed by @suletetes in #35773. - Added a
backend.logger.redactAllowlistconfiguration option that lets specific secret values pass through log redaction. Contributed by @tcardonne in #35288. - Added bounded retries for transient Cloud SQL connection failures, and fixed AWS RDS IAM authentication tokens being reused after their signing credentials expire. Contributed by @hudsonb in #35863 and #35979.
- Added a service-authenticated action registry status endpoint that reports whether a plugin provides actions. Contributed by @jabrks in #35862.
- Fixed
serializeErrorto strip stack traces from all nested error causes. Contributed by @suletetes in #35777. - Improved database event cleanup in the events backend under large backlogs.
- Hardened return URL validation in the OAuth redirect flow.
- Google IAP public verification keys are now cached according to their cache headers. Contributed by @JbravoI in #35833.
- The
auth.providers.guestconfiguration is now visible to frontend plugins. Contributed by @JessicaJHee in #35766. - The selected sign-in provider is no longer cleared when a sign-in loader is cancelled. Contributed by @JessicaJHee in #36082.
- Fixed protected app sign-in returning a 404 when the sign-in handoff is repeated. Contributed by @hudsonb in #35583.
- Added a
defaultCloseDelayMsoption toSubmenuOptions. Contributed by @benjidotsh in #33896. - Fixed long words in toast notifications overlapping the close button. Contributed by @carlerikjohan in #36140.
- Migrated the DevTools
InfoContentcomponent to Backstage UI. Contributed by @alien2003 in #34078. - Azure DevOps repository files now resolve to an edit URL. Contributed by @JbravoI in #35813.
- Fixed Azure DevOps downloads to use the requested branch or tag. Contributed by @jroebu14 in #36164.
- Bitbucket Cloud OAuth tokens are now cached per set of client credentials. Contributed by @suletetes in #35775.
- Added Bitbucket Cloud support for bearer API tokens. Contributed by @sbaramov in #35568.
- Fixed importing
@backstage/integrationfrom ESM projects. publish:gitlabnow throws a clearConflictErrorwhen the target repository already exists. Contributed by @kai-hkihara in #34494.- Fixed a regression where scaffolder step values consisting of a single template statement block, such as
ifconditions, were rendered as strings instead of boolean values. Contributed by @beatleboy501 in #36178. - Notification payload metadata is now persisted and returned when reading notifications. Contributed by @noy-solvin in #34669.
- Updated
nodemailerto version 10 in the email notifications module. - Fixed Elasticsearch search queries intermittently failing when a collator finishes indexing. The previous index is now retained until the next indexing run, roughly doubling storage per document type. Contributed by @nandni-g in #36149.
- Fixed PostgreSQL search highlighting with delimiters that need quoting.
- Fixed TechDocs asset caching on reused HTTP connections.
- Fixed TechDocs rejecting
mkdocs.ymlfiles that use Material for MkDocs emoji and superfences configuration, and removedcustom_iconspaths that resolve outside the docs directory. Contributed by @GabDug in #35364. - Declared the per-cluster
assumeRoleandexternalIdoptions in the Kubernetes backend configuration schema. Contributed by @meganide in #35977. - The
actions listCLI command now returns partial results when some plugin sources fail. Contributed by @yangcao77 in #34771. - CLIs created with
runClinow show help when a command group is invoked without a subcommand, and wait for output to be flushed before exiting. Contributed by @iamEAP in #35940. - Added a
--fixmode tobackstage-cli pm verify-patches. - The ESLint configuration for
common-librarypackages now reports named imports fromlodash, which break ESM builds. - Fixed the
no-mixed-plugin-importslint rule silently reporting nothing in repositories checked out below a dot directory. - Several packages now work with strict
node_moduleslayouts. Contributed by @sebdanielsson in #36208. - Improved code splitting for frontend module federation remotes.
- Fixed root
setupFilesAfterEnvJest configuration being shared between workspace packages, and fixed CommonJS frontend tests with ESM dependencies on Node.js 24. - Report checks in
@backstage/repo-toolsnow show a diff when a report is out of date. - Updated the
plugin-web-librarytemplate to use@backstage/ui. Contributed by @gaelgoth in #34633. - Fixed the Home page path override in the
create-apptemplate. Contributed by @Sriram-Nambiar in #36057.
Security Fixes
This release does not contain any security fixes.
Contributors
Big shoutout to all of the amazing folks who contributed to this release: @04kash, @alien2003, @antony-bouyon, @beatleboy501, @benjidotsh, @bitflicker64, @brentswisher, @byan1197, @carlerikjohan, @ciiay, @denesbeck, @djanickova, @ErikMinekus, @evhnn29, @GabDug, @gaelgoth, @gashcrumb, @greym0uth, @hopehadfield, @hudsonb, @iamEAP, @jabrks, @JbravoI, @JessicaJHee, @jroebu14, @kai-hkihara, @karthikchundi-commits, @meganide, @nandni-g, @Naycon, @neoreddog, @nikolarAutodesk, @noy-solvin, @sbaramov, @sebdanielsson, @serahkiburu, @Sriram-Nambiar, @suletetes, @tcardonne, @Teo-ShaoWei, @thenmozhi-loganathan, @vinzscam, @yangcao77
Upgrade path
We recommend that you keep your Backstage project up to date with this latest release. For more guidance on how to upgrade, check out the documentation for keeping Backstage updated.
Links and References
Below you can find a list of links and references to help you learn about and start using this new release.
- Backstage official website, documentation, and getting started guide
- GitHub repository
- Backstage's versioning and support policy
- Community Discord for discussions and support
- Changelog
- Backstage Demos, Blog, Roadmap and Plugins
Sign up for our newsletter if you want to be informed about what is happening in the world of Backstage.