This repository has been archived by the owner on Aug 30, 2023. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathapp.js
157 lines (127 loc) · 4.24 KB
/
app.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
const { projectID, orgSlug, integrationProjectID, sentryAPISecret } = require("./constants").constants;
const { getProjectUsers, assignIssue } = require("./apiRequests");
const verifySignature = require("./verify");
const sentry = require("./sentry");
const http = require("http");
const express = require("express");
const app = express();
const bodyParser = require("body-parser");
app.use(bodyParser.json());
// Array of all usernames with access to the given project
app.allUsers = [];
// Array of usernames queued up to be assigned to upcoming new issues
app.queuedUsers = [];
const errorWrapper = fn => {
return async (req, res, next) => {
try {
await fn(req, res, next);
} catch(err) {
next(err)
}
}
}
// When receiving a POST request from Sentry:
app.post("/", errorWrapper(async function post(request, response) {
if (!verifySignature(request, sentryAPISecret)) {
return response.status(401).send('bad signature');
}
const resource = request.get("sentry-hook-resource");
const {action} = request.body;
if (sentry) {
sentry.addBreadcrumb({
message: `Request received. resource: ${resource}, action: ${action}`,
level: sentry.Severity.Info
});
}
// If a new issue was just created
if (resource === "issue" && action === "created") {
const {id:newIssueProjectID} = request.body.data.issue.project;
// Only continue if this issue is for the project specified in .env
if (newIssueProjectID === projectID) {
// Init or reset queue if empty
if (app.queuedUsers.length === 0) {
app.queuedUsers = [...app.allUsers];
}
// Assign issue to the next user in the queue and remove user from queue
const {id:issueID} = request.body.data.issue;
await assignNextUser(issueID);
if (sentry) {
sentry.addBreadcrumb({
message: `New issue created. issueID: ${issueID}`,
level: sentry.Severity.Info
});
}
}
}
response.status(200).send("ok");
}));
// Get list of users for project, save to queue
async function init() {
if (sentry) {
sentry.addBreadcrumb({
message: `Server initialized`,
level: sentry.Severity.Info
});
}
let updatedUsers = await getProjectUsers(projectID, orgSlug);
if (sentry) {
sentry.addBreadcrumb({
message: `updatedUsers: ${updatedUsers}`,
level: sentry.Severity.Info
});
}
// If newly-retrieved list is still empty, give up!
if (updatedUsers.length === 0) {
throw new Error(`Unable to retrieve any users with access to project ${projectID}.`);
}
// Init queue and master list
app.allUsers = [...updatedUsers];
app.queuedUsers = [...updatedUsers];
}
async function assignNextUser(issueID) {
while (app.allUsers && app.allUsers.length > 0) {
// Reset queue if empty by copying from master list
if (app.queuedUsers && app.queuedUsers.length === 0) {
repopulateUserQueue();
}
const dequeuedUser = app.queuedUsers.shift();
try {
let result = await assignIssue(issueID, dequeuedUser);
// Stop loop once successfully assigned
return;
} catch (error) {
if (error.statusCode === 400) {
// If the user is invalid, pull them out of the master list and continue loop
removeUserFromList(dequeuedUser);
} else {
// For any other error code, peace out
console.error("Can't assign issue. ");
throw error;
}
}
}
throw new Error("Can't assign issue; no valid users remaining in master list. At this point, just go restart the server!");
}
function removeUserFromList(targetUser) {
app.allUsers = app.allUsers.filter(user => user !== targetUser);
}
function repopulateUserQueue() {
// Reset queuedUsers with list of available users
app.queuedUsers = [...app.allUsers];
}
app.use(function onError(err, req, res, next) {
const errorId = sentry.captureException(err);
console.error(err);
res.status(500);
if (errorId && integrationProjectID) {
res.set("Sentry-Hook-Error", errorId);
res.set("Sentry-Hook-Project", integrationProjectID);
}
res.send();
});
app.listen = async function() {
await init();
let server = http.createServer(this);
return server.listen.apply(server, arguments);
};
module.exports = app;