From 3051a868c3f8dc5b3ba20fe29b721bd4a0994a91 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Thu, 5 May 2022 13:46:08 +0200 Subject: [PATCH] Pull requests created from a fork on a topic branch aren't discovered. (#3512) Fixes #3511 --- src/github/folderRepositoryManager.ts | 31 ++--- src/github/githubRepository.ts | 32 +++-- src/github/graphql.ts | 8 ++ src/github/queries.gql | 168 ++++++++++++++------------ src/github/utils.ts | 4 +- src/test/view/prsTree.test.ts | 4 +- 6 files changed, 129 insertions(+), 118 deletions(-) diff --git a/src/github/folderRepositoryManager.ts b/src/github/folderRepositoryManager.ts index 3ab0a1bb7..f7bcefd9b 100644 --- a/src/github/folderRepositoryManager.ts +++ b/src/github/folderRepositoryManager.ts @@ -1800,25 +1800,18 @@ export class FolderRepositoryManager implements vscode.Disposable { return null; } - const headGitHubRepo = this.gitHubRepositories.find( - repo => repo.remote.remoteName === this.repository.state.HEAD?.upstream?.remote, - ); - - // Find the github repo that matches the upstream + // Search through each github repo to see if it has a PR with this head branch. for (const repo of this.gitHubRepositories) { - if (repo.remote.remoteName === this.repository.state.HEAD.upstream.remote) { - const matchingPullRequest = await repo.getPullRequestForBranch( - `${headGitHubRepo?.remote.owner}:${this.repository.state.HEAD.upstream.name}`, - ); - if (matchingPullRequest && matchingPullRequest.length > 0) { - return { - owner: repo.remote.owner, - repositoryName: repo.remote.repositoryName, - prNumber: matchingPullRequest[0].number, - model: matchingPullRequest[0], - }; - } - break; + const matchingPullRequest = await repo.getPullRequestForBranch( + this.repository.state.HEAD.upstream.name, + ); + if (matchingPullRequest) { + return { + owner: repo.remote.owner, + repositoryName: repo.remote.repositoryName, + prNumber: matchingPullRequest.number, + model: matchingPullRequest, + }; } } return null; @@ -1905,7 +1898,7 @@ export class FolderRepositoryManager implements vscode.Disposable { } createGitHubRepositoryFromOwnerName(owner: string, repositoryName: string): GitHubRepository { - const existing = this.findExistingGitHubRepository({owner, repositoryName}); + const existing = this.findExistingGitHubRepository({ owner, repositoryName }); if (existing) { return existing; } diff --git a/src/github/githubRepository.ts b/src/github/githubRepository.ts index 76f80eef5..f1cbd9a11 100644 --- a/src/github/githubRepository.ts +++ b/src/github/githubRepository.ts @@ -25,6 +25,7 @@ import { MentionableUsersResponse, MilestoneIssuesResponse, PullRequestResponse, + PullRequestsResponse, ViewerPermissionResponse, } from './graphql'; import { IAccount, IMilestone, Issue, PullRequest, RepoAccessAndMergeMethods } from './interface'; @@ -364,26 +365,23 @@ export class GitHubRepository implements vscode.Disposable { return undefined; } - async getPullRequestForBranch(remoteAndBranch: string): Promise { + async getPullRequestForBranch(branch: string): Promise { try { Logger.debug(`Fetch pull requests for branch - enter`, GitHubRepository.ID); - const { octokit, remote } = await this.ensure(); - const result = await octokit.pulls.list({ - owner: remote.owner, - repo: remote.repositoryName, - head: remoteAndBranch + const { query, remote, schema } = await this.ensure(); + const { data } = await query({ + query: schema.PullRequestForHead, + variables: { + owner: remote.owner, + name: remote.repositoryName, + headRefName: branch, + }, }); - - const pullRequests = result.data - .map(pullRequest => { - return this.createOrUpdatePullRequestModel( - convertRESTPullRequestToRawPullRequest(pullRequest, this), - ); - }) - .filter(item => item !== null) as PullRequestModel[]; - Logger.debug(`Fetch pull requests for branch - done`, GitHubRepository.ID); - return pullRequests; + + if (data.repository.pullRequests.nodes.length > 0) { + return this.createOrUpdatePullRequestModel(parseGraphQLPullRequest(data.repository.pullRequests.nodes[0], this)); + } } catch (e) { Logger.appendLine(`Fetching pull requests for branch failed: ${e}`, GitHubRepository.ID); if (e.code === 404) { @@ -702,7 +700,7 @@ export class GitHubRepository implements vscode.Disposable { }, }); Logger.debug(`Fetch pull request ${id} - done`, GitHubRepository.ID); - return this.createOrUpdatePullRequestModel(parseGraphQLPullRequest(data, this)); + return this.createOrUpdatePullRequestModel(parseGraphQLPullRequest(data.repository.pullRequest, this)); } catch (e) { Logger.appendLine(`GithubRepository> Unable to fetch PR: ${e}`); return; diff --git a/src/github/graphql.ts b/src/github/graphql.ts index cb669f7c7..51b16f39b 100644 --- a/src/github/graphql.ts +++ b/src/github/graphql.ts @@ -504,6 +504,14 @@ export interface IssuesResponse { }; } +export interface PullRequestsResponse { + repository: { + pullRequests: { + nodes: PullRequest[] + } + } +} + export interface MaxIssueResponse { repository: { issues: { diff --git a/src/github/queries.gql b/src/github/queries.gql index 0ed41dad4..cc4caad85 100644 --- a/src/github/queries.gql +++ b/src/github/queries.gql @@ -158,6 +158,86 @@ fragment ReviewThread on PullRequestReviewThread { } } +fragment PullRequestFragment on PullRequest { + number + url + state + body + bodyHTML + title + author { + login + url + avatarUrl + ... on User { + email + } + ... on Organization { + email + } + } + createdAt + updatedAt + headRef { + ...Ref + } + headRefName + headRefOid + headRepository { + owner { + login + } + url + } + baseRef { + ...Ref + } + baseRefName + baseRefOid + baseRepository { + owner { + login + } + url + } + labels(first: 50) { + nodes { + name + } + } + merged + mergeable + mergeStateStatus + id + databaseId + isDraft + milestone { + title + dueOn + createdAt + id + } + assignees(first: 10) { + nodes { + login + name + avatarUrl + url + email + } + } + suggestedReviewers { + isAuthor + isCommenter + reviewer { + login + avatarUrl + name + url + } + } +} + query TimelineEvents($owner: String!, $name: String!, $number: Int!, $last: Int = 150) { repository(owner: $owner, name: $name) { pullRequest(number: $number) { @@ -290,83 +370,7 @@ query PullRequestComments($owner: String!, $name: String!, $number: Int!, $first query PullRequest($owner: String!, $name: String!, $number: Int!) { repository(owner: $owner, name: $name) { pullRequest(number: $number) { - number - url - state - body - bodyHTML - title - author { - login - url - avatarUrl - ... on User { - email - } - ... on Organization { - email - } - } - createdAt - updatedAt - headRef { - ...Ref - } - headRefName - headRefOid - headRepository { - owner { - login - } - url - } - baseRef { - ...Ref - } - baseRefName - baseRefOid - baseRepository { - owner { - login - } - url - } - labels(first: 50) { - nodes { - name - } - } - merged - mergeable - mergeStateStatus - id - databaseId - isDraft - milestone { - title - dueOn - createdAt - id - } - assignees(first: 10) { - nodes { - login - name - avatarUrl - url - email - } - } - suggestedReviewers { - isAuthor - isCommenter - reviewer { - login - avatarUrl - name - url - } - } + ...PullRequestFragment } } rateLimit { @@ -528,6 +532,16 @@ query PullRequestState($owner: String!, $name: String!, $number: Int!) { } } +query PullRequestForHead($owner: String!, $name: String!, $headRefName: String!) { + repository(owner: $owner, name: $name) { + pullRequests(first: 1, headRefName: $headRefName) { + nodes { + ...PullRequestFragment + } + } + } +} + mutation AddComment($input: AddPullRequestReviewCommentInput!) { addPullRequestReviewComment(input: $input) { comment { diff --git a/src/github/utils.ts b/src/github/utils.ts index faa639553..4ffc581e3 100644 --- a/src/github/utils.ts +++ b/src/github/utils.ts @@ -530,11 +530,9 @@ export function parseMergeability(mergeability: 'UNKNOWN' | 'MERGEABLE' | 'CONFL } export function parseGraphQLPullRequest( - pullRequest: GraphQL.PullRequestResponse, + graphQLPullRequest: GraphQL.PullRequest, githubRepository: GitHubRepository, ): PullRequest { - const graphQLPullRequest = pullRequest.repository.pullRequest; - return { id: graphQLPullRequest.databaseId, graphNodeId: graphQLPullRequest.id, diff --git a/src/test/view/prsTree.test.ts b/src/test/view/prsTree.test.ts index 7a09e3166..095ced73f 100644 --- a/src/test/view/prsTree.test.ts +++ b/src/test/view/prsTree.test.ts @@ -151,7 +151,7 @@ describe('GitHub Pull Requests view', function () { ); }); }).pullRequest; - const prItem0 = parseGraphQLPullRequest(pr0, gitHubRepository); + const prItem0 = parseGraphQLPullRequest(pr0.repository.pullRequest, gitHubRepository); const pullRequest0 = new PullRequestModel(telemetry, gitHubRepository, remote, prItem0); const pr1 = gitHubRepository.addGraphQLPullRequest(builder => { @@ -167,7 +167,7 @@ describe('GitHub Pull Requests view', function () { ); }); }).pullRequest; - const prItem1 = parseGraphQLPullRequest(pr1, gitHubRepository); + const prItem1 = parseGraphQLPullRequest(pr1.repository.pullRequest, gitHubRepository); const pullRequest1 = new PullRequestModel(telemetry, gitHubRepository, remote, prItem1); const repository = new MockRepository();