74233 Commits

Author SHA1 Message Date
Fredrik Adelöw 51c45e7ae3 Remove per-batch round trips for Postgres unnest migration
The Postgres unnest UPDATE uses a fixed-size SQL string; only the array
bindings grow. The planner executes it with an index nested-loop (O(N)),
so batching only adds network round trips without reducing work. Run the
entire backfill in a single statement.

MySQL keeps its MYSQL_BATCH_SIZE=1000 because the UNION ALL SQL text
grows linearly with batch size, so smaller packets are important there.

Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
2026-04-04 22:41:29 +02:00
Fredrik Adelöw b21576575d Use string column and stringifyEntityRef for location_entity_ref
Switch the migration column type from text to string (varchar(255)),
since entity refs are always short. Also use stringifyEntityRef in
computeLocationEntityRef to handle lowercasing canonically.

Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
2026-04-04 22:24:36 +02:00
Fredrik Adelöw d16311f310 catalog-backend: persist location_entity_ref in locations table
Adds a migration that populates a new `location_entity_ref` column on the
`locations` table with the full entity ref of the corresponding
`kind: Location` entity (e.g. `location:default/generated-<sha1hex>`).
Postgres uses an unnest-based batch UPDATE; other engines use a
transaction-wrapped per-row loop.

All code paths in DefaultLocationStore that previously recomputed the hash
from type+target now read `location_entity_ref` directly from the DB row
instead. New rows written by `createLocation` and `#createLocationsByExactUrl`
have the column populated at insert time.

This is step 1 of migrating Location entity names to be based on the stable
row UUID rather than a hash of the mutable target URL.

Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
2026-04-04 22:19:26 +02:00
Kurt King ea0d31a1bc Merge branch 'master' of https://github.com/backstage/backstage into migrate-google-pubsub-alpha-metrics 2026-04-04 13:33:39 -06:00
Fredrik Adelöw 98d9a75dc2 Merge pull request #33632 from wpessers/feat/github-catalog-backend-extensiont/add-retry-to-github-client
feat(catalog): add retries to octokit client
2026-04-04 17:20:22 +02:00
Patrik Oldsberg 7f6b88783b docs: address review feedback on route refs, typos, and installation steps
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
2026-04-04 16:15:01 +02:00
Fredrik Adelöw 323da94780 Use mockCredentials in CachedEntityLoader tests and simplify cache key
Replace hand-crafted BackstageCredentials objects with mockCredentials
from @backstage/backend-test-utils, which have proper toString() methods.
Simplify getCacheKey to use String(credentials) directly and remove the
auth service dependency from CachedEntityLoader.

Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
2026-04-04 13:52:58 +02:00
Patrik Oldsberg fb571af4ee fix: correct broken doc links in search getting-started guides
Update links to removed how-to-guides anchors (#how-to-index-techdocs-documents
and #how-to-limit-what-can-be-searched-in-the-software-catalog) to point to the
existing #how-to-customize-fields-in-the-software-catalog-or-techdocs-index
anchor instead. Also update the old frontend system guide to link to the
--old variants of how-to-guides.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
2026-04-04 12:47:25 +02:00
Patrik Oldsberg 18fde07e06 docs: address review feedback on code style in examples
Replace `Promise.resolve(...)` with `async` functions in scaffolder
FormFieldBlueprint.make examples, and switch the TechDocs custom home
page example to use the `plugin.withOverrides` pattern instead of
`createFrontendModule`.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
2026-04-04 12:34:50 +02:00
Patrik Oldsberg 67fcc5a689 scaffolder: sync selected action with URL hash
Reflect the currently selected action in the URL hash so that users can
deep-link to a specific action on the actions page. On load the hash is
read to pre-select and scroll to the matching action.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
2026-04-04 11:28:47 +02:00
Fredrik Adelöw e7fdf2997f Address Copilot review: fix pagination test and add credentials assertion
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
2026-04-03 23:23:42 +02:00
Fredrik Adelöw 999f308ad5 Call getOwnServiceCredentials per request, not once per loop
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
2026-04-03 23:06:47 +02:00
Fredrik Adelöw 52a45c308b Address review feedback
- Move getOwnServiceCredentials() before the pagination loop in DefaultTechDocsCollatorFactory
- Fix stale test comment that referenced the deleted MSW /entities handler

Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
2026-04-03 23:05:02 +02:00
Fredrik Adelöw 7d9d185654 Inline catalog from options directly in createRouter
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
2026-04-03 22:58:20 +02:00
Fredrik Adelöw da3f5356ec Rename router catalogClient options to catalog and make mandatory
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
2026-04-03 22:57:23 +02:00
Fredrik Adelöw 3588c3f57f Make TechDocsCollatorFactoryOptions.catalog required
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
2026-04-03 22:55:36 +02:00
Fredrik Adelöw 31b6cc68b6 Rename TechDocsCollatorFactoryOptions.catalogClient to .catalog
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
2026-04-03 22:54:57 +02:00
Fredrik Adelöw 5e32f77884 Migrate techdocs plugins from alpha catalogServiceRef to stable
Migrated `@backstage/plugin-techdocs-backend` and
`@backstage/plugin-search-backend-module-techdocs` to use the stable
`catalogServiceRef` from `@backstage/plugin-catalog-node` instead of
the deprecated one from `@backstage/plugin-catalog-node/alpha`.

This also updates `CachedEntityLoader`, `DefaultTechDocsCollatorFactory`,
and the TechDocs router to use `CatalogService` (credentials-based) instead
of `CatalogApi` (token-based).

Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
2026-04-03 22:53:27 +02:00
Fredrik Adelöw c59dccbaf5 Merge pull request #33745 from backstage/freben/permissions-cleanup-step-2
refactor(catalog-node,catalog-backend): permissions cleanup step 2
2026-04-03 22:15:57 +02:00
Charles de Dreuille d10fbd3e29 Merge pull request #33744 from backstage/bui-badge 2026-04-03 20:40:08 +01:00
Fredrik Adelöw 056e18e4bf refactor(catalog-node,catalog-backend): permissions cleanup step 2
Remove the deprecated alpha exports CatalogPermissionRuleInput,
CatalogPermissionExtensionPoint, and catalogPermissionExtensionPoint
from catalog-node, and remove the corresponding CatalogPermissionExtensionPointImpl,
addPermissions, and addPermissionRules from catalog-backend. Custom permission
rules and permissions are now registered via coreServices.permissionsRegistry.

Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
2026-04-03 21:36:46 +02:00
Patrik Oldsberg 205c8c8dc1 Merge pull request #33714 from backstage/rugvip/dev-db
cli: experimental embedded-postgres support for local dev
2026-04-03 21:07:15 +02:00
Andre Wanlin 735af5b2d6 Merge pull request #33421 from awanlin/docs/clean-up-items
Clean up of the contrib folder
2026-04-03 12:53:38 -05:00
Andre Wanlin 8bf97618ee Fixed links
Signed-off-by: Andre Wanlin <awanlin@spotify.com>
2026-04-03 12:39:28 -05:00
Andre Wanlin e66fa1898c Sidebar fix
Signed-off-by: Andre Wanlin <awanlin@spotify.com>
2026-04-03 12:30:40 -05:00
Andre Wanlin 6e6eff9b90 Fixes
Signed-off-by: Andre Wanlin <awanlin@spotify.com>
2026-04-03 12:28:56 -05:00
Andre Wanlin 13c3c0ab15 Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com>
2026-04-03 12:28:56 -05:00
Andre Wanlin d42d56d62b Fixed broken link
Signed-off-by: Andre Wanlin <awanlin@spotify.com>
2026-04-03 12:28:56 -05:00
Andre Wanlin 5cbd39e980 Clean up of the contrib folder
Signed-off-by: Andre Wanlin <awanlin@spotify.com>
2026-04-03 12:28:53 -05:00
Patrik Oldsberg a4b9c45277 Merge pull request #33054 from StateFarmIns/theme-fix-mui-5-class-name-prefix
fix: MUI 5 v5- class name prefix reliability
2026-04-03 19:15:45 +02:00
Charles de Dreuille 4032ad7fc4 feat(ui): add Badge component
Adds a new `Badge` component to the Backstage UI library. Badge shares the same visual appearance as `Tag` (size tokens, colors, border radius, icon slot) but renders as a plain non-interactive `<span>` with no React Aria plumbing.

Key characteristics:
- Plain DOM element — accessible text content exposed to screen readers without any role override
- Background consumer — participates in the bg context system and steps up neutral background levels (`neutral-2` → `neutral-3` → `neutral-4`) when placed inside colored containers
- Supports `icon`, `size` (`small` | `medium`, defaults to `small`), `children`, and `className` props
- Fully themeable via `BadgeDefinition`

Also includes Storybook stories and full docs-ui documentation (props table, examples, theming section, changelog).

Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
Made-with: Cursor
2026-04-03 17:19:02 +01:00
Fredrik Adelöw 3dfb6ddc3c Merge pull request #33743 from backstage/freben/permissions-cleanup-step-1
refactor(catalog-backend): permissions cleanup step 1
2026-04-03 18:14:47 +02:00
Erik Miller f399a7acab feat(notifications-slack): add scope-based message update support
When a Backstage notification is re-sent with the same scope, the
notifications backend updates the existing DB record and sets
notification.updated. Previously, the SlackNotificationProcessor always
called chat.postMessage(), creating duplicate Slack messages.

This adds database-backed scope-based update support:

- New slack_message_timestamps table to persist Slack message ts values
  keyed by (scope, channel)
- After each chat.postMessage(), store the response ts in the database
- When postProcess receives a notification with updated set and a
  matching stored ts, use chat.update() instead of chat.postMessage()
- Scope context is passed as parameters through the call chain to avoid
  race conditions with concurrent postProcess calls
- Scheduled daily cleanup of old timestamp records (24h retention)
- New messagesUpdated metrics counter for observability
- Graceful degradation when no database is provided
- Explicitly picks only supported fields for chat.update calls

Signed-off-by: Erik Miller <erik.miller@gusto.com>
2026-04-03 09:03:18 -07:00
renovate[bot] e32a4cabb4 chore(deps): update dependency ws to v8.20.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-03 09:03:17 -07:00
renovate[bot] e92809bc90 chore(deps): update dependency react-hook-form to v7.72.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-03 09:03:17 -07:00
Patrik Oldsberg 8f9c1d64b8 verify-links: catch broken anchors, directory links, and invisible characters (#33713)
* verify-links: catch broken anchors, directory links, and invisible characters

Enhances the link verification script to catch several categories of
broken links that were previously missed:

- Broken anchors (cross-file and same-file) by extracting heading slugs
  from target documents and verifying anchors resolve
- Directory links missing index.md suffix within docs/
- Invisible/zero-width characters in URLs
- Case-sensitive anchor mismatches

Also strips fenced code blocks before scanning for links to avoid false
positives, and handles duplicate heading slug deduplication (GitHub and
Docusaurus append -1, -2, etc.).

Fixes a few newly-caught broken links in existing docs.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor

* Fix CodeQL incomplete multi-character sanitization alert

Apply HTML tag stripping in a loop so that nested fragments
like <scr<script>ipt> are fully removed.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor

---------

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
2026-04-03 17:48:40 +02:00
Rajib Quayum 452bb50432 chore: fix documentation
Signed-off-by: Rajib Quayum <rajibq@users.noreply.github.com>
2026-04-03 10:30:00 -04:00
Rajib Quayum a0100d4197 chore: add changeset
Signed-off-by: Rajib Quayum <rajibq@users.noreply.github.com>
2026-04-03 10:06:11 -04:00
Fredrik Adelöw 7e63730288 chore: add changeset for permissions cleanup step 1
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
2026-04-03 16:05:49 +02:00
Fredrik Adelöw c1802eb603 refactor(catalog-backend): permissions cleanup step 1
Make `permissionsRegistry` required and `permissions` always a
`PermissionsService` in `CatalogEnvironment`. Remove the deprecated
`PermissionAuthorizer` fallback path and the `createPermissionIntegrationRouter`
fallback — catalog now exclusively uses `permissionsRegistry.addResourceType`
to register its permission resource type.

Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
2026-04-03 16:03:15 +02:00
Rajib Quayum e22fc0af9c chore: update docs for MUI v5 class name prefix issue
Signed-off-by: Rajib Quayum <rajibq@users.noreply.github.com>
2026-04-03 10:01:25 -04:00
Fredrik Adelöw 75db4afdec Merge pull request #33742 from backstage/freben/host-discovery-baseurl-warnings
feat(backend-defaults): warn on localhost or invalid backend.baseUrl in HostDiscovery
2026-04-03 15:34:27 +02:00
Rajib Quayum 2c541a782b fix: prevent occasional duplication of the MUI v5 prefix
Signed-off-by: Rajib Quayum <rajibq@users.noreply.github.com>
2026-04-03 09:29:06 -04:00
Rajib Quayum 51ee29bac7 chore: pulls in master
Signed-off-by: Rajib Quayum <rajibq@users.noreply.github.com>
2026-04-03 09:27:25 -04:00
Rajib Quayum a4dc401ac3 chore: revert all previous changes
Signed-off-by: Rajib Quayum <rajibq@users.noreply.github.com>
2026-04-03 09:24:04 -04:00
Fredrik Adelöw 57543abb7c Update packages/backend-defaults/src/entrypoints/discovery/HostDiscovery.ts
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Fredrik Adelöw <freben@gmail.com>
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
2026-04-03 15:01:45 +02:00
Fredrik Adelöw 308c672680 feat(backend-defaults): warn on localhost or invalid backend.baseUrl in HostDiscovery
Adds startup warnings to HostDiscovery.fromConfig when backend.baseUrl
is set to a localhost address in a production environment, or when the
value is not a valid URL at all.

Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
2026-04-03 14:48:26 +02:00
Riley Martine d5899c2362 Allow passing showArrowHeads to entity-card:catalog-graph/relations and /catalog-graph page (#33706)
* Allow passing showArrowHeads to entity-card:catalog-graph/relations and /catalog-graph page

Signed-off-by: Riley Martine <rmartine@integralads.com>

* Update .changeset/nine-signs-end.md

Signed-off-by: Aramis Sennyey <159921952+aramissennyeydd@users.noreply.github.com>

---------

Signed-off-by: Riley Martine <rmartine@integralads.com>
Signed-off-by: Aramis Sennyey <159921952+aramissennyeydd@users.noreply.github.com>
Co-authored-by: Aramis Sennyey <159921952+aramissennyeydd@users.noreply.github.com>
2026-04-03 12:34:45 +00:00
Patrik Oldsberg 7a35328a03 Fix test expectation for toError string conversion
The `toError` utility now converts thrown strings to proper `Error`
objects, changing the cause message format from `unknown error 'boom'`
to `Error: boom`.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
2026-04-03 11:58:00 +02:00
Patrik Oldsberg 482ceed6d2 Address review feedback: simplify toError and add changeset
- Remove JSON.stringify fallback from toError, use the same unknown
  error messaging as stringifyError for all non-string/non-error values
- Add try/catch to protect against values that throw on string
  conversion (e.g. null-prototype objects, symbols)
- Fix no-op `void toError(err)` in DeleteEntityConfirmationDialog
- Fix `${err}` producing [object Object] in UrlReaderProcessor
- Fix double toError call in openStackSwift
- Update JSDoc to accurately describe the behavior
- Add tests for throwing toString and circular objects
- Add changeset for all refactored packages

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
2026-04-03 11:25:58 +02:00