Skip to content

Commit b7b1822

Browse files
feat: notify on slack when product review label is added (#82)
1 parent ddcc8bc commit b7b1822

File tree

8 files changed

+150
-7
lines changed

8 files changed

+150
-7
lines changed

.codesandbox/tasks.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@
1111
"tasks": {
1212
"server": {
1313
"name": "server",
14-
"command": "npm start"
14+
"command": "npm run staging"
1515
},
1616
"lint": {
1717
"name": "lint",
1818
"command": "npm run lint"
1919
},
2020
"n": {
2121
"name": "n",
22-
"command": "npm start",
22+
"command": "npm run staging",
2323
"runAtStart": true,
2424
"preview": {
2525
"port": 3000

.env.sample

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ LOGIN_USER=username
33
LOGIN_PASSWORD=strongpassword
44
DEFAULT_GITHUB_ORG=Git-Commit-Show
55
ONE_CLA_PER_ORG=true
6+
SLACK_DEFAULT_MESSAGE_CHANNEL_WEBHOOK_URL=https://hooks.slack.com/services/T05487DUMMY/B59DUMMY1U/htdsEdsdf7CNeDUMMY
67
GITHUB_BOT_USERS=dependabot[bot],devops-github-rudderstack
78
GITHUB_ORG_MEMBERS=
89
APP_ID="11"

CODEOWNERS

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +0,0 @@
1-
* @github/ecosystem-apps-reviewers

app.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
isCLARequired,
1414
isMessageAfterMergeRequired,
1515
} from "./src/helpers.js";
16+
import Slack from "./src/services/Slack.js";
1617

1718
try {
1819
const packageJson = await import("./package.json", {
@@ -117,10 +118,15 @@ app.webhooks.on("pull_request.labeled", async ({ octokit, payload }) => {
117118
body: comment,
118119
});
119120
}
121+
if(label.name?.toLowerCase() === "product review" && Slack.isConfigured()) {
122+
console.log("Sending message to the product review channel");
123+
const message = `:mag: <${pull_request.html_url}|#${pull_request.number}: ${pull_request.title}> by ${pull_request.user?.login}`;
124+
await Slack.sendMessage(message);
125+
}
120126
} catch (error) {
121127
if (error.response) {
122128
console.error(
123-
`Error! Status: ${error.response.status}. Message: ${error.response.data.message}`
129+
`Error! Status: ${error.response?.status}. Message: ${error.response?.data?.message}`
124130
);
125131
} else {
126132
console.error(error);
@@ -166,7 +172,7 @@ app.webhooks.on("pull_request.closed", async ({ octokit, payload }) => {
166172
app.webhooks.on("issues.opened", async ({ octokit, payload }) => {
167173
console.log(`Received a new issue event for #${payload.issue.number}`);
168174
try {
169-
// Docs for octokit.rest.issues.createComment - https://github.com/octokit/plugin-rest-endpoint-methods.js/tree/main/docs/issues/createComment.md
175+
// Docs for octokit.rest.issues.createComment - https://github.com/octokit/plugin-rest-endpoint-methods.js/tree/main/docs/issues/createComment.md
170176
await octokit.rest.issues.createComment({
171177
owner: payload.repository.owner.login,
172178
repo: payload.repository.name,

package-lock.json

Lines changed: 58 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
"type": "module",
77
"scripts": {
88
"lint": "standard",
9+
"proxy": "PORT=3000 & ./node_modules/.bin/smee -u $SMEE_URL -t https://$HOSTNAME-3000.csb.app/api/webhook",
910
"start": "node app.js",
11+
"staging": "npm run proxy & npm start",
1012
"test": "RUN_E2E_TESTS=true ./node_modules/.bin/mocha test/lifecycle.test.js test/**/*.test.js",
1113
"test:integration": "./node_modules/.bin/mocha test/lifecycle.test.js test/integration/**/*.test.js",
1214
"test:e2e": "RUN_E2E_TESTS=true ./node_modules/.bin/mocha test/lifecycle.test.js test/e2e/**/*.test.js"
@@ -16,13 +18,14 @@
1618
"chai-http": "^5.0.0",
1719
"mocha": "^10.7.3",
1820
"sinon": "^19.0.2",
21+
"smee-client": "^4.3.1",
1922
"standard": "^17.0.0"
2023
},
2124
"dependencies": {
2225
"dotenv": "^16.0.3",
2326
"octokit": "^3.1.2"
2427
},
2528
"engines": {
26-
"node": ">=20"
29+
"node": ">=20.19.0"
2730
}
2831
}

src/services/Slack.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/**
2+
* Service for interacting with Slack
3+
*/
4+
5+
class Slack {
6+
constructor() {}
7+
8+
static isConfigured() {
9+
return !!process.env.SLACK_DEFAULT_MESSAGE_CHANNEL_WEBHOOK_URL;
10+
}
11+
12+
static async sendMessage(
13+
message,
14+
{ webhookUrl = process.env.SLACK_DEFAULT_MESSAGE_CHANNEL_WEBHOOK_URL } = {}
15+
) {
16+
if (!webhookUrl) {
17+
throw new Error("Slack webhook URL is not set");
18+
}
19+
20+
if (!message) {
21+
throw new Error("Message is not set");
22+
}
23+
24+
const payload = { text: message };
25+
26+
const response = await fetch(webhookUrl, {
27+
method: "POST",
28+
headers: {
29+
"Content-Type": "application/json",
30+
},
31+
body: JSON.stringify(payload),
32+
});
33+
34+
if (!response.ok) {
35+
throw new Error(
36+
`Slack API error: ${response.status} ${response.statusText}`
37+
);
38+
}
39+
console.log(`Successfully sent message to Slack: ${message}`);
40+
}
41+
}
42+
43+
export default Slack;

test/integration/slack.test.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/**
2+
* E2E tests for the slack related services.
3+
*/
4+
5+
import { expect } from 'chai';
6+
import { describe, it } from 'mocha';
7+
import Slack from '../../src/services/Slack.js';
8+
9+
describe('Slack Services', function () {
10+
this.timeout(40000);
11+
12+
describe('sendMessage', function () {
13+
// Happy path
14+
it('should send a message to the default channel', async function () {
15+
const res = await Slack.sendMessage(':mag: <https://github.com/gitcommitshow/rudder-github-app/pull/82|#82: Test message from our GitHub App>\n*Author:* gitcommitshow\n*Created:* Sep 18, 2025 at 10:00 AM\n\n<!channel>', {
16+
webhookUrl: "https://hooks.slack.com/services/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"
17+
});
18+
expect(res).to.not.throw;
19+
});
20+
21+
// Error path 1 - no message
22+
it('should throw an error if the message is not set', async function () {
23+
expect(Slack.sendMessage(null, {
24+
webhookUrl: "https://hooks.slack.com/services/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"
25+
})).to.throw;
26+
});
27+
28+
// Error path 2 - no webhook url
29+
it('should throw an error if the webhook url is not set', async function () {
30+
expect(Slack.sendMessage("testing error path 2 - no webhook url")).to.throw;
31+
});
32+
});
33+
34+
})

0 commit comments

Comments
 (0)