Skip to content

Commit debb101

Browse files
feat: new features added (shubhaamgupta11#20)
* feat: payload change for slack and discord * feat: added support for discord role and user id * feat: added preview images * fix: preview style changed * feat: preview added * node updated to 22 * feat: error mechanism added
1 parent 3aed368 commit debb101

15 files changed

+579
-179
lines changed

.github/workflows/example.yml

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,26 @@
1-
name: Test Action
1+
name: Repo Activity Monitor Workflow
22

33
on:
4-
workflow_dispatch:
4+
workflow_dispatch: # Allows manual triggering of the workflow
55

66
jobs:
7-
test-action:
7+
monitor-repo-activity:
88
runs-on: ubuntu-latest
99
steps:
10-
- name: Checkout the code
11-
uses: actions/checkout@v3
12-
1310
- name: Set up Node.js
14-
uses: actions/setup-node@v3
11+
uses: actions/setup-node@v4
1512
with:
16-
node-version: 18
13+
node-version: 22 # Use Node.js 22 for the workflow
1714

18-
- name: Test Local Action
19-
uses: ./ # This points to the root of your action's repo
15+
- name: Run Repo Activity Monitor
16+
uses: ./ # Points to the local action repository
2017
with:
21-
task: "monitor-issues"
22-
git_secret: ${{ secrets.GIT_SECRET }}
23-
notifier: "discord"
24-
fetch_data_interval: 2 # in hours
25-
discord_webhook_url: ${{ secrets.DISCORD_WEBHOOK_URL }}
26-
repo_owner: "facebook"
27-
repo_name: "react-native"
18+
task: "monitor-issues" # Task to monitor issues (can be "monitor-prs" as well)
19+
git_secret: ${{ secrets.GIT_SECRET }} # GitHub token
20+
repo_owner: "facebook" # Replace with the repository owner
21+
repo_name: "react-native" # Replace with the repository name
22+
fetch_data_interval: 2 # Fetch data from the last 2 hours
23+
notifier: "discord" # Use Discord for notifications
24+
discord_webhook_url: ${{ secrets.DISCORD_WEBHOOK_URL }} # Discord webhook URL
25+
discord_id_type: "role" # Type of Discord ID ("user" or "role")
26+
discord_id: "111111111111111111" # Replace with the Discord role ID to mention

README.md

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Monitor Issues & PRs with Slack/Discord Notifications
1+
# Monitor Issues & PRs with Slack+Discord Notifications
22

33
Managing activity in open-source repositories can be challenging. With a constant influx of **issues** and **pull requests**, it's easy to lose track of what needs attention—especially when working with large teams or active projects. Missed notifications or delayed responses can lead to bottlenecks, reduced contributor satisfaction, and slower project progress.
44

@@ -8,8 +8,9 @@ This [GitHub Action](https://github.com/marketplace/actions/repo-activity-monito
88

99
- Tracking new issues and pull requests.
1010
- Sending auto-generated notifications to **Slack** or **Discord**.
11-
- Customizing Slack notifications with the ability to ping specific users or groups.
12-
- Allowing Slack notifications to be sent to designated channels.
11+
- Customizing **Slack** notifications with the ability to ping specific users or groups.
12+
- Customizing **Discord** notifications with the ability to ping specific users or roles.
13+
- Allowing **Slack** notifications to be sent to designated channels.
1314

1415
With **Repo Activity Monitor**, you can stay on top of your repositories activities, streamline communication, and ensure no critical issues or pull requests fall through the cracks.
1516

@@ -30,15 +31,15 @@ jobs:
3031
runs-on: ubuntu-latest
3132
steps:
3233
- name: Set up Node.js
33-
uses: actions/setup-node@v3
34+
uses: actions/setup-node@v4
3435
with:
35-
node-version: '16'
36+
node-version: '22'
3637
- name: Monitor New Issues
37-
uses: shubhaamgupta11/repo-monitor@v0.6.0
38+
uses: shubhaamgupta11/repo-monitor@v1.0.0
3839
with:
3940
# required inputs
4041
task: "monitor-issues"
41-
git_secret: "${{ secrets.GITHUB_TOKEN }}"
42+
git_secret: "${{ secrets.GIT_SECRET }}"
4243
notifier: "slack"
4344
fetch_data_interval: 1 # Hours (must align with your cron schedule)
4445
# repo inputs
@@ -68,26 +69,54 @@ jobs:
6869
runs-on: ubuntu-latest
6970
steps:
7071
- name: Set up Node.js
71-
uses: actions/setup-node@v3
72+
uses: actions/setup-node@v4
7273
with:
73-
node-version: '16'
74+
node-version: '22'
7475
- name: Monitor New PRs
75-
uses: shubhaamgupta11/repo-monitor@v0.6.0
76+
uses: shubhaamgupta11/repo-monitor@v1.0.0
7677
with:
7778
# required inputs
7879
task: "monitor-prs"
79-
git_secret: "${{ secrets.GITHUB_TOKEN }}"
80+
git_secret: "${{ secrets.GIT_SECRET }}"
8081
notifier: "discord"
8182
fetch_data_interval: 1 # Hours (must align with your cron schedule)
8283
# repo inputs
8384
repo_owner: "<owner>"
8485
repo_name: "<repo>"
8586
# Discord-specific inputs
8687
discord_webhook_url: "${{ secrets.DISCORD_WEBHOOK_URL }}"
88+
discord_id_type: "<user/role>" # Optional: Only needed to ping someone directly.
89+
discord_id: "<user-id/role-id>" # Optional: Only needed if discord_id_type is provided.
8790
```
8891
8992
> **Note:** You can configure any notifier (slack, discord) for any task (monitor-issues, monitor-prs, etc.).
9093
94+
## Message Previews
95+
Below are examples of how the notifications look on Slack and Discord.
96+
97+
### Slack Notification Previews
98+
<details> <summary>Click to view Slack notifications</summary>
99+
100+
For Issues
101+
102+
<img src="./assets/slack-issue-notification.png" alt="Slack Issue Notification" width="400"/>
103+
104+
For Pull Requests
105+
106+
<img src="./assets/slack-pr-notification.png" alt="Slack PR Notification" width="400"/> </details>
107+
108+
### Discord Notification Previews
109+
<details> <summary>Click to view Discord notifications</summary>
110+
111+
For Issues
112+
113+
<img src="./assets/discord-issue-notification.png" alt="Discord Issue Notification" width="400"/>
114+
115+
For Pull Requests
116+
117+
<img src="./assets/discord-pr-notification.png" alt="Discord PR Notification" width="400"/> </details>
118+
119+
91120
## 🔧 Inputs
92121
93122
| Input | Description | Required | Default |
@@ -103,6 +132,8 @@ jobs:
103132
| slack_id_type | Type of Slack ID (user or group, required if notifier=`slack`). This is needed to ping someone directly. | No | None |
104133
| slack_id | user id or group id as per `slack_id_type` (required if notifier=`slack`). | No | None |
105134
| discord_webhook_url | Discord webhook URL to send notifications (required if notifier=`discord`). | No | None |
135+
| discord_id_type | Type of Discord ID (user or role, required if notifier=`discord`). This is needed to ping someone directly. | No | None |
136+
| discord_id | user id or role id as per `discord_id_type` (required if notifier=`discord`). | No | None |
106137

107138
## 📖 How It Works
108139
- The action listens for new issues or PRs in the specified GitHub repository.
@@ -119,15 +150,17 @@ jobs:
119150
- Retrieve the Channel ID and User/Group IDs.
120151
- Add these secrets to your GitHub repository:
121152
- `SLACK_BOT_TOKEN`
122-
- `SLACK_CHANNEL`
123-
- `SLACK_ID_TYPE`
124-
- `SLACK_ID`
153+
- Provide the Slack Channel ID, Slack ID Type and Slack ID in the workflow.
125154

126155
### Discord
127156

128157
- Create a [Discord Webhook](https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks).
129158
- Copy the Webhook URL.
130159
- Add the Webhook URL to your GitHub repository secrets as `DISCORD_WEBHOOK_URL`.
160+
- Retrieve the User/Role IDs.
161+
- Add these secrets to your GitHub repository:
162+
- `DISCORD_WEBHOOK_URL`
163+
- Provide the Discord Webhook URL, Discord ID Type and Discord ID in the workflow.
131164

132165
## 🔮 Roadmap
133166

@@ -139,3 +172,6 @@ jobs:
139172
## 📜 License
140173

141174
This project is licensed under the [MIT License](https://github.com/shubhaamgupta11/repo-monitor/blob/main/LICENSE).
175+
176+
## Support & Feedback
177+
If you find this action helpful, please give the repository a ⭐️ on GitHub! Your support helps us grow and continue improving. Feel free to raise issues or suggest enhancements to make this even better.

action.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,16 @@ inputs:
4141
discord_webhook_url:
4242
description: Discord webhook URL to send notifications.
4343
required: false
44+
discord_id_type:
45+
description: Type of Discord ID (user or role).
46+
required: false
47+
discord_id:
48+
description: Discord ID of the recipient (user or role).
49+
required: false
4450

4551

4652
runs:
47-
using: node16
53+
using: node22
4854
main: dist/index.js
4955

5056
outputs:

action/index.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ async function run() {
2121

2222
// Discord-specific inputs
2323
const discordWebhookUrl = core.getInput("discord_webhook_url");
24+
const discordIDType = core.getInput("discord_id_type");
25+
const discordID = core.getInput("discord_id");
2426

2527
switch (task) {
2628
case "monitor-issues":
@@ -30,7 +32,7 @@ async function run() {
3032
repo,
3133
notifier,
3234
slackConfig: { slackToken, slackChannel, slackIDType, slackID },
33-
discordConfig: { discordWebhookUrl },
35+
discordConfig: { discordWebhookUrl, discordIDType, discordID },
3436
alertTime,
3537
});
3638
break;
@@ -42,7 +44,7 @@ async function run() {
4244
repo,
4345
notifier,
4446
slackConfig: { slackToken, slackChannel, slackIDType, slackID },
45-
discordConfig: { discordWebhookUrl },
47+
discordConfig: { discordWebhookUrl, discordIDType, discordID },
4648
alertTime,
4749
});
4850
break;

action/integrations/discord.js

Lines changed: 9 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
const axios = require("axios");
22
const delay = require("../utility/delay");
3+
const { generateDiscordPayload } = require("../utility/generatePayload");
4+
35
const discordWrapper = (webhookUrl) => {
46
const sendMessage = async (content) => {
57
try {
6-
await axios.post(webhookUrl, { content });
8+
await axios.post(webhookUrl, content );
79
} catch (e) {
810
console.error("Unable to send Discord message:", e.message);
911
}
@@ -15,48 +17,26 @@ const discordWrapper = (webhookUrl) => {
1517
};
1618

1719
// Send Discord Notifications
18-
const sendDiscordNotification = async (webhookUrl, issues, repo, type) => {
20+
const sendDiscordNotification = async (webhookUrl, issues, repo, type, discordIDType, discordID) => {
1921
if (!issues.length) {
2022
console.log("No issues found within the specified time frame.");
2123
return;
2224
}
2325

2426
const discord = discordWrapper(webhookUrl);
25-
26-
for (const issue of issues) {
27-
let message = '';
28-
if (type === 'issue') {
29-
message = `
30-
:chart_with_upwards_trend: **New Issue in ${repo}**
31-
*-* **Title:** ${issue.title}
32-
*-* **Labels:** ${issue.labels
33-
.map((label) => `\`${label}\``)
34-
.join(", ")}
35-
*-* **Link:** <${issue.url}>
3627

37-
Mark as acknowledged👍 after triaging
38-
`;
39-
} else if (type === 'pr') {
40-
message = `
41-
:sparkles: **New Pull Request in ${repo}**
42-
*-* **Title:** ${issue.title}
43-
*-* **Author:** ${issue.author}
44-
*-* **Labels:** ${issue.labels
45-
.map((label) => `\`${label}\``)
46-
.join(", ")}
47-
*-* **Link:** <${issue.url}>
48-
Review and acknowledge👍
49-
`;
50-
}
28+
29+
for (const issue of issues) {
30+
let payload = generateDiscordPayload({type, repo, issue, discordIDType, discordID});
5131

5232
try {
53-
await discord.sendMessage(message);
33+
await discord.sendMessage(payload);
5434
console.log(`Posted issue "${issue.title}" to Discord.`);
5535
} catch (error) {
5636
console.error(`Failed to post issue "${issue.title}" to Discord:`, error.message);
5737
}
5838

59-
console.log("Waiting for 30 seconds before sending the next message...");
39+
// Introduce a delay between messages to avoid rate limiting
6040
await delay(5 * 1000);
6141
}
6242

action/integrations/slack.js

Lines changed: 10 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
const { WebClient } = require("@slack/web-api");
22
const delay = require("../utility/delay");
3+
const { generateSlackPayload } = require("../utility/generatePayload");
34

45
const slackWrapper = (token, channel) => {
56
const client = new WebClient(token);
@@ -41,46 +42,16 @@ const sendSlackNotification = async (
4142
const slack = slackWrapper(slackToken, slackChannel);
4243

4344
for (const issue of issues) {
44-
let message = "";
45-
let assigneeText = "";
46-
47-
if (type === "issue") {
48-
assigneeText =
49-
slackIDType === "group"
50-
? `*Assignee:* <!subteam^${slackID}> *(Mark as ACK or Done after triaging)*`
51-
: slackIDType === "user"
52-
? `*Assignee:* <@${slackID}> *(Mark as ACK or Done after triaging)*`
53-
: "";
54-
55-
message = `
56-
:chart_with_upwards_trend: *New Issue in ${repo}*
57-
*-* *Title:* ${issue.title}
58-
*-* *Labels:* ${issue.labels
59-
.map((label) => `\`${label}\``)
60-
.join(", ")}
61-
*-* *Link:* <${issue.url}|View Issue>
62-
${assigneeText}
63-
`;
64-
} else if (type === "pr") {
65-
if (slackIDType === "group") {
66-
assigneeText = `*Reviewer:* <!subteam^${slackID}> *(Review and acknowledge)*`;
67-
} else if (slackIDType === "user") {
68-
assigneeText = `*Reviewer:* <@${slackID}> *(Review and acknowledge)*`;
69-
}
70-
message = `
71-
:sparkles: *New Pull Request in ${repo}*
72-
*-* *Title:* ${issue.title}
73-
*-* *Author:* ${issue.author}
74-
*-* *Labels:* ${issue.labels
75-
.map((label) => `\`${label}\``)
76-
.join(", ")}
77-
*-* *Link:* <${issue.url}|View PR>
78-
${assigneeText}
79-
`;
80-
}
45+
const payload = generateSlackPayload({
46+
type,
47+
repo,
48+
issue,
49+
slackIDType,
50+
slackID,
51+
});
8152

8253
try {
83-
await slack.sendMessage({ text: message });
54+
await slack.sendMessage(payload);
8455
console.log(`Posted issue "${issue.title}" to Slack.`);
8556
} catch (error) {
8657
console.error(
@@ -89,7 +60,7 @@ const sendSlackNotification = async (
8960
);
9061
}
9162

92-
console.log("Waiting for 30 seconds before sending the next message...");
63+
// Introduce a delay between messages to avoid rate limiting
9364
await delay(5 * 1000);
9465
}
9566

action/monitor-new-issue.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ const fetchNewIssues = async (gitToken, owner, repo, alertTime) => {
4646
...issues.map((issue) => ({
4747
title: issue.title,
4848
url: issue.html_url,
49+
avatar_url: issue.user.avatar_url,
50+
author: issue.user.login,
4951
createdAt: issue.created_at,
5052
labels: issue.labels.map((label) => label.name),
5153
comments: issue.comments,
@@ -60,7 +62,7 @@ const fetchNewIssues = async (gitToken, owner, repo, alertTime) => {
6062

6163
return newIssues;
6264
} catch (error) {
63-
console.error("Error fetching issues:", error.message);
65+
console.error("Error fetching issues:", error.response.data);
6466
return [];
6567
}
6668
};
@@ -104,12 +106,14 @@ async function monitorIssues({
104106
} else if (notifier === "discord") {
105107
const {
106108
discordWebhookUrl,
109+
discordIDType,
110+
discordID,
107111
} = discordConfig;
108112
console.log(
109113
"🔔 Sending notifications to Discord for issues:",
110114
issues.map((issue) => issue.title)
111115
);
112-
await sendDiscordNotification(discordWebhookUrl, issues, repo, "issue");
116+
await sendDiscordNotification(discordWebhookUrl, issues, repo, "issue", discordIDType, discordID);
113117
} else {
114118
throw new Error("Unsupported notifier. Use 'slack' or 'discord'.");
115119
}

0 commit comments

Comments
 (0)