Merge pull request #30028 from FrankySpot/notifications/extend-model

feat(plugin/notifications) add generic attribute field to NotificationPayload
This commit is contained in:
Patrik Oldsberg
2025-08-15 16:02:36 +02:00
committed by GitHub
8 changed files with 90 additions and 4 deletions
+6
View File
@@ -0,0 +1,6 @@
---
'@backstage/plugin-notifications-backend': patch
'@backstage/plugin-notifications-common': minor
---
Add an optional generic object `metadata` field to `NotificationPayload`. Metadata can be used to store additional unstructured data for the notification and are available to use by processors.
+1 -4
View File
@@ -211,10 +211,7 @@ export type NotificationPayload = {
topic?: string;
scope?: string;
icon?: string;
metadata?: Array<{
type: string;
value: JsonValue;
}>;
metadata?: { [KMetadataKey in string]?: JsonValue };
};
export type Notification = {
+65
View File
@@ -210,3 +210,68 @@ notificationsApi.getNotification(yourId);
// or with connection to signals:
notificationsApi.getNotification(lastSignal.notification_id);
```
## Metadata Field
The metadata field is a freeform object that is designed to be used by processors.
### Well-known Notification Metadata Fields
Below are metadata fields that will be commonly used between processors and have defined schematics.
#### backstage.io/body.markdown
```ts
# Example:
const payload = {
title: 'Entities Require Attention',
description: 'Entities: Service A, Service B'
metadata: {
'backstage.io/body.markdown': `
# Entities
- Service A
- System B
`
}
}
```
This value of this metadata field should be the notification message in markdown format. This allows additional formatting options for processors that support markdown.
### Usage
Below is an example of using the `backstage.io/body.markdown` metadata field in a custom processor.
When sending a notification:
```ts
notificationService.send({
recipients: { type: 'entity', entityRef: 'group/default:team-a' },
payload: {
title: 'Notification',
description: 'Description'
metadata: {
'backstage.io/body.markdown': `
### Notification
Description
`,
},
},
});
```
In the processor, you can then use the metadata field accordingly:
```ts
async postProcess(notification: Notification): Promise<void> {
// We suggest you parse the metadata field with a schema, i.e. Zod
const parseResult = CustomProcessorMetadataSchema.safeParse(notification.payload.metadata ?? {});
const metadata = parseResult.success ? parseResult.data : {};
customNotificationSender.send({
to: getUsers(notification.recipients),
subject: notification.payload.title,
markdownText: metadata['backstage.io/body.markdown'] ?? notification.payload.description,
});
}
```
@@ -241,6 +241,9 @@ describe.each(databases.eachSupportedId())('createRouter (%s)', databaseId => {
},
payload: {
title: 'test notification',
metadata: {
attr: 1,
},
},
});
@@ -253,6 +256,9 @@ describe.each(databases.eachSupportedId())('createRouter (%s)', databaseId => {
payload: {
severity: 'normal',
title: 'test notification',
metadata: {
attr: 1,
},
},
user: 'user:default/mock',
},
@@ -40,6 +40,7 @@
},
"dependencies": {
"@backstage/config": "workspace:^",
"@backstage/types": "workspace:^",
"@material-ui/icons": "^4.9.1"
},
"devDependencies": {
@@ -4,6 +4,7 @@
```ts
import { Config } from '@backstage/config';
import { JsonValue } from '@backstage/types';
// @public (undocumented)
export type ChannelSetting = {
@@ -52,6 +53,9 @@ export type NotificationPayload = {
topic?: string;
scope?: string;
icon?: string;
metadata?: {
[KMetadataKey in string]?: JsonValue;
};
};
// @public (undocumented)
@@ -14,6 +14,8 @@
* limitations under the License.
*/
import { JsonValue } from '@backstage/types';
/** @public */
export type NotificationSeverity = 'critical' | 'high' | 'normal' | 'low';
@@ -50,6 +52,10 @@ export type NotificationPayload = {
* Optional notification icon
*/
icon?: string;
/**
* Optional additional customizable metadata.
*/
metadata?: { [KMetadataKey in string]?: JsonValue };
};
/** @public */
+1
View File
@@ -5751,6 +5751,7 @@ __metadata:
dependencies:
"@backstage/cli": "workspace:^"
"@backstage/config": "workspace:^"
"@backstage/types": "workspace:^"
"@material-ui/icons": "npm:^4.9.1"
languageName: unknown
linkType: soft