Skip to content

announcements: integration with notifications #4378 #4816

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions workspaces/announcements/.changeset/itchy-boxes-arrive.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@backstage-community/plugin-announcements-backend': minor
---

announcements: integration with notifications #4378
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"@backstage/plugin-auth-node": "^0.6.5",
"@backstage/plugin-events-backend": "^0.5.4",
"@backstage/plugin-events-node": "^0.4.13",
"@backstage/plugin-notifications-node": "^0.2.17",
"@backstage/plugin-permission-common": "^0.9.1",
"@backstage/plugin-permission-node": "^0.10.2",
"@backstage/plugin-search-backend-node": "^1.3.13",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { signalsServiceRef } from '@backstage/plugin-signals-node';
import { eventsServiceRef } from '@backstage/plugin-events-node';
import { buildAnnouncementsContext } from './service';
import { announcementEntityPermissions } from '@backstage-community/plugin-announcements-common';
import { notificationService } from '@backstage/plugin-notifications-node';

/**
* A backend for the announcements plugin.
Expand All @@ -41,6 +42,7 @@ export const announcementsPlugin = createBackendPlugin({
permissions: coreServices.permissions,
permissionsRegistry: coreServices.permissionsRegistry,
signals: signalsServiceRef,
notifications: notificationService,
},
async init({
config,
Expand All @@ -52,6 +54,7 @@ export const announcementsPlugin = createBackendPlugin({
permissions,
permissionsRegistry,
signals,
notifications,
}) {
const context = await buildAnnouncementsContext({
config,
Expand All @@ -62,6 +65,7 @@ export const announcementsPlugin = createBackendPlugin({
permissions,
permissionsRegistry,
signals,
notifications,
});

permissionsRegistry.addPermissions(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ describe('createRouter', () => {
issueUserCookie: jest.fn(),
};

const mockNotificationService = {
send: jest.fn().mockImplementation(async () => {}),
};

afterEach(() => {
jest.resetAllMocks();
});
Expand All @@ -71,10 +75,12 @@ describe('createRouter', () => {
permissions: mockPermissions,
permissionsRegistry: mockServices.permissionsRegistry.mock(),
httpAuth: mockHttpAuth,
notifications: mockNotificationService,
};

const router = await createRouter(announcementsContext);
app = express().use(router);
mockNotificationService.send.mockClear();
});

beforeEach(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,44 @@ import {
} from '@backstage-community/plugin-announcements-common';
import { signalAnnouncement } from './service/signal';
import { AnnouncementsContext } from './service';
import { NotificationService } from '@backstage/plugin-notifications-node';
import { Config } from '@backstage/config';

const sendAnnouncementNotification = (
announcementId: string,
announcementNotificationOpts: {
notifications?: NotificationService;
config: Config;
},
) => {
const notificationsConfig =
announcementNotificationOpts.config.getOptionalConfig(
'announcements.notification',
);

const notifications = announcementNotificationOpts.notifications;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking - you could consider destructuring right here

const { config, notifications } = announcementNotificationOpts

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not needed now based on @gaelgoth next comment. But do revert if nay concern.


if (!notificationsConfig || !notifications) {
return;
}
const entityRefsTargets =
notificationsConfig.getOptionalStringArray('targets');
const hostUrl = notificationsConfig.getOptionalString('hostUrl');

notifications.send({
recipients: {
type: 'entity',
entityRef: entityRefsTargets ?? [],
},
payload: {
title: 'New Announcement',
description: 'New announcement has been added',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we allow the user to specify the title and description via params?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

link: hostUrl
? `${hostUrl}/announcements/view/${announcementId}`
: `/announcements/view/${announcementId}`,
},
});
};

interface AnnouncementRequest {
publisher: string;
Expand Down Expand Up @@ -76,6 +114,7 @@ export async function createRouter(
persistenceContext,
permissions,
signals,
notifications,
} = context;

const {
Expand Down Expand Up @@ -209,6 +248,13 @@ export async function createRouter(
tags: validatedTags,
});

// Send announcement notification
const announcementNotificationOpts = { notifications, config };
sendAnnouncementNotification(
announcement.id,
announcementNotificationOpts,
);

if (events) {
events.publish({
topic: EVENTS_TOPIC_ANNOUNCEMENTS,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ describe('buildAnnouncementsContext', () => {
publish: jest.fn(),
};

const mockNotificationService = {
send: jest.fn().mockImplementation(async () => {}),
};
const notifications = mockNotificationService;
const context = await buildAnnouncementsContext({
config,
database,
Expand All @@ -45,6 +49,7 @@ describe('buildAnnouncementsContext', () => {
permissions,
permissionsRegistry,
signals,
notifications,
});

const persistenceContext = await initializePersistenceContext(database);
Expand All @@ -58,6 +63,7 @@ describe('buildAnnouncementsContext', () => {
permissionsRegistry,
persistenceContext,
signals,
notifications,
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
} from '@backstage/backend-plugin-api';
import { EventsService } from '@backstage/plugin-events-node';
import { SignalsService } from '@backstage/plugin-signals-node';
import { NotificationService } from '@backstage/plugin-notifications-node';

/**
* Context for the announcements plugin.
Expand All @@ -42,6 +43,7 @@ export type AnnouncementsContext = {
permissionsRegistry: PermissionsRegistryService;
persistenceContext: PersistenceContext;
signals?: SignalsService;
notifications?: NotificationService;
};

/**
Expand Down Expand Up @@ -70,6 +72,7 @@ export const buildAnnouncementsContext = async ({
permissions,
permissionsRegistry,
signals,
notifications,
}: AnnouncementsContextOptions): Promise<AnnouncementsContext> => {
return {
config,
Expand All @@ -80,5 +83,6 @@ export const buildAnnouncementsContext = async ({
permissionsRegistry,
persistenceContext: await initializePersistenceContext(database),
signals,
notifications,
};
};
26 changes: 26 additions & 0 deletions workspaces/announcements/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2645,6 +2645,7 @@ __metadata:
"@backstage/plugin-catalog-node": "npm:^1.17.2"
"@backstage/plugin-events-backend": "npm:^0.5.4"
"@backstage/plugin-events-node": "npm:^0.4.13"
"@backstage/plugin-notifications-node": "npm:^0.2.17"
"@backstage/plugin-permission-backend": "npm:^0.7.2"
"@backstage/plugin-permission-backend-module-allow-all-policy": "npm:^0.2.10"
"@backstage/plugin-permission-common": "npm:^0.9.1"
Expand Down Expand Up @@ -4047,6 +4048,31 @@ __metadata:
languageName: node
linkType: hard

"@backstage/plugin-notifications-common@npm:^0.0.10":
version: 0.0.10
resolution: "@backstage/plugin-notifications-common@npm:0.0.10"
dependencies:
"@backstage/config": "npm:^1.3.3"
"@material-ui/icons": "npm:^4.9.1"
checksum: 10/901d5eedfdae1b3bffad802287b7c616be24ba022a58951ae7c4164b69c7b58b2cb27a96f596926445ad613d3a0d7c16eeff7af02518c59a92fefa11801e3e67
languageName: node
linkType: hard

"@backstage/plugin-notifications-node@npm:^0.2.17":
version: 0.2.17
resolution: "@backstage/plugin-notifications-node@npm:0.2.17"
dependencies:
"@backstage/backend-plugin-api": "npm:^1.4.1"
"@backstage/catalog-client": "npm:^1.10.2"
"@backstage/catalog-model": "npm:^1.7.5"
"@backstage/plugin-notifications-common": "npm:^0.0.10"
"@backstage/plugin-signals-node": "npm:^0.1.22"
knex: "npm:^3.0.0"
uuid: "npm:^11.0.0"
checksum: 10/4753b68b760a714e82b7b777d140b7d974b4b7e0fefd2eeeb66b5be876c52c3042ba5645b15735a641de1cfc1184c56441a13934c70ac4569b20dc5b9f820020
languageName: node
linkType: hard

"@backstage/plugin-org@npm:^0.6.41":
version: 0.6.41
resolution: "@backstage/plugin-org@npm:0.6.41"
Expand Down