@@ -29,129 +29,141 @@ export const createOrgGithubTeamHandler: SQSHandlerFunction<
2929 commonConfig : { region : genericConfig . AwsRegion } ,
3030 } ) ;
3131 const redisClient = new RedisModule . default ( secretConfig . redis_url ) ;
32- const { orgName, githubTeamName, githubTeamDescription } = payload ;
33- const orgImmutableId = getOrgByName ( orgName ) ! . id ;
34- if ( SKIP_EXTERNAL_ORG_LEAD_UPDATE . includes ( orgImmutableId ) ) {
35- logger . info (
36- `Organization ${ orgName } has external updates disabled, exiting.` ,
37- ) ;
38- return ;
39- }
40- const dynamo = new DynamoDBClient ( {
41- region : genericConfig . AwsRegion ,
42- } ) ;
43- const lock = createLock ( {
44- adapter : new IoredisAdapter ( redisClient ) ,
45- key : `createOrgGithubTeamHandler:${ orgImmutableId } ` ,
46- retryAttempts : 5 ,
47- retryDelay : 300 ,
48- } ) ;
49- return await lock . using ( async ( signal ) => {
50- const getMetadataCommand = new GetItemCommand ( {
51- TableName : genericConfig . SigInfoTableName ,
52- Key : marshall ( {
53- primaryKey : `DEFINE#${ orgName } ` ,
54- entryId : "0" ,
55- } ) ,
56- AttributesToGet : [ "leadsEntraGroupId" , "leadsGithubTeamId" ] ,
57- ConsistentRead : true ,
58- } ) ;
59- const existingData = await dynamo . send ( getMetadataCommand ) ;
60- if ( ! existingData || ! existingData . Item ) {
61- throw new InternalServerError ( {
62- message : `Could not find org entry for ${ orgName } ` ,
63- } ) ;
64- }
65- const currentOrgInfo = unmarshall ( existingData . Item ) as {
66- leadsEntraGroupId ?: string ;
67- leadsGithubTeamId ?: string ;
68- } ;
69- if ( ! currentOrgInfo . leadsEntraGroupId ) {
70- logger . info ( `${ orgName } does not have an Entra group, skipping!` ) ;
71- return ;
72- }
73- if ( currentOrgInfo . leadsGithubTeamId ) {
74- logger . info ( "This org already has a GitHub team, skipping" ) ;
32+ try {
33+ const { orgName, githubTeamName, githubTeamDescription } = payload ;
34+ const orgImmutableId = getOrgByName ( orgName ) ! . id ;
35+ if ( SKIP_EXTERNAL_ORG_LEAD_UPDATE . includes ( orgImmutableId ) ) {
36+ logger . info (
37+ `Organization ${ orgName } has external updates disabled, exiting.` ,
38+ ) ;
7539 return ;
7640 }
77- if ( signal . aborted ) {
78- throw new InternalServerError ( {
79- message :
80- "Checked on lock before creating GitHub team, we've lost the lock!" ,
81- } ) ;
82- }
83- logger . info ( `Creating GitHub team for ${ orgName } !` ) ;
84- const suffix = currentEnvironmentConfig . GroupEmailSuffix ;
85- const finalName = `${ githubTeamName } ${ suffix === "" ? "" : `-${ suffix } ` } ` ;
86- const { updated, id : teamId } = await createGithubTeam ( {
87- orgId : currentEnvironmentConfig . GithubOrgName ,
88- githubToken : secretConfig . github_pat ,
89- parentTeamId : currentEnvironmentConfig . ExecGithubTeam ,
90- name : finalName ,
91- description : githubTeamDescription ,
92- logger,
41+ const dynamo = new DynamoDBClient ( {
42+ region : genericConfig . AwsRegion ,
9343 } ) ;
94- if ( ! updated ) {
95- logger . info (
96- `Github team "${ finalName } " already existed. We're assuming team sync was already set up (if not, please configure manually).` ,
97- ) ;
98- } else {
99- logger . info (
100- `Github team "${ finalName } " created with team ID "${ teamId } ".` ,
101- ) ;
102- if ( currentEnvironmentConfig . GithubIdpSyncEnabled ) {
44+ const lock = createLock ( {
45+ adapter : new IoredisAdapter ( redisClient ) ,
46+ key : `createOrgGithubTeamHandler:${ orgImmutableId } ` ,
47+ retryAttempts : 5 ,
48+ retryDelay : 300 ,
49+ } ) ;
50+ return await lock . using ( async ( signal ) => {
51+ const getMetadataCommand = new GetItemCommand ( {
52+ TableName : genericConfig . SigInfoTableName ,
53+ Key : marshall ( {
54+ primaryKey : `DEFINE#${ orgName } ` ,
55+ entryId : "0" ,
56+ } ) ,
57+ ProjectionExpression : "#entra,#gh" ,
58+ ExpressionAttributeNames : {
59+ "#entra" : "leadsEntraGroupId" ,
60+ "#gh" : "leadsGithubTeamId" ,
61+ } ,
62+ ConsistentRead : true ,
63+ } ) ;
64+ const existingData = await dynamo . send ( getMetadataCommand ) ;
65+ if ( ! existingData || ! existingData . Item ) {
66+ throw new InternalServerError ( {
67+ message : `Could not find org entry for ${ orgName } ` ,
68+ } ) ;
69+ }
70+ const currentOrgInfo = unmarshall ( existingData . Item ) as {
71+ leadsEntraGroupId ?: string ;
72+ leadsGithubTeamId ?: string ;
73+ } ;
74+ if ( ! currentOrgInfo . leadsEntraGroupId ) {
75+ logger . info ( `${ orgName } does not have an Entra group, skipping!` ) ;
76+ return ;
77+ }
78+ if ( currentOrgInfo . leadsGithubTeamId ) {
79+ logger . info ( "This org already has a GitHub team, skipping" ) ;
80+ return ;
81+ }
82+ if ( signal . aborted ) {
83+ throw new InternalServerError ( {
84+ message :
85+ "Checked on lock before creating GitHub team, we've lost the lock!" ,
86+ } ) ;
87+ }
88+ logger . info ( `Creating GitHub team for ${ orgName } !` ) ;
89+ const suffix = currentEnvironmentConfig . GroupEmailSuffix ;
90+ const finalName = `${ githubTeamName } ${ suffix === "" ? "" : `-${ suffix } ` } ` ;
91+ const { updated, id : teamId } = await createGithubTeam ( {
92+ orgId : currentEnvironmentConfig . GithubOrgName ,
93+ githubToken : secretConfig . github_pat ,
94+ parentTeamId : currentEnvironmentConfig . ExecGithubTeam ,
95+ name : finalName ,
96+ description : githubTeamDescription ,
97+ logger,
98+ } ) ;
99+ if ( ! updated ) {
103100 logger . info (
104- `Setting up IDP sync for Github team from Entra ID group ${ currentOrgInfo . leadsEntraGroupId } ` ,
101+ `Github team " ${ finalName } " already existed. We're assuming team sync was already set up (if not, please configure manually). ` ,
105102 ) ;
106- await assignIdpGroupsToTeam ( {
107- githubToken : secretConfig . github_pat ,
108- teamId,
109- logger,
110- groupsToSync : [ currentOrgInfo . leadsEntraGroupId ] ,
111- orgId : currentEnvironmentConfig . GithubOrgId ,
112- orgName : currentEnvironmentConfig . GithubOrgName ,
113- } ) ;
103+ } else {
104+ logger . info (
105+ `Github team "${ finalName } " created with team ID "${ teamId } ".` ,
106+ ) ;
107+ if ( currentEnvironmentConfig . GithubIdpSyncEnabled ) {
108+ logger . info (
109+ `Setting up IDP sync for Github team from Entra ID group ${ currentOrgInfo . leadsEntraGroupId } ` ,
110+ ) ;
111+ await assignIdpGroupsToTeam ( {
112+ githubToken : secretConfig . github_pat ,
113+ teamId,
114+ logger,
115+ groupsToSync : [ currentOrgInfo . leadsEntraGroupId ] ,
116+ orgId : currentEnvironmentConfig . GithubOrgId ,
117+ orgName : currentEnvironmentConfig . GithubOrgName ,
118+ } ) ;
119+ }
114120 }
115- }
116- logger . info ( "Adding updates to audit log" ) ;
117- const logStatement = updated
118- ? buildAuditLogTransactPut ( {
119- entry : {
120- module : Modules . ORG_INFO ,
121- message : `Created GitHub team "${ finalName } " for organization leads.` ,
122- actor : metadata . initiator ,
123- target : orgName ,
124- } ,
125- } )
126- : undefined ;
127- const storeGithubIdOperation = async ( ) => {
128- const commandTransaction = new TransactWriteItemsCommand ( {
129- TransactItems : [
130- ...( logStatement ? [ logStatement ] : [ ] ) ,
131- {
132- Update : {
133- TableName : genericConfig . SigInfoTableName ,
134- Key : marshall ( {
135- primaryKey : `DEFINE#${ orgName } ` ,
136- entryId : "0" ,
137- } ) ,
138- UpdateExpression :
139- "SET leadsGithubTeamId = :githubTeamId, updatedAt = :updatedAt" ,
140- ExpressionAttributeValues : marshall ( {
141- ":githubTeamId" : teamId ,
142- ":updatedAt" : new Date ( ) . toISOString ( ) ,
143- } ) ,
121+ logger . info ( "Adding updates to audit log" ) ;
122+ const logStatement = updated
123+ ? buildAuditLogTransactPut ( {
124+ entry : {
125+ module : Modules . ORG_INFO ,
126+ message : `Created GitHub team "${ finalName } " for organization leads.` ,
127+ actor : metadata . initiator ,
128+ target : orgName ,
144129 } ,
145- } ,
146- ] ,
147- } ) ;
148- return await dynamo . send ( commandTransaction ) ;
149- } ;
130+ } )
131+ : undefined ;
132+ const storeGithubIdOperation = async ( ) => {
133+ const commandTransaction = new TransactWriteItemsCommand ( {
134+ TransactItems : [
135+ ...( logStatement ? [ logStatement ] : [ ] ) ,
136+ {
137+ Update : {
138+ TableName : genericConfig . SigInfoTableName ,
139+ Key : marshall ( {
140+ primaryKey : `DEFINE#${ orgName } ` ,
141+ entryId : "0" ,
142+ } ) ,
143+ UpdateExpression :
144+ "SET leadsGithubTeamId = :githubTeamId, updatedAt = :updatedAt" ,
145+ ExpressionAttributeValues : marshall ( {
146+ ":githubTeamId" : teamId ,
147+ ":updatedAt" : new Date ( ) . toISOString ( ) ,
148+ } ) ,
149+ } ,
150+ } ,
151+ ] ,
152+ } ) ;
153+ return await dynamo . send ( commandTransaction ) ;
154+ } ;
150155
151- await retryDynamoTransactionWithBackoff (
152- storeGithubIdOperation ,
153- logger ,
154- `Store GitHub team ID for ${ orgName } ` ,
155- ) ;
156- } ) ;
156+ await retryDynamoTransactionWithBackoff (
157+ storeGithubIdOperation ,
158+ logger ,
159+ `Store GitHub team ID for ${ orgName } ` ,
160+ ) ;
161+ } ) ;
162+ } finally {
163+ try {
164+ await redisClient . quit ( ) ;
165+ } catch {
166+ redisClient . disconnect ( ) ;
167+ }
168+ }
157169} ;
0 commit comments