Skip to content

Commit

Permalink
Makes by URL or ID searched GitLab PRs checkoutable
Browse files Browse the repository at this point in the history
  • Loading branch information
sergeibbb committed Dec 27, 2024
1 parent 3cbe734 commit ffce252
Show file tree
Hide file tree
Showing 3 changed files with 146 additions and 11 deletions.
2 changes: 1 addition & 1 deletion src/plus/integrations/integration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,7 @@ export abstract class IntegrationBase<
const connected = this.maybeConnected ?? (await this.isConnected());
if (!connected) return undefined;

const pr = this.container.cache.getPullRequest(id, resource, this, () => ({
const pr = await this.container.cache.getPullRequest(id, resource, this, () => ({
value: (async () => {
try {
const result = await this.getProviderPullRequest?.(this._session!, resource, id);
Expand Down
66 changes: 58 additions & 8 deletions src/plus/integrations/providers/gitlab/gitlab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,13 @@ import type {
GitLabCommit,
GitLabIssue,
GitLabMergeRequest,
GitLabMergeRequestFull,
GitLabMergeRequestREST,
GitLabMergeRequestState,
GitLabProjectREST,
GitLabUser,
} from './models';
import { fromGitLabMergeRequestREST, fromGitLabMergeRequestState } from './models';
import { fromGitLabMergeRequest, fromGitLabMergeRequestREST, fromGitLabMergeRequestState } from './models';

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

const projectId = await this.getProjectId(provider, token, owner, repo, options?.baseUrl, cancellation);
if (!projectId) return undefined;
interface QueryResult {
data: {
project: {
mergeRequest: GitLabMergeRequestFull | null;
} | null;
};
}

try {
const mr = await this.request<GitLabMergeRequestREST>(
const query = `query getMergeRequest(
$fullPath: ID!
$iid: String!
) {
project(fullPath: $fullPath) {
mergeRequest(iid: $iid) {
id,
iid
state,
author {
id
name
avatarUrl
webUrl
}
diffRefs {
baseSha
headSha
}
title
description
webUrl
createdAt
updatedAt
mergedAt
targetBranch
sourceBranch
project {
id
fullPath
webUrl
}
sourceProject {
id
fullPath
webUrl
}
}
}
}`;

const rsp = await this.graphql<QueryResult>(
provider,
token,
options?.baseUrl,
`v4/projects/${projectId}/merge_requests/${id}`,
query,
{
method: 'GET',
fullPath: `${owner}/${repo}`,
iid: String(id),
},
cancellation,
scope,
);
if (mr == null) return undefined;

return fromGitLabMergeRequestREST(mr, provider, { owner: owner, repo: repo });
if (rsp?.data?.project?.mergeRequest == null) return undefined;

const pr = rsp.data.project.mergeRequest;
return fromGitLabMergeRequest(pr, provider);
} catch (ex) {
if (ex instanceof RequestNotFoundError) return undefined;

Expand Down
89 changes: 87 additions & 2 deletions src/plus/integrations/providers/gitlab/models.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { HostingIntegrationId } from '../../../../constants.integrations';
import type { PullRequestState } from '../../../../git/models/pullRequest';
import { PullRequest } from '../../../../git/models/pullRequest';
import type { PullRequestRefs, PullRequestState } from '../../../../git/models/pullRequest';
import { PullRequest, PullRequestMergeableState } from '../../../../git/models/pullRequest';
import type { PullRequestUrlIdentity } from '../../../../git/models/pullRequest.utils';
import type { Provider } from '../../../../git/models/remoteProvider';
import type { Integration } from '../../integration';
Expand Down Expand Up @@ -67,6 +67,24 @@ export interface GitLabMergeRequest {
webUrl: string;
}

export interface GitLabRepositoryStub {
id: string;
fullPath: string;
webUrl: string;
}

export interface GitLabMergeRequestFull extends GitLabMergeRequest {
id: string;
targetBranch: string;
sourceBranch: string;
diffRefs: {
baseSha: string | null;
headSha: string;
};
project: GitLabRepositoryStub;
sourceProject: GitLabRepositoryStub;
}

export type GitLabMergeRequestState = 'opened' | 'closed' | 'locked' | 'merged';

export function fromGitLabMergeRequestState(state: GitLabMergeRequestState): PullRequestState {
Expand All @@ -93,6 +111,15 @@ export interface GitLabMergeRequestREST {
updated_at: string;
closed_at: string | null;
merged_at: string | null;
diff_refs: {
base_sha: string;
head_sha: string;
start_sha: string;
};
source_branch: string;
source_project_id: number;
target_branch: string;
target_project_id: number;
web_url: string;
}

Expand Down Expand Up @@ -167,3 +194,61 @@ export function getGitLabPullRequestIdentityFromMaybeUrl(url: string): RequireSo

return { prNumber: match[2], ownerAndRepo: match[1], provider: HostingIntegrationId.GitLab };
}

export function fromGitLabMergeRequest(pr: GitLabMergeRequestFull, provider: Provider): PullRequest {
return new PullRequest(
provider,
{
// author
id: pr.author?.id ?? '',
name: pr.author?.name ?? 'Unknown',
avatarUrl: pr.author?.avatarUrl ?? '',
url: pr.author?.webUrl ?? '',
},
pr.iid, // id
pr.id, // nodeId
pr.title,
pr.webUrl || '',
{
// IssueRepository
owner: '',
repo: '',
url: '',
},
fromGitLabMergeRequestState(pr.state), // PullRequestState
new Date(pr.createdAt),
new Date(pr.updatedAt),
// TODO@eamodio this isn't right, but GitLab doesn't seem to provide a closedAt on merge requests in GraphQL
pr.state !== 'closed' ? undefined : new Date(pr.updatedAt),
pr.mergedAt == null ? undefined : new Date(pr.mergedAt),
PullRequestMergeableState.Unknown,
undefined, // viewerCanUpdate
fromGitLabMergeRequestRefs(pr), // PullRequestRefs
);
}

function fromGitLabMergeRequestRefs(pr: GitLabMergeRequestFull): PullRequestRefs | undefined {
return {
base: {
owner: getRepoNamespace(pr.sourceProject.fullPath),
branch: pr.sourceBranch,
exists: true,
url: pr.sourceProject.webUrl,
repo: pr.sourceProject.fullPath,
sha: pr.diffRefs.baseSha || '',
},
head: {
owner: getRepoNamespace(pr.project.fullPath),
branch: pr.targetBranch,
exists: true,
url: pr.project.webUrl,
repo: pr.project.fullPath,
sha: pr.diffRefs.headSha,
},
isCrossRepository: pr.sourceProject.id !== pr.project.id,
};
}

function getRepoNamespace(projectFullPath: string) {
return projectFullPath.split('/').slice(0, -1).join('/');
}

0 comments on commit ffce252

Please sign in to comment.