-
Notifications
You must be signed in to change notification settings - Fork 0
Feat: Add a generic webhook for sending event notifications #879
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
brian-lou
wants to merge
19
commits into
main
Choose a base branch
from
brian/add-generic-webhook
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
b15d743
Add txn logging
brian-lou 20b59c3
Delete unused index.ts files
brian-lou 575eb6f
Fix tests
brian-lou e38691d
Add http status to txn
brian-lou 3627224
Deprecate old Slack handler
brian-lou 53802ac
Add generic-notifier
brian-lou 6f14385
Fix tests
brian-lou 2d50f63
Add blocks to generic notifier
brian-lou 67ff8c2
Update readme
brian-lou 780a143
Merge branch 'main' into brian/add-generic-webhook
brian-lou 2628a1a
Add 400 error for invalid source field
brian-lou ad0745b
Update readme
brian-lou c61f87c
Change generic webhook API
brian-lou 3915a01
Add example service-registry config & change types
brian-lou 30cb490
Fix tests
brian-lou 7a308c7
Del unused ssh-agent stuff
brian-lou 85ac0f9
Revert ci.yml changes
brian-lou 7ff4b83
Revert migration.yml changes
brian-lou bc4ed32
Add TODO
brian-lou File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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,15 @@ | ||
/* | ||
|
||
This file contains secrets used for verifying incoming events from different HTTP sources. | ||
|
||
*/ | ||
|
||
export const EVENT_NOTIFIER_SECRETS = { | ||
// Follow the pattern below to add a new secret | ||
// The secret will also need to be added in the deploy.sh script and in | ||
// Google Secret manager | ||
// 'example-service': process.env.EXAMPLE_SERVICE_SECRET, | ||
}; | ||
if (process.env.ENV !== 'production') | ||
EVENT_NOTIFIER_SECRETS['example-service'] = | ||
process.env.EXAMPLE_SERVICE_SECRET; |
This file contains hidden or 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,36 @@ | ||
{ | ||
"example_service": { | ||
"alert_slack_channels": [ | ||
"slack-channel-id-or-name" | ||
], | ||
"aspiring_domain_experts": [], | ||
"component": "tool", | ||
"dashboard": null, | ||
"docs": { | ||
"notion page": "https://www.notion.so/" | ||
}, | ||
"domain_experts": [ | ||
{ | ||
"email": "[email protected]", | ||
"name": "Example Person" | ||
} | ||
], | ||
"escalation": "https://sentry.pagerduty.com/", | ||
"id": "example_service", | ||
"name": "Example service", | ||
"notes": null, | ||
"production_readiness_docs": [], | ||
"slack_channels": [ | ||
"discuss-stuff" | ||
], | ||
"slos": [], | ||
"teams": [ | ||
{ | ||
"display_name": "Team 1", | ||
"id": "team1", | ||
"tags": [] | ||
} | ||
], | ||
"tier": 1 | ||
} | ||
} |
This file contains hidden or 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,32 @@ | ||
export interface Team { | ||
id: string; | ||
display_name: string; | ||
tags: string[]; | ||
} | ||
|
||
export interface Expert { | ||
email: string; | ||
name: string; | ||
} | ||
|
||
export interface Service { | ||
id: string; | ||
name: string; | ||
tier: number | null; | ||
component: string | null; | ||
teams: Team[]; | ||
slack_channels: string[]; | ||
alert_slack_channels: string[]; | ||
domain_experts: Expert[]; | ||
escalation: string; | ||
slos: string[]; | ||
dashboard: string | null; | ||
production_readiness_docs: string[]; | ||
notes: string | null; | ||
docs: Record<string, string>; | ||
aspiring_domain_experts: Expert[]; | ||
} | ||
|
||
export type ServiceRegistry = { | ||
[serviceName: string]: Service; | ||
}; |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains hidden or 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 hidden or 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,8 @@ | ||
import servicesData from '@/service-registry/service_registry.json'; | ||
import type { Service, ServiceRegistry } from '@/service-registry/types/index'; | ||
|
||
const services: ServiceRegistry = servicesData; | ||
|
||
export function getService(serviceId: string): Service { | ||
return services[serviceId]; | ||
} |
This file contains hidden or 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 hidden or 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,105 @@ | ||
import testInvalidPayload from '@test/payloads/generic-notifier/testInvalidPayload.json'; | ||
import testPayload from '@test/payloads/generic-notifier/testPayload.json'; | ||
import { createNotifierRequest } from '@test/utils/createGenericMessageRequest'; | ||
|
||
import { buildServer } from '@/buildServer'; | ||
import { DATADOG_API_INSTANCE } from '@/config'; | ||
import { GenericEvent, SlackMessage } from '@/types'; | ||
import { bolt } from '@api/slack'; | ||
|
||
import { messageSlack } from './generic-notifier'; | ||
|
||
describe('generic messages webhook', function () { | ||
let fastify; | ||
beforeEach(async function () { | ||
fastify = await buildServer(false); | ||
}); | ||
|
||
afterEach(function () { | ||
fastify.close(); | ||
jest.clearAllMocks(); | ||
}); | ||
|
||
it('correctly inserts generic notifier when stage starts', async function () { | ||
jest.spyOn(bolt.client.chat, 'postMessage').mockImplementation(jest.fn()); | ||
jest | ||
.spyOn(DATADOG_API_INSTANCE, 'createEvent') | ||
.mockImplementation(jest.fn()); | ||
const response = await createNotifierRequest( | ||
fastify, | ||
testPayload as GenericEvent | ||
); | ||
|
||
expect(response.statusCode).toBe(200); | ||
}); | ||
|
||
it('returns 400 for an invalid source', async function () { | ||
const response = await fastify.inject({ | ||
method: 'POST', | ||
url: '/event-notifier/v1', | ||
payload: testInvalidPayload, | ||
}); | ||
expect(response.statusCode).toBe(400); | ||
}); | ||
it('returns 400 for invalid signature', async function () { | ||
const response = await fastify.inject({ | ||
method: 'POST', | ||
url: '/event-notifier/v1', | ||
headers: { | ||
'x-infra-hub-signature': 'invalid', | ||
}, | ||
payload: testPayload, | ||
}); | ||
expect(response.statusCode).toBe(400); | ||
}); | ||
|
||
it('returns 400 for no signature', async function () { | ||
const response = await fastify.inject({ | ||
method: 'POST', | ||
url: '/event-notifier/v1', | ||
payload: testPayload, | ||
}); | ||
expect(response.statusCode).toBe(400); | ||
}); | ||
|
||
describe('messageSlack tests', function () { | ||
afterEach(function () { | ||
jest.clearAllMocks(); | ||
}); | ||
|
||
it('writes to slack', async function () { | ||
const postMessageSpy = jest.spyOn(bolt.client.chat, 'postMessage'); | ||
await messageSlack(testPayload.data[0] as SlackMessage); | ||
expect(postMessageSpy).toHaveBeenCalledTimes(1); | ||
const message = postMessageSpy.mock.calls[0][0]; | ||
expect(message).toEqual({ | ||
channel: '#aaaaaa', | ||
text: 'Random text here', | ||
unfurl_links: false, | ||
}); | ||
}); | ||
}); | ||
|
||
it('checks that slack msg is sent', async function () { | ||
const postMessageSpy = jest.spyOn(bolt.client.chat, 'postMessage'); | ||
const response = await createNotifierRequest( | ||
fastify, | ||
testPayload as GenericEvent | ||
); | ||
|
||
expect(postMessageSpy).toHaveBeenCalledTimes(2); | ||
|
||
expect(response.statusCode).toBe(200); | ||
}); | ||
it('checks that dd msg is sent', async function () { | ||
const ddMessageSpy = jest.spyOn(DATADOG_API_INSTANCE, 'createEvent'); | ||
const response = await createNotifierRequest( | ||
fastify, | ||
testPayload as GenericEvent | ||
); | ||
|
||
expect(ddMessageSpy).toHaveBeenCalledTimes(1); | ||
|
||
expect(response.statusCode).toBe(200); | ||
}); | ||
}); |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.