Skip to content

Commit c021e94

Browse files
devversionjelbourn
authored andcommitted
chore(dashboard): http function to list pull requests with conflicts (#6675)
Introduces a new http trigger in the Dashboard functions that returns all Pull Requests with merge conflicts. This allows us to show a list of PRs with merge conflicts in the dashboard. To ensure that the API calls are as fast as possible, the pull requests with conflicts are queried using Github's new GraphQL API.
1 parent 248dee8 commit c021e94

File tree

6 files changed

+87
-24
lines changed

6 files changed

+87
-24
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export {payloadGithubStatus} from './payload-github-status';
2+
export {pullRequestsWithConflicts} from './pull-requests-with-conflicts';
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import {GraphQLClient} from 'graphql-request';
2+
import {config} from 'firebase-functions';
3+
import * as GithubApi from 'github';
4+
5+
/** API token for the Github repository. Required to set the github status on commits and PRs. */
6+
const githubAccessToken = config().secret.github;
7+
8+
/** API Endpoint for the Github API v4 using GraphQL. */
9+
const githubApiV4Endpoint = 'https://api.github.com/graphql';
10+
11+
/** Export the GitHub V3 API instance that is authenticated. */
12+
export const githubApiV3 = new GithubApi();
13+
14+
/** Export the GraphQL client that can be used to query the Github API v4. */
15+
export const githubApiV4 = new GraphQLClient(githubApiV4Endpoint, {
16+
headers: {
17+
Authorization: `Bearer ${githubAccessToken}`,
18+
}
19+
});
20+
21+
// Authenticate the Github API package with the user token.
22+
githubApiV3.authenticate({type: 'token', token: githubAccessToken});
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import {githubApiV4} from './github-api';
2+
3+
/** GraphQL query that finds all Pull Requests and their mergeable state. */
4+
const getOpenPullRequestsWithMergeableStateQuery = `
5+
query getOpenPullRequestsWithMergeableState($lastCursor: String) {
6+
repository(owner: "angular", name: "material2") {
7+
pullRequests(states: OPEN, first: 100, after: $lastCursor) {
8+
pageInfo {
9+
hasNextPage,
10+
endCursor
11+
}
12+
nodes {
13+
number,
14+
mergeable
15+
}
16+
}
17+
}
18+
}`;
19+
20+
/** Pull Request node that will be returned by the Github V4 API. */
21+
export interface PullRequestWithMergeableState {
22+
number: number;
23+
mergeable: string;
24+
}
25+
26+
/** Queries the GitHub API to find all open pull requests and their mergeable state. */
27+
export async function getOpenPullRequestsWithMergeableState()
28+
: Promise<PullRequestWithMergeableState[]> {
29+
const nodes: PullRequestWithMergeableState[] = [];
30+
let lastData: any|null = null;
31+
32+
while (!lastData || lastData.repository.pullRequests.pageInfo.hasNextPage) {
33+
lastData = await githubApiV4.request(getOpenPullRequestsWithMergeableStateQuery, {
34+
lastCursor: lastData && lastData.repository.pullRequests.pageInfo.endCursor
35+
});
36+
37+
nodes.push(...lastData.repository.pullRequests.nodes);
38+
}
39+
40+
return nodes;
41+
}
42+
43+
Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,4 @@
1-
import {config} from 'firebase-functions';
2-
3-
const request = require('request');
4-
const {version, name} = require('../package.json');
5-
6-
/** API token for the Github repository. Required to set the github status on commits and PRs. */
7-
const repoToken = config().secret.github;
1+
import {githubApiV3} from './github-api';
82

93
/** Data that must be specified to set a Github PR status. */
104
export type GithubStatusData = {
@@ -18,25 +12,13 @@ export type GithubStatusData = {
1812
export function setGithubStatus(commitSHA: string, data: GithubStatusData) {
1913
const state = data.result ? 'success' : 'failure';
2014

21-
const requestData = {
15+
return githubApiV3.repos.createStatus({
16+
owner: 'angular',
17+
repo: 'material2',
18+
sha: commitSHA,
2219
state: state,
2320
target_url: data.url,
21+
description: data.description,
2422
context: data.name,
25-
description: data.description
26-
};
27-
28-
const headers = {
29-
'Authorization': `token ${repoToken}`,
30-
'User-Agent': `${name}/${version}`
31-
};
32-
33-
return new Promise((resolve, reject) => {
34-
request({
35-
url: `https://api.github.com/repos/angular/material2/statuses/${commitSHA}`,
36-
method: 'POST',
37-
body: requestData,
38-
headers: headers,
39-
json: true
40-
}, (error: any, response: any) => error ? reject(error) : resolve(response.statusCode));
4123
});
4224
}

tools/dashboard/functions/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
"@types/jsonwebtoken": "^7.2.1",
77
"firebase-admin": "~4.2.1",
88
"firebase-functions": "^0.5.7",
9+
"github": "^10.0.0",
10+
"graphql-request": "^1.3.4",
911
"jsonwebtoken": "^7.4.1",
1012
"request": "^2.81.0",
1113
"ts-node": "^3.0.6",
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import {https} from 'firebase-functions';
2+
import {getOpenPullRequestsWithMergeableState} from './github/github-graphql-queries';
3+
4+
/**
5+
* Firebase HTTP trigger that responds with a list of Pull Requests that have merge conflicts.
6+
*/
7+
export const pullRequestsWithConflicts = https.onRequest(async (_request, response) => {
8+
const pullRequests = (await getOpenPullRequestsWithMergeableState())
9+
.filter(pullRequest => pullRequest.mergeable === 'CONFLICTING');
10+
11+
response.status(200).json(pullRequests);
12+
});
13+

0 commit comments

Comments
 (0)