@@ -26,6 +26,7 @@ export enum AcceptMergeRequestResultKind {
2626 WaitingForApprovals ,
2727 UnresolvedDiscussion ,
2828 Unauthorized ,
29+ InvalidSha ,
2930}
3031
3132interface Response {
@@ -92,6 +93,11 @@ interface UnauthorizedResponse extends Response {
9293 mergeRequestInfo : MergeRequestInfo ;
9394}
9495
96+ interface InvalidShaResponse extends Response {
97+ kind : AcceptMergeRequestResultKind . InvalidSha ;
98+ mergeRequestInfo : MergeRequestInfo ;
99+ }
100+
95101export type AcceptMergeRequestResult = SuccessResponse
96102 | ClosedMergeRequestResponse
97103 | ReassignedMergeRequestResponse
@@ -104,6 +110,11 @@ export type AcceptMergeRequestResult = SuccessResponse
104110 | UnresolvedDiscussionResponse
105111 | UnauthorizedResponse ;
106112
113+ export type MergeMergeRequestResult = SuccessResponse
114+ | CanNotBeMergedResponse
115+ | InvalidShaResponse
116+ | UnauthorizedResponse ;
117+
107118interface AcceptMergeRequestOptions {
108119 ciInterval : number ;
109120 removeBranchAfterMerge : boolean ;
@@ -140,23 +151,97 @@ export const filterBotLabels = (labels: string[]): string[] => {
140151 return labels . filter ( ( label ) => ! values . includes ( label ) ) ;
141152} ;
142153
143- export const acceptMergeRequest = async ( gitlabApi : GitlabApi , mergeRequest : MergeRequest , user : User , options : AcceptMergeRequestOptions ) : Promise < AcceptMergeRequestResult > => {
144- let mergeRequestInfo : MergeRequestInfo ;
154+ export const acceptMergeRequest = async (
155+ gitlabApi : GitlabApi ,
156+ mergeRequest : MergeRequest ,
157+ user : User ,
158+ options : AcceptMergeRequestOptions ,
159+ ) : Promise < MergeMergeRequestResult > => {
160+ console . log ( `[MR][${ mergeRequest . iid } ] Calling merge request` ) ;
161+ const mergeRequestInfo = await gitlabApi . getMergeRequestInfo ( mergeRequest . project_id , mergeRequest . iid ) ;
162+ const response = await gitlabApi . sendRawRequest ( `/api/v4/projects/${ mergeRequestInfo . project_id } /merge_requests/${ mergeRequestInfo . iid } /merge` , RequestMethod . Put , {
163+ should_remove_source_branch : options . removeBranchAfterMerge ,
164+ sha : mergeRequestInfo . diff_refs . head_sha ,
165+ squash : mergeRequestInfo . labels . includes ( options . skipSquashingLabel ) ? false : options . squashMergeRequest ,
166+ squash_commit_message : `${ mergeRequestInfo . title } (!${ mergeRequestInfo . iid } )` ,
167+ merge_commit_message : `${ mergeRequestInfo . title } (!${ mergeRequestInfo . iid } )` ,
168+ } ) ;
169+
170+ if ( response . status === 405 ) {
171+ console . log ( `[MR][${ mergeRequestInfo . iid } ] 405 - cannot be merged` ) ;
172+ return {
173+ kind : AcceptMergeRequestResultKind . CanNotBeMerged ,
174+ mergeRequestInfo,
175+ user,
176+ } ;
177+ }
178+
179+ if ( response . status === 406 ) {
180+ console . log ( `[MR][${ mergeRequestInfo . iid } ] 406 - already merged` ) ;
181+ return {
182+ kind : AcceptMergeRequestResultKind . SuccessfullyMerged ,
183+ mergeRequestInfo,
184+ user,
185+ } ;
186+ }
187+
188+ if ( response . status === 409 ) {
189+ console . log ( `[MR][${ mergeRequestInfo . iid } ] 409 - SHA does not match HEAD of source branch` ) ;
190+ return {
191+ kind : AcceptMergeRequestResultKind . InvalidSha ,
192+ mergeRequestInfo,
193+ user,
194+ } ;
195+ }
196+
197+ if ( response . status === 401 ) {
198+ console . log ( `[MR][${ mergeRequestInfo . iid } ] 409 - Unauthorized` ) ;
199+ return {
200+ kind : AcceptMergeRequestResultKind . Unauthorized ,
201+ mergeRequestInfo,
202+ user,
203+ } ;
204+ }
205+
206+ if ( response . status !== 200 ) {
207+ throw new Error ( `Unsupported response status ${ response . status } ` ) ;
208+ }
209+
210+ const data = await response . json ( ) ;
211+ if ( typeof data !== 'object' && data . id === undefined ) {
212+ console . error ( 'response' , data ) ;
213+ throw new Error ( 'Invalid response' ) ;
214+ }
215+
216+ if ( ! containsLabel ( mergeRequestInfo . labels , BotLabels . Accepting ) ) {
217+ await gitlabApi . updateMergeRequest ( mergeRequestInfo . project_id , mergeRequestInfo . iid , {
218+ labels : [ ...filterBotLabels ( mergeRequestInfo . labels ) , BotLabels . Accepting ] . join ( ',' ) ,
219+ } ) ;
220+ }
221+
222+ return {
223+ kind : AcceptMergeRequestResultKind . SuccessfullyMerged ,
224+ mergeRequestInfo,
225+ user,
226+ } ;
227+ } ;
228+
229+ export const runAcceptingMergeRequest = async ( gitlabApi : GitlabApi , mergeRequest : MergeRequest , user : User , options : AcceptMergeRequestOptions ) : Promise < AcceptMergeRequestResult > => {
145230 let numberOfPipelineValidationRetries = defaultPipelineValidationRetries ;
146231 let numberOfRebasingRetries = defaultRebasingRetries ;
147232
148233 while ( true ) {
149- const tasks : Promise < any > [ ] = [ sleep ( options . ciInterval ) ] ;
150- mergeRequestInfo = await gitlabApi . getMergeRequestInfo ( mergeRequest . project_id , mergeRequest . iid ) ;
151-
152- if ( ! containsAssignedUser ( mergeRequestInfo , user ) ) {
153- return {
154- kind : AcceptMergeRequestResultKind . ReassignedMergeRequest ,
155- mergeRequestInfo,
156- user,
157- } ;
234+ const mergeResponse = await acceptMergeRequest ( gitlabApi , mergeRequest , user , options ) ;
235+ if (
236+ mergeResponse . kind === AcceptMergeRequestResultKind . SuccessfullyMerged
237+ || mergeResponse . kind === AcceptMergeRequestResultKind . Unauthorized
238+ ) {
239+ return mergeResponse ;
158240 }
159241
242+ const mergeRequestInfo = mergeResponse . mergeRequestInfo ;
243+ const tasks : Promise < any > [ ] = [ sleep ( options . ciInterval ) ] ;
244+
160245 if ( mergeRequestInfo . state === MergeState . Merged ) {
161246 return {
162247 kind : AcceptMergeRequestResultKind . SuccessfullyMerged ,
@@ -185,13 +270,11 @@ export const acceptMergeRequest = async (gitlabApi: GitlabApi, mergeRequest: Mer
185270 } ;
186271 }
187272
188- const approvals = await gitlabApi . getMergeRequestApprovals ( mergeRequestInfo . project_id , mergeRequestInfo . iid ) ;
189- if ( approvals . approvals_left > 0 ) {
273+ if ( ! containsAssignedUser ( mergeRequestInfo , user ) ) {
190274 return {
191- kind : AcceptMergeRequestResultKind . WaitingForApprovals ,
275+ kind : AcceptMergeRequestResultKind . ReassignedMergeRequest ,
192276 mergeRequestInfo,
193277 user,
194- approvals,
195278 } ;
196279 }
197280
@@ -224,6 +307,16 @@ export const acceptMergeRequest = async (gitlabApi: GitlabApi, mergeRequest: Mer
224307 } ;
225308 }
226309
310+ const approvals = await gitlabApi . getMergeRequestApprovals ( mergeRequestInfo . project_id , mergeRequestInfo . iid ) ;
311+ if ( approvals . approvals_left > 0 ) {
312+ return {
313+ kind : AcceptMergeRequestResultKind . WaitingForApprovals ,
314+ mergeRequestInfo,
315+ user,
316+ approvals,
317+ } ;
318+ }
319+
227320 if ( mergeRequestInfo . diverged_commits_count > 0 ) {
228321 if ( numberOfRebasingRetries <= 0 && mergeRequestInfo . merge_error !== null ) {
229322 console . log ( `[MR][${ mergeRequestInfo . iid } ] Merge error after rebase` ) ;
@@ -354,57 +447,6 @@ export const acceptMergeRequest = async (gitlabApi: GitlabApi, mergeRequest: Mer
354447 }
355448 }
356449
357- console . log ( `[MR][${ mergeRequestInfo . iid } ] Calling merge request` ) ;
358- const response = await gitlabApi . sendRawRequest ( `/api/v4/projects/${ mergeRequestInfo . project_id } /merge_requests/${ mergeRequestInfo . iid } /merge` , RequestMethod . Put , {
359- should_remove_source_branch : options . removeBranchAfterMerge ,
360- sha : mergeRequestInfo . diff_refs . head_sha ,
361- squash : mergeRequestInfo . labels . includes ( options . skipSquashingLabel ) ? false : options . squashMergeRequest ,
362- squash_commit_message : `${ mergeRequestInfo . title } (!${ mergeRequestInfo . iid } )` ,
363- merge_commit_message : `${ mergeRequestInfo . title } (!${ mergeRequestInfo . iid } )` ,
364- } ) ;
365-
366- if ( response . status === 405 ) {
367- console . log ( `[MR][${ mergeRequestInfo . iid } ] 405 - cannot be merged` ) ;
368- continue ;
369- }
370-
371- if ( response . status === 406 ) {
372- console . log ( `[MR][${ mergeRequestInfo . iid } ] 406 - already merged` ) ;
373- continue ;
374- }
375-
376- if ( response . status === 409 ) {
377- console . log ( `[MR][${ mergeRequestInfo . iid } ] 409 - SHA does not match HEAD of source branch` ) ;
378- continue ;
379- }
380-
381- if ( response . status === 401 ) {
382- return {
383- kind : AcceptMergeRequestResultKind . Unauthorized ,
384- mergeRequestInfo,
385- user,
386- } ;
387- }
388-
389- if ( response . status !== 200 ) {
390- throw new Error ( `Unsupported response status ${ response . status } ` ) ;
391- }
392-
393- const data = await response . json ( ) ;
394- if ( typeof data !== 'object' && data . id === undefined ) {
395- console . error ( 'response' , data ) ;
396- throw new Error ( 'Invalid response' ) ;
397- }
398-
399- if ( ! containsLabel ( mergeRequestInfo . labels , BotLabels . Accepting ) ) {
400- tasks . push (
401- gitlabApi . updateMergeRequest ( mergeRequestInfo . project_id , mergeRequestInfo . iid , {
402- labels : [ ...filterBotLabels ( mergeRequestInfo . labels ) , BotLabels . Accepting ] . join ( ',' ) ,
403- } ) ,
404- ) ;
405- }
406-
407- console . log ( `[MR][${ mergeRequestInfo . iid } ] Merge request is processing` ) ;
408450 await Promise . all ( tasks ) ;
409451 }
410452} ;
0 commit comments