Skip to content

Commit ddd6bed

Browse files
committed
feat: check if PR is in merge queue
Signed-off-by: Adam Setch <[email protected]>
1 parent 42b24f8 commit ddd6bed

File tree

5 files changed

+90
-3
lines changed

5 files changed

+90
-3
lines changed

src/renderer/typesGitHub.ts

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,16 @@ export type UserType =
5050
| 'User';
5151

5252
/**
53-
* Note: draft and merged are not official states in the GitHub API.
54-
* These are derived from the pull request's `merged` and `draft` properties.
53+
* Note: draft, merged and queued are not official states in the GitHub API.
54+
* These are derived from the pull request's `merged` and `draft` properties, or
55+
* by checking the PR merge queue state.
5556
*/
56-
export type PullRequestStateType = 'closed' | 'draft' | 'merged' | 'open';
57+
export type PullRequestStateType =
58+
| 'closed'
59+
| 'draft'
60+
| 'merged'
61+
| 'open'
62+
| 'queued';
5763

5864
export type StateType =
5965
| CheckSuiteStatus
@@ -497,6 +503,19 @@ export interface GraphQLSearch<T> {
497503
};
498504
}
499505

506+
export interface GraphQLMergeQueue {
507+
data: {
508+
repository: {
509+
pullRequest: {
510+
mergeQueueEntry: {
511+
state: string;
512+
position: number;
513+
} | null;
514+
};
515+
};
516+
};
517+
}
518+
500519
export interface Discussion {
501520
number: number;
502521
title: string;

src/renderer/utils/api/client.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import type {
1212
Commit,
1313
CommitComment,
1414
Discussion,
15+
GraphQLMergeQueue,
1516
GraphQLSearch,
1617
Issue,
1718
IssueOrPullRequestComment,
@@ -25,6 +26,7 @@ import type {
2526
import { isAnsweredDiscussionFeatureSupported } from '../features';
2627
import { rendererLogError } from '../logger';
2728
import { QUERY_SEARCH_DISCUSSIONS } from './graphql/discussions';
29+
import { QUERY_CHECK_MERGE_QUEUE_FOR_PR } from './graphql/pullRequests';
2830
import { formatAsGitHubSearchSyntax } from './graphql/utils';
2931
import { apiRequestAuth } from './request';
3032
import { getGitHubAPIBaseUrl, getGitHubGraphQLUrl } from './utils';
@@ -285,3 +287,27 @@ export async function getLatestDiscussion(
285287
);
286288
}
287289
}
290+
291+
/**
292+
* Check if PR is in merge queue.
293+
*/
294+
export async function queryMergeQueueForPr(
295+
notification: Notification,
296+
prNumber: number,
297+
): AxiosPromise<GraphQLMergeQueue> {
298+
const url = getGitHubGraphQLUrl(notification.account.hostname);
299+
300+
return apiRequestAuth(
301+
url.toString() as Link,
302+
'POST',
303+
notification.account.token,
304+
{
305+
query: print(QUERY_CHECK_MERGE_QUEUE_FOR_PR),
306+
variables: {
307+
owner: notification.repository.owner.login,
308+
repository: notification.repository.name,
309+
prNumber: prNumber,
310+
},
311+
},
312+
);
313+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import gql from 'graphql-tag';
2+
3+
export const QUERY_CHECK_MERGE_QUEUE_FOR_PR = gql`
4+
query checkMergeQueueForPR(
5+
$owner: String!
6+
$repository: String!
7+
$prNumber: Int!
8+
) {
9+
repository(owner: $owner, name: $repository) {
10+
pullRequest(number: $prNumber) {
11+
mergeQueueEntry {
12+
state
13+
position
14+
}
15+
}
16+
}
17+
}
18+
`;

src/renderer/utils/notifications/handlers/default.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ export class DefaultHandler implements NotificationTypeHandler {
4242
case 'RESOLVED':
4343
case 'merged':
4444
return IconColor.PURPLE;
45+
case 'queued':
46+
return IconColor.YELLOW;
4547
default:
4648
return IconColor.GRAY;
4749
}

src/renderer/utils/notifications/handlers/pullRequest.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type { FC } from 'react';
33
import type { OcticonProps } from '@primer/octicons-react';
44
import {
55
GitMergeIcon,
6+
GitMergeQueueIcon,
67
GitPullRequestClosedIcon,
78
GitPullRequestDraftIcon,
89
GitPullRequestIcon,
@@ -23,6 +24,7 @@ import {
2324
getIssueOrPullRequestComment,
2425
getPullRequest,
2526
getPullRequestReviews,
27+
queryMergeQueueForPr,
2628
} from '../../api/client';
2729
import { isStateFilteredOut, isUserFilteredOut } from '../filters/filter';
2830
import { DefaultHandler } from './default';
@@ -44,6 +46,12 @@ class PullRequestHandler extends DefaultHandler {
4446
prState = 'merged';
4547
} else if (pr.draft) {
4648
prState = 'draft';
49+
} else {
50+
const mergeQueue = await isPRInMergeQueue(notification, pr.number);
51+
52+
if (mergeQueue) {
53+
pr.state = 'queued';
54+
}
4755
}
4856

4957
// Return early if this notification would be hidden by state filters
@@ -95,6 +103,8 @@ class PullRequestHandler extends DefaultHandler {
95103
return GitPullRequestClosedIcon;
96104
case 'merged':
97105
return GitMergeIcon;
106+
case 'queued':
107+
return GitMergeQueueIcon;
98108
default:
99109
return GitPullRequestIcon;
100110
}
@@ -173,3 +183,15 @@ export function parseLinkedIssuesFromPr(pr: PullRequest): string[] {
173183

174184
return linkedIssues;
175185
}
186+
187+
export async function isPRInMergeQueue(
188+
notification: Notification,
189+
prNumber: number,
190+
): Promise<boolean> {
191+
const mergeQueueResponse = await queryMergeQueueForPr(notification, prNumber);
192+
193+
const mergeQueueEntry =
194+
mergeQueueResponse.data.data.repository.pullRequest.mergeQueueEntry;
195+
196+
return mergeQueueEntry !== null;
197+
}

0 commit comments

Comments
 (0)