angular-cn/dev-infra/utils/github.ts

112 lines
3.5 KiB
TypeScript
Raw Normal View History

/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {graphql as unauthenticatedGraphql} from '@octokit/graphql';
import {params, query as graphqlQuery, types} from 'typed-graphqlify';
import {NgDevConfig} from './config';
/** The configuration required for github interactions. */
type GithubConfig = NgDevConfig['github'];
/**
* Authenticated instance of Github GraphQl API service, relies on a
* personal access token being available in the TOKEN environment variable.
*/
const graphql = unauthenticatedGraphql.defaults({
headers: {
// TODO(josephperrott): Remove reference to TOKEN environment variable as part of larger
// effort to migrate to expecting tokens via GITHUB_ACCESS_TOKEN environment variables.
authorization: `token ${process.env.TOKEN || process.env.GITHUB_ACCESS_TOKEN}`,
}
});
/** Get a PR from github */
export async function getPr<PrSchema>(
prSchema: PrSchema, prNumber: number, {owner, name}: GithubConfig) {
const PR_QUERY = params(
{
$number: 'Int!', // The PR number
$owner: 'String!', // The organization to query for
$name: 'String!', // The organization to query for
},
{
repository: params({owner: '$owner', name: '$name'}, {
pullRequest: params({number: '$number'}, prSchema),
})
});
const result =
await graphql(graphqlQuery(PR_QUERY), {number: prNumber, owner, name}) as typeof PR_QUERY;
return result.repository.pullRequest;
}
/** Get all pending PRs from github */
export async function getPendingPrs<PrSchema>(prSchema: PrSchema, {owner, name}: GithubConfig) {
// The GraphQL query object to get a page of pending PRs
const PRS_QUERY = params(
{
$first: 'Int', // How many entries to get with each request
$after: 'String', // The cursor to start the page at
$owner: 'String!', // The organization to query for
$name: 'String!', // The repository to query for
},
{
repository: params({owner: '$owner', name: '$name'}, {
pullRequests: params(
{
first: '$first',
after: '$after',
states: `OPEN`,
},
{
nodes: [prSchema],
pageInfo: {
hasNextPage: types.boolean,
endCursor: types.string,
},
}),
})
});
const query = graphqlQuery('members', PRS_QUERY);
/**
* Gets the query and queryParams for a specific page of entries.
*/
const queryBuilder = (count: number, cursor?: string) => {
return {
query,
params: {
after: cursor || null,
first: count,
owner,
name,
},
};
};
// The current cursor
let cursor: string|undefined;
// If an additional page of members is expected
let hasNextPage = true;
// Array of pending PRs
const prs: Array<PrSchema> = [];
// For each page of the response, get the page and add it to the
// list of PRs
while (hasNextPage) {
const {query, params} = queryBuilder(100, cursor);
const results = await graphql(query, params) as typeof PRS_QUERY;
prs.push(...results.repository.pullRequests.nodes);
hasNextPage = results.repository.pullRequests.pageInfo.hasNextPage;
cursor = results.repository.pullRequests.pageInfo.endCursor;
}
return prs;
}