-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(awards): add slack notifications (#31)
* add notification gateway * addf slack notification gateway * load slack notification gateway from config * pass config from demo app * only notify if there are new recipients * prettier * test the Awards.update func * change config spec a bit - icon_emoji and username fields seem to not actually work for the incoming webhook bot - i imagine we may have a `slack.bot` configuration, so isolating `webhook` to its own object * link to award in backstage * fetch user entities when sending notifications * remove "Woohoo!" * add description block * notify recipients on create award * remove comment * update test for new impl * add test for create notifying new recipients * fix tsc * add tests for slack notifications gateway * add docs * add copyrights * add AwardsNotifier abstraction to not bloat Awards class * make webhook an env var in examples as it contains secrets * make config required * don't pass around identityRef where it's not yet needed * add copyrights
- Loading branch information
Showing
14 changed files
with
603 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
/* | ||
* Copyright SeatGeek | ||
* Licensed under the terms of the Apache-2.0 license. See LICENSE file in project root for terms. | ||
*/ | ||
import { Award } from '@seatgeek/backstage-plugin-awards-common'; | ||
import * as winston from 'winston'; | ||
import { Awards } from './awards'; | ||
import { AwardsStore } from './database/awards'; | ||
import { AwardsNotifier } from './notifier'; | ||
|
||
const frank = 'user:default/frank-ocean'; | ||
|
||
function makeAward(): Award { | ||
return { | ||
uid: '123456', | ||
name: 'Test Award', | ||
description: 'This is a test award', | ||
image: 'image_data', | ||
owners: [frank], | ||
recipients: ['user:default/peyton-manning', 'user:default/serena-williams'], | ||
}; | ||
} | ||
|
||
describe('Awards', () => { | ||
let db: jest.Mocked<AwardsStore>; | ||
let notifier: jest.Mocked<AwardsNotifier>; | ||
let awards: Awards; | ||
|
||
beforeEach(() => { | ||
db = { | ||
search: jest.fn(), | ||
add: jest.fn(), | ||
update: jest.fn(), | ||
delete: jest.fn(), | ||
}; | ||
notifier = { | ||
notifyNewRecipients: jest.fn(), | ||
}; | ||
const logger = winston.createLogger({ | ||
transports: [new winston.transports.Console({ silent: true })], | ||
}); | ||
awards = new Awards(db, notifier, logger); | ||
}); | ||
|
||
afterEach(() => { | ||
jest.resetAllMocks(); | ||
}); | ||
|
||
describe('create', () => { | ||
it('should notify new recipients', async () => { | ||
const award = makeAward(); | ||
db.add = jest.fn().mockResolvedValue(award); | ||
const result = await awards.create({ | ||
name: award.name, | ||
description: award.description, | ||
image: award.image, | ||
owners: award.owners, | ||
recipients: award.recipients, | ||
}); | ||
|
||
// wait for the afterCreate promises to complete | ||
await new Promise(process.nextTick); | ||
|
||
expect(result).toEqual(award); | ||
expect(db.add).toHaveBeenCalledWith( | ||
award.name, | ||
award.description, | ||
award.image, | ||
award.owners, | ||
award.recipients, | ||
); | ||
expect(notifier.notifyNewRecipients).toHaveBeenCalledWith(award, [ | ||
'user:default/peyton-manning', | ||
'user:default/serena-williams', | ||
]); | ||
}); | ||
}); | ||
|
||
describe('update', () => { | ||
it('should notify new recipients', async () => { | ||
const award = makeAward(); | ||
db.search = jest.fn().mockResolvedValue([award]); | ||
const updated = { | ||
...award, | ||
recipients: [ | ||
...award.recipients, | ||
'user:default/megan-rapinoe', | ||
'user:default/adrianne-lenker', | ||
], | ||
}; | ||
db.update = jest.fn().mockResolvedValue(updated); | ||
const result = await awards.update(frank, award.uid, updated); | ||
|
||
// wait for the afterUpdate promises to complete | ||
await new Promise(process.nextTick); | ||
|
||
expect(result).toEqual(updated); | ||
expect(db.update).toHaveBeenCalledWith( | ||
updated.uid, | ||
updated.name, | ||
updated.description, | ||
updated.image, | ||
updated.owners, | ||
updated.recipients, | ||
); | ||
expect(notifier.notifyNewRecipients).toHaveBeenCalledWith(updated, [ | ||
'user:default/megan-rapinoe', | ||
'user:default/adrianne-lenker', | ||
]); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
95 changes: 95 additions & 0 deletions
95
plugins/awards-backend/src/notifications/notifications.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
/* | ||
* Copyright SeatGeek | ||
* Licensed under the terms of the Apache-2.0 license. See LICENSE file in project root for terms. | ||
*/ | ||
import { UserEntity } from '@backstage/catalog-model'; | ||
import { Award } from '@seatgeek/backstage-plugin-awards-common'; | ||
import { IncomingWebhook } from '@slack/webhook'; | ||
import { SlackNotificationsGateway } from './notifications'; | ||
|
||
describe('SlackNotificationsGateway', () => { | ||
// @ts-ignore | ||
const slack: jest.Mocked<IncomingWebhook> = { | ||
send: jest.fn(), | ||
}; | ||
|
||
beforeEach(() => { | ||
jest.resetAllMocks(); | ||
}); | ||
|
||
it('should send a message to slack', async () => { | ||
const gateway = new SlackNotificationsGateway( | ||
slack, | ||
'http://localhost:3000', | ||
); | ||
const award: Award = { | ||
uid: '123', | ||
name: 'Coolest Test', | ||
description: 'For great tests', | ||
image: 'image', | ||
owners: [], | ||
recipients: [], | ||
}; | ||
const newRecipients: UserEntity[] = [ | ||
{ | ||
apiVersion: 'backstage.io/v1alpha1', | ||
kind: 'User', | ||
metadata: { | ||
name: 'taylor-swift', | ||
annotations: { | ||
'slack.com/user_id': '123', | ||
}, | ||
}, | ||
spec: { | ||
profile: { | ||
displayName: 'Taylor Swift', | ||
}, | ||
}, | ||
}, | ||
{ | ||
apiVersion: 'backstage.io/v1alpha1', | ||
kind: 'User', | ||
metadata: { | ||
name: 'lebron-james', | ||
annotations: { | ||
'slack.com/user_id': '456', | ||
}, | ||
}, | ||
spec: { | ||
profile: { | ||
displayName: 'Lebron James', | ||
}, | ||
}, | ||
}, | ||
]; | ||
|
||
await gateway.notifyNewRecipientsAdded(award, newRecipients); | ||
|
||
expect(slack.send).toHaveBeenCalledWith({ | ||
blocks: [ | ||
{ | ||
type: 'header', | ||
text: { | ||
type: 'plain_text', | ||
text: ':trophy: The following users have received the Coolest Test Award :trophy:', | ||
emoji: true, | ||
}, | ||
}, | ||
{ | ||
type: 'section', | ||
text: { | ||
type: 'mrkdwn', | ||
text: '<http://localhost:3000/catalog/default/User/taylor-swift|Taylor Swift> (<@123>), <http://localhost:3000/catalog/default/User/lebron-james|Lebron James> (<@456>)', | ||
}, | ||
}, | ||
{ | ||
type: 'section', | ||
text: { | ||
type: 'mrkdwn', | ||
text: '> For great tests (<http://localhost:3000/awards/view/123|More info>)', | ||
}, | ||
}, | ||
], | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.