Skip to content

Commit ac5ea5a

Browse files
💡 make org config issues clearer (#85)
* This adds a new response state- bad_config- so that those impacted by this application can more easily identify what problem their org sync is running into.
1 parent db9341e commit ac5ea5a

File tree

4 files changed

+65
-21
lines changed

4 files changed

+65
-21
lines changed

src/services/gitHub.ts

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Octokit } from "octokit";
22
import { createAppAuth } from "@octokit/auth-app";
33
import { Config } from "../config";
4-
import { AddMemberResponse, CopilotAddResponse, GitHubClient, GitHubId, GitHubTeamId, InstalledClient, Org, OrgInvite, OrgRoles, RemoveMemberResponse, Response } from "./gitHubTypes";
4+
import { AddMemberResponse, CopilotAddResponse, GitHubClient, GitHubId, GitHubTeamId, InstalledClient, Org, OrgConfigResponse, OrgInvite, OrgRoles, RemoveMemberResponse, Response } from "./gitHubTypes";
55
import { AppConfig } from "./appConfig";
66
import yaml from "js-yaml";
77
import { throttling } from "@octokit/plugin-throttling";
@@ -615,7 +615,7 @@ class InstalledGitHubClient implements InstalledClient {
615615

616616
}
617617

618-
public async GetConfigurationForInstallation(): Response<OrgConfig> {
618+
public async GetConfigurationForInstallation(): OrgConfigResponse {
619619
// TODO: this function doesn't really belong on this class...
620620
// i.e., it doesn't fit with a "GitHub Facade"
621621
const getContentRequest = {
@@ -631,15 +631,17 @@ class InstalledGitHubClient implements InstalledClient {
631631
}
632632
catch {
633633
return {
634-
successful: false
634+
successful: false,
635+
state: "NoConfig"
635636
}
636637
}
637638

638639
const potentialFiles = filesResponse.data;
639640

640641
if (!Array.isArray(potentialFiles)) {
641642
return {
642-
successful: false
643+
successful: false,
644+
state: "NoConfig"
643645
}
644646
}
645647

@@ -649,7 +651,9 @@ class InstalledGitHubClient implements InstalledClient {
649651

650652
if (onlyConfigFiles.length != 1) {
651653
return {
652-
successful: false
654+
successful: false,
655+
state: "BadConfig",
656+
message: "Multiple configuration files are not supported at this point in time."
653657
}
654658
}
655659

@@ -664,15 +668,24 @@ class InstalledGitHubClient implements InstalledClient {
664668

665669
if (Array.isArray(contentData) || contentData.type != "file") {
666670
return {
667-
successful: false
671+
successful: false,
672+
state: "BadConfig"
668673
}
669674
}
670675

671-
const configuration = yaml.load(Buffer.from(contentData.content, 'base64').toString()) as OrgConfigurationOptions;
672-
673-
return {
674-
successful: true,
675-
data: new OrgConfig(configuration)
676+
try {
677+
const configuration = yaml.load(Buffer.from(contentData.content, 'base64').toString()) as OrgConfigurationOptions;
678+
return {
679+
successful: true,
680+
data: new OrgConfig(configuration)
681+
}
682+
}
683+
catch {
684+
return {
685+
successful: false,
686+
state: "BadConfig",
687+
message: "Error parsing configuration- check configuration file for validity: https://github.com/cloudpups/github-teams-user-sync/blob/main/docs/OrganizationConfiguration.md"
688+
}
676689
}
677690
}
678691
}

src/services/gitHubCache.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { CacheClient } from "../app";
22
import { ILogger } from "../logging";
3-
import { AddMemberResponse, CopilotAddResponse, GitHubId, GitHubTeamId, InstalledClient, OrgInvite, OrgRoles, RemoveMemberResponse, Response } from "./gitHubTypes";
3+
import { AddMemberResponse, CopilotAddResponse, GitHubId, GitHubTeamId, InstalledClient, OrgConfigResponse, OrgInvite, OrgRoles, RemoveMemberResponse, Response } from "./gitHubTypes";
44
import { OrgConfig } from "./orgConfig";
55

66
export class GitHubClientCache implements InstalledClient {
@@ -146,7 +146,7 @@ export class GitHubClientCache implements InstalledClient {
146146
return this.client.AddSecurityManagerTeam(team);
147147
}
148148

149-
GetConfigurationForInstallation(): Response<OrgConfig> {
149+
GetConfigurationForInstallation(): OrgConfigResponse {
150150
return this.client.GetConfigurationForInstallation();
151151
}
152152
}

src/services/gitHubTypes.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,19 @@ export type OrgInvite = {
1919
GitHubUser: string
2020
}
2121

22+
export type OrgConfigResponseSuccess = {
23+
successful: true,
24+
data: OrgConfig
25+
}
26+
27+
export type OrgConfigResponseBad = {
28+
successful: false,
29+
state: "NoConfig" | "BadConfig",
30+
message?: string
31+
}
32+
33+
export type OrgConfigResponse = Promise<OrgConfigResponseSuccess | OrgConfigResponseBad>;
34+
2235
export interface InstalledClient {
2336
GetCurrentOrgName(): string
2437
GetCurrentRateLimit(): Promise<{ remaining: number }>
@@ -32,7 +45,7 @@ export interface InstalledClient {
3245
RemoveTeamMemberAsync(team: GitHubTeamName, user: GitHubId): RemoveMemberResponse
3346
UpdateTeamDetails(team: GitHubTeamName, description: string): Response
3447
AddSecurityManagerTeam(team: GitHubTeamName): Promise<unknown>
35-
GetConfigurationForInstallation(): Response<OrgConfig>
48+
GetConfigurationForInstallation(): OrgConfigResponse
3649
SetOrgRole(id: GitHubId, role: OrgRoles): Response
3750
GetPendingOrgInvites():Response<OrgInvite[]>
3851
CancelOrgInvite(invite:OrgInvite): Response

src/services/githubSync.ts

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// REMEMBER TO REPLACE '_' with '-' for GitHub Names! 🤦‍♂️
22

3+
import e from "express";
34
import { Log, LogError } from "../logging";
45
import { AppConfig } from "./appConfig";
56
import { CopilotAddResponse, FailedResponse, GitHubId, InstalledClient, OrgInvite } from "./gitHubTypes";
@@ -167,7 +168,7 @@ async function SynchronizeGitHubTeam(installedGitHubClient: InstalledClient, tea
167168

168169
type ReturnTypeOfSyncOrg = {
169170
message?: string;
170-
status: "failed" | "completed" | "no_config";
171+
status: "failed" | "completed" | "no_config" | "bad_config";
171172
orgName: string;
172173
syncedSecurityManagerTeams: string[];
173174
orgOwnersGroup: string;
@@ -261,13 +262,14 @@ async function syncOrg(installedGitHubClient: InstalledClient, appConfig: AppCon
261262
}
262263
const setOfExistingTeams = new Set(existingTeamsResponse.data.map(t => t.Name.toUpperCase()));
263264

264-
const orgConfigResponse = await installedGitHubClient.GetConfigurationForInstallation();
265+
const orgConfigResponse = await installedGitHubClient.GetConfigurationForInstallation();
265266

266-
const orgConfig = orgConfigResponse.successful ? orgConfigResponse.data : undefined;
267+
const securityManagersFromOrgConfig = orgConfigResponse.successful ? orgConfigResponse.data.AdditionalSecurityManagerGroups : [];
268+
const securityManagersDisplayNameSourceMap = orgConfigResponse.successful ? orgConfigResponse.data.DisplayNameToSourceMap : new Map<string,string>();
267269

268270
const securityManagerTeams = [
269271
...appConfig.SecurityManagerTeams,
270-
...orgConfig?.AdditionalSecurityManagerGroups ?? []
272+
...securityManagersFromOrgConfig
271273
];
272274

273275
if (securityManagerTeams.length > 0) {
@@ -278,7 +280,7 @@ async function syncOrg(installedGitHubClient: InstalledClient, appConfig: AppCon
278280
securityManagerTeams,
279281
setOfExistingTeams,
280282
shortLink: appConfig.Description.ShortLink,
281-
displayNameToSourceMap: orgConfig?.DisplayNameToSourceMap ?? new Map<string,string>()
283+
displayNameToSourceMap: securityManagersDisplayNameSourceMap
282284
});
283285

284286
if (!syncManagersResponse.Success) {
@@ -293,15 +295,31 @@ async function syncOrg(installedGitHubClient: InstalledClient, appConfig: AppCon
293295
...response,
294296
syncedSecurityManagerTeams: syncManagersResponse.SyncedSecurityManagerTeams
295297
}
296-
}
298+
}
297299

298-
if (orgConfig == undefined) {
300+
if (!orgConfigResponse.successful && orgConfigResponse.state == "NoConfig") {
299301
return {
300302
...response,
301303
message: "Cannot access/fetch organization config",
302304
status: "no_config"
303305
}
304306
}
307+
else if(!orgConfigResponse.successful && orgConfigResponse.state == "BadConfig") {
308+
return {
309+
...response,
310+
message: orgConfigResponse.message,
311+
status: "bad_config"
312+
}
313+
}
314+
else if (!orgConfigResponse.successful) {
315+
return {
316+
...response,
317+
message: orgConfigResponse.message,
318+
status: "bad_config"
319+
}
320+
}
321+
322+
const orgConfig = orgConfigResponse.data;
305323

306324
Log(JSON.stringify(orgConfig));
307325

0 commit comments

Comments
 (0)