-
Notifications
You must be signed in to change notification settings - Fork 20
/
functions.js
230 lines (218 loc) · 6.92 KB
/
functions.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
/**
* Filter Pull Requests with requested reviewers only
* @param {Array} pullRequests Pull Requests to filter
* @return {Array} Pull Requests to review
*/
function getPullRequestsToReview(pullRequests) {
return pullRequests.filter((pr) => pr.requested_reviewers.length || pr.requested_teams.length);
}
/**
* Filter Pull Requests without a specific label
* @param {Array} pullRequests Pull Requests to filter
* @param {String} ignoreLabels Pull Request label(s) to ignore
* @return {Array} Pull Requests without a specific label
*/
function getPullRequestsWithoutLabel(pullRequests, ignoreLabels) {
const ignoreLabelsArray = ignoreLabels.replace(/\s*,\s*/g, ',').split(','); // ['ignore1', 'ignore2', ...]
const ignoreLabelsSet = new Set(ignoreLabelsArray);
return pullRequests.filter((pr) => !((pr.labels || []).some((label) => ignoreLabelsSet.has(label.name))));
}
/**
* Count Pull Requests reviewers
* @param {Array} pullRequests Pull Requests
* @return {Number} Reviewers number
*/
function getPullRequestsReviewersCount(pullRequests) {
return pullRequests.reduce((total, pullRequest) => (total + pullRequest.requested_reviewers.length), 0);
}
/**
* Create an Array of Objects with { url, title, login } properties from a list of Pull Requests
* @param {Array} pullRequestsToReview Pull Requests
* @return {Array} Array of Objects with { url, title, login } properties
*/
function createPr2UserArray(pullRequestsToReview) {
const pr2user = [];
for (const pr of pullRequestsToReview) {
for (const user of pr.requested_reviewers) {
pr2user.push({
url: pr.html_url,
title: pr.title,
login: user.login,
});
}
for (const team of pr.requested_teams) {
pr2user.push({
url: pr.html_url,
title: pr.title,
login: team.slug,
});
}
}
return pr2user;
}
/**
* Check if the github-provider-map string is in correct format
* @param {String} str String to be checked to be in correct format
* @return {Boolean} String validity as boolean
*/
function checkGithubProviderFormat(str) {
// Pattern made with the help of ChatGPT
const az09 = '[A-z0-9_\\-@\\.]+';
const pattern = new RegExp(`^${az09}:${az09}(,\\s*${az09}:${az09})*$`, 'm');
return pattern.test(str);
}
/**
* Convert a string like "name1:ID123,name2:ID456" to an Object { name1: "ID123", name2: "ID456"}
* @param {String} str String to convert to Object
* @return {Object} Object with usernames as properties and IDs as values
*/
function stringToObject(str) {
const map = {};
if (!str) {
return map;
}
const users = str.replace(/[\s\r\n]+/g, '').split(',');
users.forEach((user) => {
const [github, provider] = user.split(':');
map[github] = provider;
});
return map;
}
/**
* Create a pretty message to print
* @param {Array} pr2user Array of Object with these properties { url, title, login }
* @param {Object} github2provider Object containing usernames as properties and IDs as values
* @param {String} provider Service to use: slack or msteams
* @return {String} Pretty message to print
*/
function prettyMessage(pr2user, github2provider, provider) {
let message = '';
for (const obj of pr2user) {
switch (provider) {
case 'slack': {
const mention = github2provider[obj.login] ?
`<@${github2provider[obj.login]}>` :
`@${obj.login}`;
message += `Hey ${mention}, the PR "${obj.title}" is waiting for your review: ${obj.url}\n`;
break;
}
case 'rocket': {
const mention = github2provider[obj.login] ?
`<@${github2provider[obj.login]}>` :
`@${obj.login}`;
message += `Hey ${mention}, the PR "${obj.title}" is waiting for your review: ${obj.url}\n`;
break;
}
case 'msteams': {
const mention = github2provider[obj.login] ?
`<at>${obj.login}</at>` :
`@${obj.login}`;
message += `Hey ${mention}, the PR "${obj.title}" is waiting for your review: [${obj.url}](${obj.url}) \n`;
break;
}
}
}
return message;
}
/**
* Create an array of MS teams mention objects for users requested in a review
* Docs: https://bit.ly/3UlOoqo
* @param {Object} github2provider Object containing usernames as properties and IDs as values
* @param {Array} pr2user Array of Object with these properties { url, title, login }
* @return {Array} MS teams mention objects
*/
function getTeamsMentions(github2provider, pr2user) {
const mentions = [];
// Add mentions array only if the map is provided, or no notification is sent
if (Object.keys(github2provider).length > 0) {
for (const user of pr2user) {
// mentioed property needs id and name, or no notification is sent
if (github2provider[user.login]) {
mentions.push({
type: `mention`,
text: `<at>${user.login}</at>`,
mentioned: {
id: github2provider[user.login],
name: user.login,
},
});
}
}
}
return mentions;
}
/**
* Formats channel and slack message text into a request object
* @param {String} channel channel to send the message to
* @param {String} message slack message text
* @return {Object} Slack message data object
*/
function formatSlackMessage(channel, message) {
const messageData = {
channel: channel,
username: 'Pull Request reviews reminder',
text: message,
};
return messageData;
}
/**
* Formats channel and rocket message text into a request object
* @param {String} channel channel to send the message to
* @param {String} message rocket message text
* @return {Object} rocket message data object
*/
function formatRocketMessage(channel, message) {
const messageData = {
channel: channel,
username: 'Pull Request reviews reminder',
text: message,
};
return messageData;
}
/**
* Format the MS Teams message request object
* Docs: https://bit.ly/3UlOoqo
* @param {String} message formatted message string
* @param {Array} [mentionsArray] teams mention objects array
* @return {Object} Ms Teams message data object
*/
function formatTeamsMessage(message, mentionsArray = []) {
const messageData = {
type: `message`,
attachments: [
{
contentType: `application/vnd.microsoft.card.adaptive`,
content: {
type: `AdaptiveCard`,
body: [
{
type: `TextBlock`,
text: message,
wrap: true,
},
],
$schema: `http://adaptivecards.io/schemas/adaptive-card.json`,
version: `1.0`,
msteams: {
width: 'Full',
entities: mentionsArray,
},
},
},
],
};
return messageData;
}
module.exports = {
getPullRequestsToReview,
getPullRequestsWithoutLabel,
getPullRequestsReviewersCount,
createPr2UserArray,
checkGithubProviderFormat,
stringToObject,
prettyMessage,
getTeamsMentions,
formatTeamsMessage,
formatRocketMessage,
formatSlackMessage,
};