create-app - Added Notifications and Signals to be installed by default

Signed-off-by: Andre Wanlin <awanlin@spotify.com>
This commit is contained in:
Andre Wanlin
2025-08-15 07:42:16 -05:00
parent 3f6029ce2a
commit e33fce15df
14 changed files with 134 additions and 2 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/create-app': patch
---
Added Notifications and Signals to be installed by default
+52
View File
@@ -33,6 +33,12 @@ Example of use-cases:
## Installation
:::note
As of the `1.42.0` release of Backstage, Notifications and Signals are installed as part of the default `@backstage/create-app` instance which means you won't need to follow the installations steps outlined here. The only exception to this is adding the [Notifications tab to User Settings](#user-specific-notification-settings) to allow managing these settings.
:::
The following sections will walk you through the installation of the various parts of the Backstage Notification System.
### Add Notifications Backend
@@ -173,6 +179,52 @@ notifications:
If the retention is set to false, notifications will not be automatically deleted.
## Scaffolder Action
:::note
As of the `1.42.0` release of Backstage, the Notifications Scaffolder action is installed as part of the default `@backstage/create-app` instance which means you won't need to follow the installations steps outlined here. Feel free to skip to the [Basic Example](#basic-example).
:::
There is also a Scaffolder action that you can use to send a notification as part of your Software Template.
First we need to add the backend package:
```bash title="From your Backstage root directory"
yarn --cwd packages/backend add @backstage/plugin-scaffolder-backend-module-notifications
```
Then we need to add it to our backend:
```ts title="packages/backend/src/index.ts"
const backend = createBackend();
// ...
backend.add(
import('@backstage/plugin-scaffolder-backend-module-notifications'),
);
```
### Basic Example
Here's an example of how you can use it in your Software Template, more details and examples can be found in the "Installed actions" screen in your Backstage instances:
```yaml title="template.yaml"
steps:
- id: notify
name: Notify
action: notification:send
input:
recipients: entity
entityRefs:
- user:default/guest
title: 'Template executed'
info: 'Your template has been executed'
severity: 'normal'
```
The example above would send a notification to the Guest user (`user:default/guest`)
## Additional info
An example of a backend plugin sending notifications can be found in the [`@backstage/plugin-scaffolder-backend-module-notifications` package](https://github.com/backstage/backstage/tree/master/plugins/scaffolder-backend-module-notifications).
@@ -89,12 +89,17 @@ jest.mock('./versions', () => ({
'@backstage/plugin-catalog-react': '1.0.0',
'@backstage/plugin-kubernetes': '1.0.0',
'@backstage/plugin-kubernetes-backend': '1.0.0',
'@backstage/plugin-notifications': '1.0.0',
'@backstage/plugin-notifications-backend': '1.0.0',
'@backstage/plugin-org': '1.0.0',
'@backstage/plugin-scaffolder': '1.0.0',
'@backstage/plugin-scaffolder-backend-module-github': '1.0.0',
'@backstage/plugin-scaffolder-backend-module-notifications': '1.0.0',
'@backstage/plugin-permission-react': '1.0.0',
'@backstage/plugin-search': '1.0.0',
'@backstage/plugin-search-react': '1.0.0',
'@backstage/plugin-signals': '1.0.0',
'@backstage/plugin-signals-backend': '1.0.0',
'@backstage/plugin-techdocs': '1.0.0',
'@backstage/plugin-techdocs-react': '1.0.0',
'@backstage/plugin-techdocs-module-addons-contrib': '1.0.0',
+11
View File
@@ -68,6 +68,8 @@ import { version as pluginCatalogGraph } from '../../../../plugins/catalog-graph
import { version as pluginCatalogImport } from '../../../../plugins/catalog-import/package.json';
import { version as pluginKubernetes } from '../../../../plugins/kubernetes/package.json';
import { version as pluginKubernetesBackend } from '../../../../plugins/kubernetes-backend/package.json';
import { version as pluginNotifications } from '../../../../plugins/notifications/package.json';
import { version as pluginNotificationsBackend } from '../../../../plugins/notifications-backend/package.json';
import { version as pluginOrg } from '../../../../plugins/org/package.json';
import { version as pluginPermissionBackend } from '../../../../plugins/permission-backend/package.json';
import { version as pluginPermissionBackendModulePolicyAllowAll } from '../../../../plugins/permission-backend-module-policy-allow-all/package.json';
@@ -78,6 +80,7 @@ import { version as pluginProxyBackend } from '../../../../plugins/proxy-backend
import { version as pluginScaffolder } from '../../../../plugins/scaffolder/package.json';
import { version as pluginScaffolderBackend } from '../../../../plugins/scaffolder-backend/package.json';
import { version as pluginScaffolderBackendModuleGithub } from '../../../../plugins/scaffolder-backend-module-github/package.json';
import { version as pluginScaffolderBackendModuleNotifications } from '../../../../plugins/scaffolder-backend-module-notifications/package.json';
import { version as pluginSearch } from '../../../../plugins/search/package.json';
import { version as pluginSearchReact } from '../../../../plugins/search-react/package.json';
import { version as pluginSearchBackend } from '../../../../plugins/search-backend/package.json';
@@ -85,6 +88,8 @@ import { version as pluginSearchBackendModuleCatalog } from '../../../../plugins
import { version as pluginSearchBackendModulePg } from '../../../../plugins/search-backend-module-pg/package.json';
import { version as pluginSearchBackendModuleTechdocs } from '../../../../plugins/search-backend-module-techdocs/package.json';
import { version as pluginSearchBackendNode } from '../../../../plugins/search-backend-node/package.json';
import { version as pluginSignals } from '../../../../plugins/signals/package.json';
import { version as pluginSignalsBackend } from '../../../../plugins/signals-backend/package.json';
import { version as pluginTechdocs } from '../../../../plugins/techdocs/package.json';
import { version as pluginTechdocsReact } from '../../../../plugins/techdocs-react/package.json';
import { version as pluginTechdocsModuleAddonsContrib } from '../../../../plugins/techdocs-module-addons-contrib/package.json';
@@ -130,6 +135,8 @@ export const packageVersions = {
'@backstage/plugin-catalog-import': pluginCatalogImport,
'@backstage/plugin-kubernetes': pluginKubernetes,
'@backstage/plugin-kubernetes-backend': pluginKubernetesBackend,
'@backstage/plugin-notifications': pluginNotifications,
'@backstage/plugin-notifications-backend': pluginNotificationsBackend,
'@backstage/plugin-org': pluginOrg,
'@backstage/plugin-permission-backend': pluginPermissionBackend,
'@backstage/plugin-permission-backend-module-allow-all-policy':
@@ -142,6 +149,8 @@ export const packageVersions = {
'@backstage/plugin-scaffolder-backend': pluginScaffolderBackend,
'@backstage/plugin-scaffolder-backend-module-github':
pluginScaffolderBackendModuleGithub,
'@backstage/plugin-scaffolder-backend-module-notifications':
pluginScaffolderBackendModuleNotifications,
'@backstage/plugin-search': pluginSearch,
'@backstage/plugin-search-react': pluginSearchReact,
'@backstage/plugin-search-backend': pluginSearchBackend,
@@ -151,6 +160,8 @@ export const packageVersions = {
'@backstage/plugin-search-backend-module-techdocs':
pluginSearchBackendModuleTechdocs,
'@backstage/plugin-search-backend-node': pluginSearchBackendNode,
'@backstage/plugin-signals': pluginSignals,
'@backstage/plugin-signals-backend': pluginSignalsBackend,
'@backstage/plugin-techdocs': pluginTechdocs,
'@backstage/plugin-techdocs-react': pluginTechdocsReact,
'@backstage/plugin-techdocs-module-addons-contrib':
@@ -66,6 +66,18 @@ spec:
repoContentsUrl: ${{ steps['publish'].output.repoContentsUrl }}
catalogInfoPath: '/catalog-info.yaml'
# Let's notify the user that the template has completed using the Notification action
- id: notify
name: Notify
action: notification:send
input:
recipients: entity
entityRefs:
- user:default/guest
title: 'Template executed'
info: 'Your template has been executed'
severity: 'normal'
# Outputs are displayed to the user after a successful execution of the template.
output:
links:
@@ -28,11 +28,13 @@
"@backstage/plugin-catalog-import": "^{{version '@backstage/plugin-catalog-import'}}",
"@backstage/plugin-catalog-react": "^{{version '@backstage/plugin-catalog-react'}}",
"@backstage/plugin-kubernetes": "^{{version '@backstage/plugin-kubernetes'}}",
"@backstage/plugin-notifications": "^{{ version '@backstage/plugin-notifications'}}",
"@backstage/plugin-org": "^{{version '@backstage/plugin-org'}}",
"@backstage/plugin-permission-react": "^{{version '@backstage/plugin-permission-react'}}",
"@backstage/plugin-scaffolder": "^{{version '@backstage/plugin-scaffolder'}}",
"@backstage/plugin-search": "^{{version '@backstage/plugin-search'}}",
"@backstage/plugin-search-react": "^{{version '@backstage/plugin-search-react'}}",
"@backstage/plugin-signals": "^{{ version '@backstage/plugin-signals'}}",
"@backstage/plugin-techdocs": "^{{version '@backstage/plugin-techdocs'}}",
"@backstage/plugin-techdocs-module-addons-contrib": "^{{version '@backstage/plugin-techdocs-module-addons-contrib'}}",
"@backstage/plugin-techdocs-react": "^{{version '@backstage/plugin-techdocs-react'}}",
@@ -35,6 +35,8 @@ import { AppRouter, FlatRoutes } from '@backstage/core-app-api';
import { CatalogGraphPage } from '@backstage/plugin-catalog-graph';
import { RequirePermission } from '@backstage/plugin-permission-react';
import { catalogEntityCreatePermission } from '@backstage/plugin-catalog-common/alpha';
import { NotificationsPage } from '@backstage/plugin-notifications';
import { SignalsDisplay } from '@backstage/plugin-signals';
const app = createApp({
apis,
@@ -94,6 +96,7 @@ const routes = (
</Route>
<Route path="/settings" element={<UserSettingsPage />} />
<Route path="/catalog-graph" element={<CatalogGraphPage />} />
<Route path="/notifications" element={<NotificationsPage />} />
</FlatRoutes>
);
@@ -101,6 +104,7 @@ export default app.createRoot(
<>
<AlertDisplay />
<OAuthRequestDialog />
<SignalsDisplay />
<AppRouter>
<Root>{routes}</Root>
</AppRouter>
@@ -27,6 +27,7 @@ import MenuIcon from '@material-ui/icons/Menu';
import SearchIcon from '@material-ui/icons/Search';
import { MyGroupsSidebarItem } from '@backstage/plugin-org';
import GroupIcon from '@material-ui/icons/People';
import { NotificationsSidebarItem } from '@backstage/plugin-notifications';
const useSidebarLogoStyles = makeStyles({
root: {
@@ -83,6 +84,8 @@ export const Root = ({ children }: PropsWithChildren<{}>) => (
</SidebarGroup>
<SidebarSpace />
<SidebarDivider />
<NotificationsSidebarItem />
<SidebarDivider />
<SidebarGroup
label="Settings"
icon={<UserSettingsSignInAvatar />}
@@ -27,6 +27,7 @@
"@backstage/plugin-catalog-backend-module-logs": "^{{version '@backstage/plugin-catalog-backend-module-logs'}}",
"@backstage/plugin-catalog-backend-module-scaffolder-entity-model": "^{{version '@backstage/plugin-catalog-backend-module-scaffolder-entity-model'}}",
"@backstage/plugin-kubernetes-backend": "^{{version '@backstage/plugin-kubernetes-backend'}}",
"@backstage/plugin-notifications-backend": "^{{version '@backstage/plugin-notifications-backend'}}",
"@backstage/plugin-permission-backend": "^{{version '@backstage/plugin-permission-backend'}}",
"@backstage/plugin-permission-backend-module-allow-all-policy": "^{{version '@backstage/plugin-permission-backend-module-allow-all-policy'}}",
"@backstage/plugin-permission-common": "^{{version '@backstage/plugin-permission-common'}}",
@@ -34,11 +35,13 @@
"@backstage/plugin-proxy-backend": "^{{version '@backstage/plugin-proxy-backend'}}",
"@backstage/plugin-scaffolder-backend": "^{{version '@backstage/plugin-scaffolder-backend'}}",
"@backstage/plugin-scaffolder-backend-module-github": "^{{version '@backstage/plugin-scaffolder-backend-module-github'}}",
"@backstage/plugin-scaffolder-backend-module-notifications": "^{{version '@backstage/plugin-scaffolder-backend-module-notifications'}}",
"@backstage/plugin-search-backend": "^{{version '@backstage/plugin-search-backend'}}",
"@backstage/plugin-search-backend-module-catalog": "^{{version '@backstage/plugin-search-backend-module-catalog'}}",
"@backstage/plugin-search-backend-module-pg": "^{{version '@backstage/plugin-search-backend-module-pg'}}",
"@backstage/plugin-search-backend-module-techdocs": "^{{version '@backstage/plugin-search-backend-module-techdocs'}}",
"@backstage/plugin-search-backend-node": "^{{version '@backstage/plugin-search-backend-node'}}",
"@backstage/plugin-signals-backend": "^{{version '@backstage/plugin-signals-backend'}}",
"@backstage/plugin-techdocs-backend": "^{{version '@backstage/plugin-techdocs-backend'}}",
"app": "link:../app",
"better-sqlite3": "^12.0.0",
@@ -12,8 +12,13 @@ const backend = createBackend();
backend.add(import('@backstage/plugin-app-backend'));
backend.add(import('@backstage/plugin-proxy-backend'));
// scaffolder plugin
backend.add(import('@backstage/plugin-scaffolder-backend'));
backend.add(import('@backstage/plugin-scaffolder-backend-module-github'));
backend.add(import('@backstage/plugin-scaffolder-backend-module-notifications'));
// techdocs plugin
backend.add(import('@backstage/plugin-techdocs-backend'));
// auth plugin
@@ -49,7 +54,11 @@ backend.add(import('@backstage/plugin-search-backend-module-pg'));
backend.add(import('@backstage/plugin-search-backend-module-catalog'));
backend.add(import('@backstage/plugin-search-backend-module-techdocs'));
// kubernetes
// kubernetes plugin
backend.add(import('@backstage/plugin-kubernetes-backend'));
// notifications and signals plugins
backend.add(import('@backstage/plugin-notifications-backend'));
backend.add(import('@backstage/plugin-signals-backend'));
backend.start();
@@ -65,6 +65,18 @@ spec:
input:
repoContentsUrl: ${{ steps['publish'].output.repoContentsUrl }}
catalogInfoPath: '/catalog-info.yaml'
# Let's notify the user that the template has completed using the Notification action
- id: notify
name: Notify
action: notification:send
input:
recipients: entity
entityRefs:
- user:default/guest
title: 'Template executed'
info: 'Your template has been executed'
severity: 'normal'
# Outputs are displayed to the user after a successful execution of the template.
output:
@@ -19,9 +19,11 @@
"@backstage/frontend-defaults": "^{{ version '@backstage/frontend-defaults'}}",
"@backstage/frontend-plugin-api": "^{{ version '@backstage/frontend-plugin-api'}}",
"@backstage/plugin-catalog": "^{{ version '@backstage/plugin-catalog'}}",
"@backstage/plugin-notifications": "^{{ version '@backstage/plugin-notifications'}}",
"@backstage/plugin-org": "^{{ version '@backstage/plugin-org'}}",
"@backstage/plugin-scaffolder": "^{{ version '@backstage/plugin-scaffolder'}}",
"@backstage/plugin-search": "^{{ version '@backstage/plugin-search'}}",
"@backstage/plugin-signals": "^{{ version '@backstage/plugin-signals'}}",
"@backstage/plugin-user-settings": "^{{ version '@backstage/plugin-user-settings'}}",
"@backstage/ui": "^{{ version '@backstage/ui'}}",
"@material-ui/core": "^4.12.2",
@@ -27,6 +27,7 @@
"@backstage/plugin-catalog-backend-module-logs": "^{{version '@backstage/plugin-catalog-backend-module-logs'}}",
"@backstage/plugin-catalog-backend-module-scaffolder-entity-model": "^{{version '@backstage/plugin-catalog-backend-module-scaffolder-entity-model'}}",
"@backstage/plugin-kubernetes-backend": "^{{version '@backstage/plugin-kubernetes-backend'}}",
"@backstage/plugin-notifications-backend": "^{{version '@backstage/plugin-notifications-backend'}}",
"@backstage/plugin-permission-backend": "^{{version '@backstage/plugin-permission-backend'}}",
"@backstage/plugin-permission-backend-module-allow-all-policy": "^{{version '@backstage/plugin-permission-backend-module-allow-all-policy'}}",
"@backstage/plugin-permission-common": "^{{version '@backstage/plugin-permission-common'}}",
@@ -34,11 +35,13 @@
"@backstage/plugin-proxy-backend": "^{{version '@backstage/plugin-proxy-backend'}}",
"@backstage/plugin-scaffolder-backend": "^{{version '@backstage/plugin-scaffolder-backend'}}",
"@backstage/plugin-scaffolder-backend-module-github": "^{{version '@backstage/plugin-scaffolder-backend-module-github'}}",
"@backstage/plugin-scaffolder-backend-module-notifications": "^{{version '@backstage/plugin-scaffolder-backend-module-notifications'}}",
"@backstage/plugin-search-backend": "^{{version '@backstage/plugin-search-backend'}}",
"@backstage/plugin-search-backend-module-catalog": "^{{version '@backstage/plugin-search-backend-module-catalog'}}",
"@backstage/plugin-search-backend-module-pg": "^{{version '@backstage/plugin-search-backend-module-pg'}}",
"@backstage/plugin-search-backend-module-techdocs": "^{{version '@backstage/plugin-search-backend-module-techdocs'}}",
"@backstage/plugin-search-backend-node": "^{{version '@backstage/plugin-search-backend-node'}}",
"@backstage/plugin-signals-backend": "^{{version '@backstage/plugin-signals-backend'}}",
"@backstage/plugin-techdocs-backend": "^{{version '@backstage/plugin-techdocs-backend'}}",
"app": "link:../app",
"better-sqlite3": "^9.0.0",
@@ -12,8 +12,13 @@ const backend = createBackend();
backend.add(import('@backstage/plugin-app-backend'));
backend.add(import('@backstage/plugin-proxy-backend'));
// scaffolder plugin
backend.add(import('@backstage/plugin-scaffolder-backend'));
backend.add(import('@backstage/plugin-scaffolder-backend-module-github'));
backend.add(import('@backstage/plugin-scaffolder-backend-module-notifications'));
// techdocs plugin
backend.add(import('@backstage/plugin-techdocs-backend'));
// auth plugin
@@ -49,7 +54,11 @@ backend.add(import('@backstage/plugin-search-backend-module-pg'));
backend.add(import('@backstage/plugin-search-backend-module-catalog'));
backend.add(import('@backstage/plugin-search-backend-module-techdocs'));
// kubernetes
// kubernetes plugin
backend.add(import('@backstage/plugin-kubernetes-backend'));
// notifications and signals plugins
backend.add(import('@backstage/plugin-notifications-backend'));
backend.add(import('@backstage/plugin-signals-backend'));
backend.start();