Skip to content

Commit 5d901ee

Browse files
committed
Makes text-searched GitLab PRs checkoutable
(#3788, #3795)
1 parent b2206de commit 5d901ee

File tree

2 files changed

+79
-13
lines changed

2 files changed

+79
-13
lines changed

src/plus/integrations/providers/gitlab/gitlab.ts

Lines changed: 76 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ import { fromGitLabMergeRequest, fromGitLabMergeRequestREST, fromGitLabMergeRequ
4545

4646
// drop it as soon as we switch to @gitkraken/providers-api
4747
const gitlabUserIdPrefix = 'gid://gitlab/User/';
48+
const gitlabMergeRequestIdPrefix = 'gid://gitlab/MergeRequest/';
49+
4850
function buildGitLabUserId(id: string | undefined): string | undefined {
4951
return id?.startsWith(gitlabUserIdPrefix) ? id.substring(gitlabUserIdPrefix.length) : id;
5052
}
@@ -724,11 +726,12 @@ export class GitLabApi implements Disposable {
724726
return [];
725727
}
726728
try {
729+
const perPageLimit = 20; // with bigger amount we exceed the max GraphQL complexity in the next query
727730
const gitlabPRs = await this.request<GitLabMergeRequestREST[]>(
728731
provider,
729732
token,
730733
options?.baseUrl,
731-
`v4/search/?scope=merge_requests&search=${search}`,
734+
`v4/search/?scope=merge_requests&search=${search}&per_page=${perPageLimit}`,
732735
{
733736
method: 'GET',
734737
},
@@ -739,15 +742,78 @@ export class GitLabApi implements Disposable {
739742
return [];
740743
}
741744

742-
const prs: PullRequest[] = gitlabPRs.map(pr => {
743-
const fullRef = pr.references.full;
744-
const project = {
745-
owner: fullRef.substring(0, fullRef.lastIndexOf('/')),
746-
repo: fullRef.substring(fullRef.lastIndexOf('/') + 1, fullRef.lastIndexOf('!')),
747-
};
748-
return fromGitLabMergeRequestREST(pr, provider, project);
749-
});
750-
return prs;
745+
interface QueryResult {
746+
data: Record<`mergeRequest_${number}`, GitLabMergeRequestFull>;
747+
}
748+
749+
const queryArgs = gitlabPRs.map((_, i) => `$id_${i}: MergeRequestID!`).join('\n');
750+
const queryFields = gitlabPRs
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 = gitlabPRs.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 = gitlabPRs.reduce<PullRequest[]>((prsAggr, gitLabPr, i) => {
788+
const pr = rsp.data[`mergeRequest_${i}`];
789+
const fullPr: GitLabMergeRequestFull = {
790+
...pr,
791+
iid: String(gitLabPr.iid),
792+
id: String(gitLabPr.id),
793+
state: gitLabPr.state,
794+
author: {
795+
id: buildGitLabUserId(gitLabPr.author?.id) ?? '',
796+
name: gitLabPr.author?.name ?? 'Unknown',
797+
avatarUrl: gitLabPr.author?.avatar_url ?? '',
798+
webUrl: gitLabPr.author?.web_url ?? '',
799+
},
800+
title: gitLabPr.title,
801+
description: gitLabPr.description,
802+
webUrl: gitLabPr.web_url,
803+
createdAt: gitLabPr.created_at,
804+
updatedAt: gitLabPr.updated_at,
805+
mergedAt: gitLabPr.merged_at,
806+
sourceBranch: gitLabPr.source_branch,
807+
targetBranch: gitLabPr.target_branch,
808+
};
809+
if (pr != null) {
810+
prsAggr.push(fromGitLabMergeRequest(fullPr, provider));
811+
}
812+
return prsAggr;
813+
}, []);
814+
return resultPrs;
815+
}
816+
return [];
751817
} catch (ex) {
752818
if (ex instanceof RequestNotFoundError) return [];
753819

src/plus/integrations/providers/gitlab/models.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ export interface GitLabMergeRequestFull extends GitLabMergeRequest {
7878
diffRefs: {
7979
baseSha: string | null;
8080
headSha: string;
81-
};
81+
} | null;
8282
project: GitLabRepositoryStub;
8383
sourceProject: GitLabRepositoryStub;
8484
}
@@ -228,15 +228,15 @@ function fromGitLabMergeRequestRefs(pr: GitLabMergeRequestFull): PullRequestRefs
228228
exists: true,
229229
url: pr.sourceProject.webUrl,
230230
repo: pr.sourceProject.fullPath,
231-
sha: pr.diffRefs.baseSha || '',
231+
sha: pr.diffRefs?.baseSha || '',
232232
},
233233
head: {
234234
owner: getRepoNamespace(pr.project.fullPath),
235235
branch: pr.targetBranch,
236236
exists: true,
237237
url: pr.project.webUrl,
238238
repo: pr.project.fullPath,
239-
sha: pr.diffRefs.headSha,
239+
sha: pr.diffRefs?.headSha || '',
240240
},
241241
isCrossRepository: pr.sourceProject.id !== pr.project.id,
242242
};

0 commit comments

Comments
 (0)