Skip to content

Commit 48d5928

Browse files
add additinal error handling
1 parent f5692fd commit 48d5928

1 file changed

Lines changed: 108 additions & 79 deletions

File tree

src/services/gitHub.ts

Lines changed: 108 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,23 @@ import { AsyncReturnType } from "../utility";
99

1010
const config = Config();
1111

12-
function MakeTeamNameSafe(teamName:string) {
12+
function MakeTeamNameSafe(teamName: string) {
1313
// There are most likely much more than this...
1414
const specialCharacterRemoveRegexp = /[ &%#@!$]/g;
1515
const saferName = teamName.replaceAll(specialCharacterRemoveRegexp, '-');
1616

1717
const multiReplaceRegexp = /(-){2,}/g;
1818
const removeTrailingDashesRegexp = /-+$/g
19-
19+
2020
const withDuplicatesRemoved = saferName.replaceAll(multiReplaceRegexp, "-").replaceAll(removeTrailingDashesRegexp, "");
21-
21+
2222
return withDuplicatesRemoved;
2323
}
2424

2525
async function GetOrgClient(installationId: number): Promise<InstalledClient> {
2626
interface options {
27-
method:string
28-
url:string
27+
method: string
28+
url: string
2929
}
3030

3131
// TODO: look further into this... it seems like it would be best if
@@ -41,31 +41,31 @@ async function GetOrgClient(installationId: number): Promise<InstalledClient> {
4141
installationId
4242
},
4343
throttle: {
44-
onRateLimit: (retryAfter:number, options:options, octokit:Octokit, retryCount:number) => {
45-
octokit.log.warn(
46-
`Request quota exhausted for request ${options.method} ${options.url}`
47-
);
48-
49-
if (retryCount < 10) {
50-
// retries 10 times
51-
octokit.log.info(`Retrying after ${retryAfter} seconds!`);
52-
return true;
53-
}
44+
onRateLimit: (retryAfter: number, options: options, octokit: Octokit, retryCount: number) => {
45+
octokit.log.warn(
46+
`Request quota exhausted for request ${options.method} ${options.url}`
47+
);
48+
49+
if (retryCount < 10) {
50+
// retries 10 times
51+
octokit.log.info(`Retrying after ${retryAfter} seconds!`);
52+
return true;
53+
}
5454
},
55-
onSecondaryRateLimit: (retryAfter:number, options:options, octokit:Octokit) => {
56-
// does not retry, only logs a warning
57-
octokit.log.warn(
58-
`SecondaryRateLimit detected for request ${options.method} ${options.url}. Retry after ${retryAfter} seconds`
59-
);
55+
onSecondaryRateLimit: (retryAfter: number, options: options, octokit: Octokit) => {
56+
// does not retry, only logs a warning
57+
octokit.log.warn(
58+
`SecondaryRateLimit detected for request ${options.method} ${options.url}. Retry after ${retryAfter} seconds`
59+
);
6060

61-
return true;
61+
return true;
6262
},
63-
}
63+
}
6464
})
6565

6666
const orgName = await installedOctokit.rest.apps.getInstallation({ installation_id: installationId });
6767

68-
if(!orgName.data.account?.login) {
68+
if (!orgName.data.account?.login) {
6969
// TODO: throw custom wrapped error...
7070
throw new Error("Login cannot be null for orgs")
7171
}
@@ -87,29 +87,37 @@ function authenticatedClient() {
8787
}
8888

8989
async function GetInstallations(client: Octokit): Promise<Org[]> {
90-
const installationList = await client.paginate(client.rest.apps.listInstallations, {
91-
per_page: 100
92-
})
90+
try {
91+
const installationList = await client.paginate(client.rest.apps.listInstallations, {
92+
per_page: 100
93+
})
9394

94-
const mappedOrgs = installationList.map(i => {
95-
return {
96-
id: i.id,
97-
orgName: i.account?.login ?? "",
98-
suspendedAt: i.suspended_at,
99-
suspendedBy: i.suspended_by?.login
100-
}
101-
});
95+
// TODO: this function is doing too much, it is not
96+
// just a simple facade anymore...
97+
const mappedOrgs = installationList.map(i => {
98+
return {
99+
id: i.id,
100+
orgName: i.account?.login ?? "",
101+
suspendedAt: i.suspended_at,
102+
suspendedBy: i.suspended_by?.login
103+
}
104+
});
102105

103-
const suspendedInstallations = mappedOrgs.filter(i => i.suspendedAt != undefined);
106+
const suspendedInstallations = mappedOrgs.filter(i => i.suspendedAt != undefined);
104107

105-
console.log(`The following installations have been suspended: ${JSON.stringify(suspendedInstallations)}`)
108+
console.log(`The following installations have been suspended: ${JSON.stringify(suspendedInstallations)}`)
106109

107-
return mappedOrgs.filter(i => i.suspendedAt == undefined).map(i => {
108-
return {
109-
id: i.id,
110-
orgName: i.orgName
111-
}
112-
});
110+
return mappedOrgs.filter(i => i.suspendedAt == undefined).map(i => {
111+
return {
112+
id: i.id,
113+
orgName: i.orgName
114+
}
115+
});
116+
}
117+
catch {
118+
// TODO: log error
119+
return [] as Org[]
120+
}
113121
}
114122

115123
async function GetAppConfig(client: Octokit): Promise<AppConfig> {
@@ -134,7 +142,7 @@ async function GetAppConfig(client: Octokit): Promise<AppConfig> {
134142

135143
const filesResponse = await appOctokit.rest.repos.getContent(getContentRequest);
136144

137-
const potentialFiles = filesResponse.data;
145+
const potentialFiles = filesResponse.data;
138146

139147
if (!Array.isArray(potentialFiles)) {
140148
throw new Error("AppConfig not found!")
@@ -228,25 +236,25 @@ class InstalledGitHubClient implements InstalledClient {
228236
}
229237
}
230238

231-
public async IsUserMember(id: string): Response<boolean> {
239+
public async IsUserMember(id: string): Response<boolean> {
232240
try {
233241
await this.gitHubClient.rest.orgs.checkMembershipForUser({
234242
org: this.orgName,
235243
username: id
236244
})
237245
}
238-
catch{
246+
catch {
239247
// TODO: actually catch exception and investigate...
240248
// not all exceptions could mean that the user is not a member
241249
return {
242250
successful: true,
243251
data: false
244252
}
245253
}
246-
254+
247255
return {
248256
successful: true,
249-
data: true
257+
data: true
250258
}
251259
}
252260

@@ -258,7 +266,7 @@ class InstalledGitHubClient implements InstalledClient {
258266
const teams = response.map(i => {
259267
return {
260268
Id: i.id,
261-
Name: i.name
269+
Name: i.name
262270
}
263271
});
264272

@@ -271,26 +279,40 @@ class InstalledGitHubClient implements InstalledClient {
271279
public async AddTeamMember(team: GitHubTeamName, id: GitHubId): Response<unknown> {
272280
const safeTeam = MakeTeamNameSafe(team);
273281

274-
await this.gitHubClient.rest.teams.addOrUpdateMembershipForUserInOrg({
275-
org: this.orgName,
276-
team_slug: safeTeam,
277-
username: id
278-
})
282+
try {
283+
await this.gitHubClient.rest.teams.addOrUpdateMembershipForUserInOrg({
284+
org: this.orgName,
285+
team_slug: safeTeam,
286+
username: id
287+
})
279288

280-
return {
281-
successful: true,
282-
// TODO: make this type better to avoid nulls...
283-
data: null
289+
return {
290+
successful: true,
291+
// TODO: make this type better to avoid nulls...
292+
data: null
293+
}
294+
}
295+
catch {
296+
return {
297+
successful: false
298+
}
284299
}
285300
}
286301

287-
public async CreateTeam(team: GitHubTeamName, description:string): Response<unknown> {
288-
await this.gitHubClient.rest.teams.create({
289-
name: team,
290-
org: this.orgName,
291-
description,
292-
privacy:"closed"
293-
})
302+
public async CreateTeam(team: GitHubTeamName, description: string): Response<unknown> {
303+
try {
304+
await this.gitHubClient.rest.teams.create({
305+
name: team,
306+
org: this.orgName,
307+
description,
308+
privacy: "closed"
309+
})
310+
}
311+
catch {
312+
return {
313+
successful: false
314+
}
315+
}
294316

295317
return {
296318
successful: true,
@@ -306,7 +328,7 @@ class InstalledGitHubClient implements InstalledClient {
306328
})
307329

308330
return {
309-
successful:true,
331+
successful: true,
310332
data: response.data.login
311333
}
312334
}
@@ -322,7 +344,7 @@ class InstalledGitHubClient implements InstalledClient {
322344

323345
const response = await this.gitHubClient.paginate(this.gitHubClient.rest.teams.listMembersInOrg, {
324346
org: this.orgName,
325-
team_slug: safeTeam,
347+
team_slug: safeTeam,
326348
})
327349

328350
return {
@@ -336,16 +358,23 @@ class InstalledGitHubClient implements InstalledClient {
336358
public async RemoveTeamMemberAsync(team: GitHubTeamName, user: GitHubId): Response<unknown> {
337359
const safeTeam = MakeTeamNameSafe(team);
338360

339-
await this.gitHubClient.rest.teams.removeMembershipForUserInOrg({
340-
team_slug: safeTeam,
341-
org: this.orgName,
342-
username: user
343-
})
361+
try {
362+
await this.gitHubClient.rest.teams.removeMembershipForUserInOrg({
363+
team_slug: safeTeam,
364+
org: this.orgName,
365+
username: user
366+
})
344367

345-
return {
346-
successful: true,
347-
// TODO: make this type better to avoid nulls...
348-
data: null
368+
return {
369+
successful: true,
370+
// TODO: make this type better to avoid nulls...
371+
data: null
372+
}
373+
}
374+
catch {
375+
return {
376+
successful: false
377+
}
349378
}
350379
}
351380

@@ -356,7 +385,7 @@ class InstalledGitHubClient implements InstalledClient {
356385
org: this.orgName,
357386
privacy: "closed",
358387
team_slug: safeTeam,
359-
description: description
388+
description: description
360389
})
361390

362391
return {
@@ -384,11 +413,11 @@ class InstalledGitHubClient implements InstalledClient {
384413
path: ""
385414
};
386415

387-
let filesResponse : AsyncReturnType<typeof this.gitHubClient.rest.repos.getContent>;
416+
let filesResponse: AsyncReturnType<typeof this.gitHubClient.rest.repos.getContent>;
388417

389-
try{
418+
try {
390419
filesResponse = await this.gitHubClient.rest.repos.getContent(getContentRequest);
391-
}
420+
}
392421
catch {
393422
return {
394423
successful: false

0 commit comments

Comments
 (0)