最近 merged-pr-statを使ってマージされたPR情報を集計したり、レビューの偏り具合を可視化するスクリプトを書いたりしていた。この時自分のチームが使っているレポジトリをどう一覧化するかに困っていた。もともとはひとまずスクリプト上でハードコードしていたが、これだとメンテが面倒。
よくよく考えてみると、GitHubのTeamでレポジトリのアクセス権限を管理してるんだから、それを使えばよいのでは?と思って調べてみたら、GraphQL APIを使ったら一発だったのでメモ。
GraphQL APIを使ってGithub Teamが持つレポジトリを取得する
こんなクエリを書いたらいい。org-name1やteam-name1のところは適宜置き換える。
query {
organization(login: "org-name1") {
team(slug: "team-name1") {
repositories(first: 100) {
nodes {
nameWithOwner
}
pageInfo {
hasNextPage
endCursor
}
}
}
}
}
https://developer.github.com/v4/explorer/ とかで実行すると様子がわかる。以下のような構造のレスポンスが返ってくる。
{
"data": {
"organization": {
"team": {
"repositories": {
"nodes": [
{
"nameWithOwner": "shibayu36/repo1"
},
{
"nameWithOwner": "shibayu36/repo2"
},
{
"nameWithOwner": "shibayu36/repo3"
},
],
"pageInfo": {
"hasNextPage": false,
"endCursor": "Y3Vyc29yOnYyOpHOEkFhXQ=="
}
}
}
}
}
}
TypeScriptを使ってorg名team名から全レポジトリ一覧を取得する関数を書いてみる
ページネーションもちゃんとして全リストを取ってくるようにしたTypeScriptの関数の例。
import { gql, GraphQLClient } from "graphql-request";
type _TeamRepositoriesResponse = Readonly<{
organization?: {
team?: {
repositories?: {
nodes: {
nameWithOwner: string;
}[];
pageInfo: {
hasNextPage: boolean;
endCursor: string;
};
};
};
};
}>;
export async function fetchTeamRepositories(
client: GraphQLClient,
orgName: string,
teamName: string
): Promise<string[]> {
const gqlQuery = gql`
query($orgName: String!, $teamName: String!, $after: String) {
organization(login: $orgName) {
team(slug: $teamName) {
repositories(first: 100, after: $after) {
nodes {
nameWithOwner
}
pageInfo {
hasNextPage
endCursor
}
}
}
}
}
`;
let after: string | undefined;
let repos: string[] = [];
while (true) {
const data = await client.request<_TeamRepositoriesResponse>(gqlQuery, {
orgName,
teamName,
after,
});
const repositoriesNode = data.organization?.team?.repositories;
if (!repositoriesNode) break;
repos = repos.concat(repositoriesNode.nodes.map(n => n.nameWithOwner));
if (!repositoriesNode.pageInfo.hasNextPage) break;
after = repositoriesNode.pageInfo.endCursor;
}
return repos;
}
こんな感じで使える。
const GITHUB_GRAPHQL_ENDPOINT = "https://api.github.com/graphql";
const GITHUB_TOKEN = process.env.GITHUB_TOKEN;
const graphQLClient = new GraphQLClient(GITHUB_GRAPHQL_ENDPOINT, {
headers: {
authorization: `Bearer ${GITHUB_TOKEN}`,
},
});
const teamRepos = await fetchTeamRepositories(graphQLClient, "shibayu36", "team1");
まとめ
GraphQL APIを使って、特定のGitHub Teamが持つレポジトリ一覧を一発で取得するのを試してみた。最近GitHubのAPIを色々使ってみてるけど、とにかくGraphQL APIは一発で取りやすいし、API Limitにも引っかかりにくいしで超便利。