@@ -45,6 +45,8 @@ import { fromGitLabMergeRequest, fromGitLabMergeRequestREST, fromGitLabMergeRequ
4545
4646// drop it as soon as we switch to @gitkraken /providers-api
4747const gitlabUserIdPrefix = 'gid://gitlab/User/' ;
48+ const gitlabMergeRequestIdPrefix = 'gid://gitlab/MergeRequest/' ;
49+
4850function buildGitLabUserId ( id : string | undefined ) : string | undefined {
4951 return id ?. startsWith ( gitlabUserIdPrefix ) ? id . substring ( gitlabUserIdPrefix . length ) : id ;
5052}
@@ -711,6 +713,116 @@ export class GitLabApi implements Disposable {
711713 }
712714 }
713715
716+ @debug < GitLabApi [ 'searchPullRequests' ] > ( { args : { 0 : p => p . name , 1 : '<token>' } } )
717+ async searchPullRequests (
718+ provider : Provider ,
719+ token : string ,
720+ options ?: { search ?: string ; user ?: string ; repos ?: string [ ] ; baseUrl ?: string ; avatarSize ?: number } ,
721+ cancellation ?: CancellationToken ,
722+ ) : Promise < PullRequest [ ] > {
723+ const scope = getLogScope ( ) ;
724+ const search = options ?. search ;
725+ if ( ! search ) {
726+ return [ ] ;
727+ }
728+ try {
729+ const perPageLimit = 20 ; // with bigger amount we exceed the max GraphQL complexity in the next query
730+ const restPRs = await this . request < GitLabMergeRequestREST [ ] > (
731+ provider ,
732+ token ,
733+ options ?. baseUrl ,
734+ `v4/search/?scope=merge_requests&search=${ search } &per_page=${ perPageLimit } ` ,
735+ {
736+ method : 'GET' ,
737+ } ,
738+ cancellation ,
739+ scope ,
740+ ) ;
741+ if ( restPRs . length === 0 ) {
742+ return [ ] ;
743+ }
744+
745+ interface QueryResult {
746+ data : Record < `mergeRequest_${number } `, GitLabMergeRequestFull > ;
747+ }
748+
749+ const queryArgs = restPRs . map ( ( _ , i ) => `$id_${ i } : MergeRequestID!` ) . join ( '\n' ) ;
750+ const queryFields = restPRs
751+ . map ( ( _ , i ) => `mergeRequest_${ i } : mergeRequest(id: $id_${ i } ) { ...mergeRequestFields }` )
752+ . join ( '\n' ) ;
753+ // Set of fields includes only additional fields that are not included in GitLabMergeRequestREST.
754+ // It's limited as much as possible to reduce complexity of the query.
755+ const queryMrFields = `fragment mergeRequestFields on MergeRequest {
756+ diffRefs {
757+ baseSha
758+ headSha
759+ }
760+ project {
761+ id
762+ fullPath
763+ webUrl
764+ }
765+ sourceProject {
766+ id
767+ fullPath
768+ webUrl
769+ }
770+ }` ;
771+ const query = `query getMergeRequests (${ queryArgs } ) {${ queryFields } } ${ queryMrFields } ` ;
772+
773+ const params = restPRs . reduce < Record < `id_${number } `, string > > ( ( ids , gitlabRestPr , i ) => {
774+ ids [ `id_${ i } ` ] = `${ gitlabMergeRequestIdPrefix } ${ gitlabRestPr . id } ` ;
775+ return ids ;
776+ } , { } ) ;
777+ const rsp = await this . graphql < QueryResult > (
778+ provider ,
779+ token ,
780+ options ?. baseUrl ,
781+ query ,
782+ params ,
783+ cancellation ,
784+ scope ,
785+ ) ;
786+ if ( rsp ?. data != null ) {
787+ const resultPRs = restPRs . reduce < PullRequest [ ] > ( ( accum , restPR , i ) => {
788+ const graphQlPR = rsp . data [ `mergeRequest_${ i } ` ] ;
789+ if ( graphQlPR == null ) {
790+ return accum ;
791+ }
792+
793+ const fullPr : GitLabMergeRequestFull = {
794+ ...graphQlPR ,
795+ iid : String ( restPR . iid ) ,
796+ id : String ( restPR . id ) ,
797+ state : restPR . state ,
798+ author : {
799+ id : buildGitLabUserId ( restPR . author ?. id ) ?? '' ,
800+ name : restPR . author ?. name ?? 'Unknown' ,
801+ avatarUrl : restPR . author ?. avatar_url ?? '' ,
802+ webUrl : restPR . author ?. web_url ?? '' ,
803+ } ,
804+ title : restPR . title ,
805+ description : restPR . description ,
806+ webUrl : restPR . web_url ,
807+ createdAt : restPR . created_at ,
808+ updatedAt : restPR . updated_at ,
809+ mergedAt : restPR . merged_at ,
810+ sourceBranch : restPR . source_branch ,
811+ targetBranch : restPR . target_branch ,
812+ } ;
813+ accum . push ( fromGitLabMergeRequest ( fullPr , provider ) ) ;
814+ return accum ;
815+ } , [ ] ) ;
816+ return resultPRs ;
817+ }
818+ return [ ] ;
819+ } catch ( ex ) {
820+ if ( ex instanceof RequestNotFoundError ) return [ ] ;
821+
822+ throw this . handleException ( ex , provider , scope ) ;
823+ }
824+ }
825+
714826 private async findUser (
715827 provider : Provider ,
716828 token : string ,
0 commit comments