最近 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にも引っかかりにくいしで超便利。