Skip to content
This repository has been archived by the owner on Jan 29, 2024. It is now read-only.

Commit

Permalink
feat: filter out dependabot notifications (#599)
Browse files Browse the repository at this point in the history
* feat: filter out dependabot notifications

* fix: remove not helpful checks

* fix: clean req schema add sinon assert
  • Loading branch information
brainrepo committed Apr 25, 2023
1 parent 811805f commit a3e39da
Show file tree
Hide file tree
Showing 6 changed files with 256 additions and 16 deletions.
4 changes: 4 additions & 0 deletions src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,7 @@ export const notificationConfig = rcfile('notification-config', {
cwd: join(process.cwd(), 'config'),
configFileName: 'notification-config',
})

// Adding a new github username here all the creation / changes on the PRs
// and Issues from this author will be excluded and not notified.
export const excludedAuthors = ['dependabot']
3 changes: 3 additions & 0 deletions src/graphql.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ export const getActivityById = async ({ graphqlClient, id }) => {
number
title
url
author {
login
}
}
}
}`,
Expand Down
6 changes: 5 additions & 1 deletion src/slackbot.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { getRawMessage, formatMessage } from './messages.js'
import { notificationConfig } from './config.js'
import { excludedAuthors, notificationConfig } from './config.js'
import {
getProjectById,
getActivityById,
Expand Down Expand Up @@ -35,6 +35,10 @@ export async function sendNotification({ request, app }) {

const { node } = await getItem(request)

if (excludedAuthors.includes(node.content?.author?.login)) {
return
}

const message = formatMessage({
content_type: getContentType(request),
node,
Expand Down
12 changes: 6 additions & 6 deletions test/fixtures/graphql/getProjectItemByIdResponse.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
export default {
export default (user = 'testuser') => ({
node: {
creator: {
url: 'https://github.com/testuser',
login: 'testuser',
url: `https://github.com/${user}`,
login: user,
},
id: 'PVTI_lADOBpWafM4AEgSvzgB_LQk',
project: {
Expand All @@ -23,8 +23,8 @@ export default {
nodes: [],
},
author: {
url: 'https://github.com/testuser',
login: 'testuser',
url: `https://github.com/${user}`,
login: user,
name: 'Test User',
},
id: 'I_kwDOHwYncM5PZJ_7',
Expand Down Expand Up @@ -55,4 +55,4 @@ export default {
],
},
},
}
})
84 changes: 84 additions & 0 deletions test/fixtures/webhook/itemCreatedDependabot.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
export default {
action: 'created',
projects_v2_item: {
id: 8156154,
node_id: 'dependabot_node',
project_node_id: 'PVT_kwDOBpWafM4AEgSx_x',
content_node_id: 'I_kwDOHwYncM5PMB7x',
content_type: 'Issue',
creator: {
login: 'dependabot',
id: 29484805,
node_id: 'MDQ6VXNlcjI5NDg0ODA1a',
avatar_url: 'https://avatars.githubusercontent.com/u/29484805?v=4',
gravatar_id: '',
url: 'https://api.github.com/users/some-github-user',
html_url: 'https://github.com/some-github-user',
followers_url: 'https://api.github.com/users/some-github-user/followers',
following_url:
'https://api.github.com/users/some-github-user/following{/other_user}',
gists_url:
'https://api.github.com/users/some-github-user/gists{/gist_id}',
starred_url:
'https://api.github.com/users/some-github-user/starred{/owner}{/repo}',
subscriptions_url:
'https://api.github.com/users/some-github-user/subscriptions',
organizations_url: 'https://api.github.com/users/some-github-user/orgs',
repos_url: 'https://api.github.com/users/some-github-user/repos',
events_url:
'https://api.github.com/users/some-github-user/events{/privacy}',
received_events_url:
'https://api.github.com/users/some-github-user/received_events',
type: 'User',
site_admin: false,
},
created_at: '2022-08-04T12:54:31Z',
updated_at: '2022-08-04T12:54:31Z',
archived_at: null,
},
organization: {
login: 'dev-test-org-3000',
id: 110467708,
node_id: 'O_kgDOBpWafA',
url: 'https://api.github.com/orgs/dev-test-org-3000',
repos_url: 'https://api.github.com/orgs/dev-test-org-3000/repos',
events_url: 'https://api.github.com/orgs/dev-test-org-3000/events',
hooks_url: 'https://api.github.com/orgs/dev-test-org-3000/hooks',
issues_url: 'https://api.github.com/orgs/dev-test-org-3000/issues',
members_url:
'https://api.github.com/orgs/dev-test-org-3000/members{/member}',
public_members_url:
'https://api.github.com/orgs/dev-test-org-3000/public_members{/member}',
avatar_url: 'https://avatars.githubusercontent.com/u/110467708?v=4',
description: null,
},
sender: {
login: 'some-github-user',
id: 29484805,
node_id: 'MDQ6VXNlcjI5NDg0ODA1',
avatar_url: 'https://avatars.githubusercontent.com/u/29484805?v=4',
gravatar_id: '',
url: 'https://api.github.com/users/some-github-user',
html_url: 'https://github.com/some-github-user',
followers_url: 'https://api.github.com/users/some-github-user/followers',
following_url:
'https://api.github.com/users/some-github-user/following{/other_user}',
gists_url: 'https://api.github.com/users/some-github-user/gists{/gist_id}',
starred_url:
'https://api.github.com/users/some-github-user/starred{/owner}{/repo}',
subscriptions_url:
'https://api.github.com/users/some-github-user/subscriptions',
organizations_url: 'https://api.github.com/users/some-github-user/orgs',
repos_url: 'https://api.github.com/users/some-github-user/repos',
events_url:
'https://api.github.com/users/some-github-user/events{/privacy}',
received_events_url:
'https://api.github.com/users/some-github-user/received_events',
type: 'User',
site_admin: false,
},
installation: {
id: 27961269,
node_id: 'MDIzOkludGVncmF0aW9uSW5zdGFsbGF0aW9uMjc5NjEyNjk=',
},
}
163 changes: 154 additions & 9 deletions test/routes/webhook.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { createSignature } from '../../lib/verify-request.js'
import config from '../../src/config.js'
import getProjectItemByIdResponse from '../fixtures/graphql/getProjectItemByIdResponse.js'
import itemCreated from '../fixtures/webhook/itemCreated.js'
import itemCreatedDependabot from '../fixtures/webhook/itemCreatedDependabot.js'
import itemDeleted from '../fixtures/webhook/itemDeleted.js'
import itemMovedNoStatusToTodo from '../fixtures/webhook/itemMovedNoStatusToTodo.js'
import pullRequestCreated from '../fixtures/webhook/pullRequestCreated.js'
Expand Down Expand Up @@ -80,7 +81,7 @@ test('POST /webhook', async t => {
const app = await build(t, {
// the authentication function returns a function
graphqlClient: async () => () => {
return getProjectItemByIdResponse
return getProjectItemByIdResponse()
},
slackApp: async function slackApp() {
return {
Expand Down Expand Up @@ -123,7 +124,8 @@ test('POST /webhook', async t => {
'X-Hub-Signature-256': signature,
},
})
t.equal(slackStub.callCount, 1)
sinon.assert.calledOnce(slackStub)

t.equal(res.statusCode, 200)
})
t.test('item deleted', async t => {
Expand All @@ -139,7 +141,8 @@ test('POST /webhook', async t => {
'X-Hub-Signature-256': signature,
},
})
t.equal(slackStub.callCount, 1)
sinon.assert.calledOnce(slackStub)

t.equal(res.statusCode, 200)
})

Expand Down Expand Up @@ -172,7 +175,8 @@ test('POST /webhook', async t => {
'X-Hub-Signature-256': signature,
},
})
t.equal(slackStub.callCount, 1)
sinon.assert.calledOnce(slackStub)

t.equal(res.statusCode, 200)
})

Expand All @@ -192,7 +196,7 @@ test('POST /webhook', async t => {
'X-Hub-Signature-256': signature,
},
})
t.equal(slackStub.callCount, 0)
sinon.assert.notCalled(slackStub)
t.equal(res.statusCode, 200)
})

Expand All @@ -209,20 +213,160 @@ test('POST /webhook', async t => {
'X-Hub-Signature-256': signature,
},
})
t.equal(slackStub.callCount, 1)
sinon.assert.calledOnce(slackStub)

t.equal(res.statusCode, 200)
})
}
)
t.test(`doesn't do anything if it's a dependabot action`, async t => {
const slackStub = sinon.stub()
const app = await build(t, {
// the authentication function returns a function
graphqlClient: async () => () => {
return getProjectItemByIdResponse('dependabot')
},
slackApp: async function slackApp() {
return {
client: {
chat: {
postMessage: params => {
slackStub()
return params
},
},
},
}
},
})

t.test('item created', async t => {
const signature = createSignature(
itemCreatedDependabot,
config.ORG_WEBHOOK_SECRET
)
const res = await app.inject({
url: '/webhook',
method: 'POST',
body: itemCreatedDependabot,
headers: {
'X-Hub-Signature-256': signature,
},
})
sinon.assert.notCalled(slackStub)
t.equal(res.statusCode, 200)
})

t.test('item updated', async t => {
const signature = createSignature(
itemMovedNoStatusToTodo,
config.ORG_WEBHOOK_SECRET
)
const res = await app.inject({
url: '/webhook',
method: 'POST',
body: itemMovedNoStatusToTodo,
headers: {
'X-Hub-Signature-256': signature,
},
})
sinon.assert.notCalled(slackStub)
t.equal(res.statusCode, 200)
})

t.test('item deleted', async t => {
const signature = createSignature(itemDeleted, config.ORG_WEBHOOK_SECRET)
const res = await app.inject({
url: '/webhook',
method: 'POST',
body: itemDeleted,
headers: {
'X-Hub-Signature-256': signature,
},
})
sinon.assert.notCalled(slackStub)
t.equal(res.statusCode, 200)
})

t.test('pr created', async t => {
const signature = createSignature(
pullRequestCreated,
config.ORG_WEBHOOK_SECRET
)
const res = await app.inject({
url: '/webhook',
method: 'POST',
body: pullRequestCreated,
headers: {
'X-Hub-Signature-256': signature,
},
})
sinon.assert.notCalled(slackStub)
t.equal(res.statusCode, 200)
})

t.test('pr deleted', async t => {
const signature = createSignature(
pullRequestDeleted,
config.ORG_WEBHOOK_SECRET
)
const res = await app.inject({
url: '/webhook',
method: 'POST',
body: pullRequestDeleted,
headers: {
'X-Hub-Signature-256': signature,
},
})
sinon.assert.notCalled(slackStub)
t.equal(res.statusCode, 200)
})

/**
* the request should be ignored because it is of type reordered
*/
t.test('pr moved', async t => {
const signature = createSignature(
pullRequestMoved,
config.ORG_WEBHOOK_SECRET
)
const res = await app.inject({
url: '/webhook',
method: 'POST',
body: pullRequestMoved,
headers: {
'X-Hub-Signature-256': signature,
},
})
sinon.assert.notCalled(slackStub)
t.equal(res.statusCode, 200)
})

t.test('item with a non existent node_id', async t => {
const signature = createSignature(
itemInvalidNodeId,
config.ORG_WEBHOOK_SECRET
)
const res = await app.inject({
url: '/webhook',
method: 'POST',
body: itemInvalidNodeId,
headers: {
'X-Hub-Signature-256': signature,
},
})
sinon.assert.notCalled(slackStub)
t.equal(res.statusCode, 200)
})
})
t.test(
'sends graphql and slack bot requests with invalid getProjectItemById:',
async t => {
const slackStub = sinon.stub()
const graphqlClientStub = sinon.stub()
graphqlClientStub.onFirstCall().rejects(new Error())
graphqlClientStub.onSecondCall().resolves(getProjectItemByIdResponse)
graphqlClientStub.onThirdCall().resolves(getProjectItemByIdResponse)
graphqlClientStub.onSecondCall().resolves(getProjectItemByIdResponse())
graphqlClientStub.onThirdCall().resolves(getProjectItemByIdResponse())
const app = await build(t, {
graphqlClient: async () => graphqlClientStub,
slackApp: async function slackApp() {
Expand Down Expand Up @@ -252,7 +396,8 @@ test('POST /webhook', async t => {
'X-Hub-Signature-256': signature,
},
})
t.equal(slackStub.callCount, 1)
sinon.assert.calledOnce(slackStub)

t.equal(res.statusCode, 200)
})
}
Expand Down

0 comments on commit a3e39da

Please sign in to comment.