Skip to content

Commit b2206de

Browse files
committed
Makes by URL or ID searched GitLab PRs checkoutable
(#3788, #3795)
1 parent 7410224 commit b2206de

File tree

3 files changed

+145
-10
lines changed

3 files changed

+145
-10
lines changed

src/plus/integrations/integration.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,7 @@ export abstract class IntegrationBase<
557557
const connected = this.maybeConnected ?? (await this.isConnected());
558558
if (!connected) return undefined;
559559

560-
const pr = this.container.cache.getPullRequest(id, resource, this, () => ({
560+
const pr = await this.container.cache.getPullRequest(id, resource, this, () => ({
561561
value: (async () => {
562562
try {
563563
const result = await this.getProviderPullRequest?.(this._session!, resource, id);

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

Lines changed: 58 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,13 @@ import type {
3535
GitLabCommit,
3636
GitLabIssue,
3737
GitLabMergeRequest,
38+
GitLabMergeRequestFull,
3839
GitLabMergeRequestREST,
3940
GitLabMergeRequestState,
4041
GitLabProjectREST,
4142
GitLabUser,
4243
} from './models';
43-
import { fromGitLabMergeRequestREST, fromGitLabMergeRequestState } from './models';
44+
import { fromGitLabMergeRequest, fromGitLabMergeRequestREST, fromGitLabMergeRequestState } from './models';
4445

4546
// drop it as soon as we switch to @gitkraken/providers-api
4647
const gitlabUserIdPrefix = 'gid://gitlab/User/';
@@ -585,24 +586,73 @@ export class GitLabApi implements Disposable {
585586
): Promise<PullRequest | undefined> {
586587
const scope = getLogScope();
587588

588-
const projectId = await this.getProjectId(provider, token, owner, repo, options?.baseUrl, cancellation);
589-
if (!projectId) return undefined;
589+
interface QueryResult {
590+
data: {
591+
project: {
592+
mergeRequest: GitLabMergeRequestFull | null;
593+
} | null;
594+
};
595+
}
590596

591597
try {
592-
const mr = await this.request<GitLabMergeRequestREST>(
598+
const query = `query getMergeRequest(
599+
$fullPath: ID!
600+
$iid: String!
601+
) {
602+
project(fullPath: $fullPath) {
603+
mergeRequest(iid: $iid) {
604+
id,
605+
iid
606+
state,
607+
author {
608+
id
609+
name
610+
avatarUrl
611+
webUrl
612+
}
613+
diffRefs {
614+
baseSha
615+
headSha
616+
}
617+
title
618+
description
619+
webUrl
620+
createdAt
621+
updatedAt
622+
mergedAt
623+
targetBranch
624+
sourceBranch
625+
project {
626+
id
627+
fullPath
628+
webUrl
629+
}
630+
sourceProject {
631+
id
632+
fullPath
633+
webUrl
634+
}
635+
}
636+
}
637+
}`;
638+
639+
const rsp = await this.graphql<QueryResult>(
593640
provider,
594641
token,
595642
options?.baseUrl,
596-
`v4/projects/${projectId}/merge_requests/${id}`,
643+
query,
597644
{
598-
method: 'GET',
645+
fullPath: `${owner}/${repo}`,
646+
iid: String(id),
599647
},
600648
cancellation,
601649
scope,
602650
);
603-
if (mr == null) return undefined;
604651

605-
return fromGitLabMergeRequestREST(mr, provider, { owner: owner, repo: repo });
652+
if (rsp?.data?.project?.mergeRequest == null) return undefined;
653+
654+
const pr = rsp.data.project.mergeRequest;
655+
return fromGitLabMergeRequest(pr, provider);
606656
} catch (ex) {
607657
if (ex instanceof RequestNotFoundError) return undefined;
608658

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

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { PullRequestState } from '../../../../git/models/pullRequest';
1+
import type { PullRequestRefs, PullRequestState } from '../../../../git/models/pullRequest';
22
import { PullRequest, PullRequestMergeableState } from '../../../../git/models/pullRequest';
33
import type { Provider } from '../../../../git/models/remoteProvider';
44
import type { Integration } from '../../integration';
@@ -65,6 +65,24 @@ export interface GitLabMergeRequest {
6565
webUrl: string;
6666
}
6767

68+
export interface GitLabRepositoryStub {
69+
id: string;
70+
fullPath: string;
71+
webUrl: string;
72+
}
73+
74+
export interface GitLabMergeRequestFull extends GitLabMergeRequest {
75+
id: string;
76+
targetBranch: string;
77+
sourceBranch: string;
78+
diffRefs: {
79+
baseSha: string | null;
80+
headSha: string;
81+
};
82+
project: GitLabRepositoryStub;
83+
sourceProject: GitLabRepositoryStub;
84+
}
85+
6886
export type GitLabMergeRequestState = 'opened' | 'closed' | 'locked' | 'merged';
6987

7088
export function fromGitLabMergeRequestState(state: GitLabMergeRequestState): PullRequestState {
@@ -92,6 +110,15 @@ export interface GitLabMergeRequestREST {
92110
closed_at: string | null;
93111
merged_at: string | null;
94112
detailed_merge_status: 'conflict' | 'mergeable' | string; // https://docs.gitlab.com/ee/api/merge_requests.html#merge-status
113+
diff_refs: {
114+
base_sha: string;
115+
head_sha: string;
116+
start_sha: string;
117+
};
118+
source_branch: string;
119+
source_project_id: number;
120+
target_branch: string;
121+
target_project_id: number;
95122
web_url: string;
96123
references: {
97124
full: string;
@@ -160,3 +187,61 @@ export function fromGitLabMergeRequestProvidersApi(pr: ProviderPullRequest, prov
160187
};
161188
return fromProviderPullRequest(wrappedPr, provider);
162189
}
190+
191+
export function fromGitLabMergeRequest(pr: GitLabMergeRequestFull, provider: Provider): PullRequest {
192+
return new PullRequest(
193+
provider,
194+
{
195+
// author
196+
id: pr.author?.id ?? '',
197+
name: pr.author?.name ?? 'Unknown',
198+
avatarUrl: pr.author?.avatarUrl ?? '',
199+
url: pr.author?.webUrl ?? '',
200+
},
201+
pr.iid, // id
202+
pr.id, // nodeId
203+
pr.title,
204+
pr.webUrl || '',
205+
{
206+
// IssueRepository
207+
owner: '',
208+
repo: '',
209+
url: '',
210+
},
211+
fromGitLabMergeRequestState(pr.state), // PullRequestState
212+
new Date(pr.createdAt),
213+
new Date(pr.updatedAt),
214+
// TODO@eamodio this isn't right, but GitLab doesn't seem to provide a closedAt on merge requests in GraphQL
215+
pr.state !== 'closed' ? undefined : new Date(pr.updatedAt),
216+
pr.mergedAt == null ? undefined : new Date(pr.mergedAt),
217+
PullRequestMergeableState.Unknown,
218+
undefined, // viewerCanUpdate
219+
fromGitLabMergeRequestRefs(pr), // PullRequestRefs
220+
);
221+
}
222+
223+
function fromGitLabMergeRequestRefs(pr: GitLabMergeRequestFull): PullRequestRefs | undefined {
224+
return {
225+
base: {
226+
owner: getRepoNamespace(pr.sourceProject.fullPath),
227+
branch: pr.sourceBranch,
228+
exists: true,
229+
url: pr.sourceProject.webUrl,
230+
repo: pr.sourceProject.fullPath,
231+
sha: pr.diffRefs.baseSha || '',
232+
},
233+
head: {
234+
owner: getRepoNamespace(pr.project.fullPath),
235+
branch: pr.targetBranch,
236+
exists: true,
237+
url: pr.project.webUrl,
238+
repo: pr.project.fullPath,
239+
sha: pr.diffRefs.headSha,
240+
},
241+
isCrossRepository: pr.sourceProject.id !== pr.project.id,
242+
};
243+
}
244+
245+
function getRepoNamespace(projectFullPath: string) {
246+
return projectFullPath.split('/').slice(0, -1).join('/');
247+
}

0 commit comments

Comments
 (0)