GitHub API で特定の user/organization のすべてのリポジトリ情報を取得する
標題のとおり、 GitHub API で特定の user/organization のすべてのリポジトリ情報を取得します。
環境は Node.js 12 を利用します。
前提条件
- Node.js v12.13.0
- GitHub の Personal Access Token を取得済み (public リポジトリの情報のみを取得する場合は不要)
GitHub API について
現在 GitHub API は v3 になっています。リファレンスは下記のとおりです。
リポジトリ情報を取得するには Repositories ページを参照します。
ユーザーと組織のリポジトリ一覧は下記のような URL で取得できることがわかります。
https://api.github.com/users/<ユーザー名>/repos
https://api.github.com/orgs/<組織名>/repos
上記のようにユーザーと組織は若干 URL が異なるのみです。
API を試す
試しにユーザーと組織について API をブラウザーで開いて結果を取得してみます。
いずれも下記のような JSON が得られます。
[
{
"id": 11730342,
"node_id": "MDEwOlJlcG9zaXRvcnkxMTczMDM0Mg==",
"name": "vue",
"full_name": "vuejs/vue",
"private": false,
"owner": { ... },
"html_url": "https://github.com/vuejs/vue",
"description": "🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.",
"fork": false,
"url": "https://api.github.com/repos/vuejs/vue",
...
"created_at": "2013-07-29T03:24:51Z",
"updated_at": "2020-01-18T03:16:27Z",
"pushed_at": "2020-01-18T03:01:08Z",
"git_url": "git://github.com/vuejs/vue.git",
"ssh_url": "git@github.com:vuejs/vue.git",
"clone_url": "https://github.com/vuejs/vue.git",
"svn_url": "https://github.com/vuejs/vue",
"homepage": "http://vuejs.org",
"size": 28015,
"stargazers_count": 155803,
"watchers_count": 155803,
"language": "JavaScript",
"has_issues": true,
"has_projects": true,
"has_downloads": true,
"has_wiki": true,
"has_pages": false,
"forks_count": 23435,
"mirror_url": null,
"archived": false,
"disabled": false,
"open_issues_count": 428,
"license": { ... },
"forks": 23435,
"open_issues": 428,
"watchers": 155803,
"default_branch": "dev",
"permissions": {
"admin": false,
"push": false,
"pull": true
}
},
...
]
一部省略していますが、レスポンスは配列になっており、それぞれの要素が各リポジトリに対応します。
また、リポジトリが1回のリクエストに収まらない場合は、 HTTP のレスポンスヘッダーに次のような Link
ヘッダーが含まれます。
Link: <https://api.github.com/organizations/6128107/repos?page=2>; rel="next", <https://api.github.com/organizations/6128107/repos?page=4>; rel="last"
1回のリクエストで取得できる数を指定できないため、基本的にはこの Link
ヘッダーにある rel="next"
の URL を順次取得して、すべての情報を取得していく必要があります。
この next の URL は最初にリクエストした API の URL とは異なるので注意が必要です。
Node.js サンプルスクリプト
Node.js で axios パッケージを使って、 REST API からのデータを取得します。
const GITHUB_API_URL = 'https://api.github.com';
const GITHUB_TOKEN = '<GitHub API Token>';
// Prepare axios for GitHub API
const axiosBase = require('axios');
const github = axiosBase.create({
baseURL: GITHUB_API_URL,
headers: {
'Content-Type': 'application/json',
'Authorization': `token ${GITHUB_TOKEN}`,
},
responseType: 'json',
});
/**
* Gets a list of repos in GitHub.
* @param {String} ownerType Resource type of owner (orgs|users)
* @param {String} owner Owner name
*/
async function getGithubRepos(ownerType, owner) {
let url = `${ownerType}/${owner}/repos?sort=full_name`;
const array = [];
while (url) {
const { next, data } = await getGithubReposPage(url);
if (data) array.push(data);
url = next;
}
return array.flat();
}
async function getGithubReposPage(url) {
const result = await github.get(url);
let next = null;
if (result.headers && result.headers.link) {
// extract next url from "link" header
const matches = /\<([^<>]+)\>; rel\="next"/.exec(result.headers.link);
if (matches) {
next = matches[1];
}
}
const data = result.data || null;
return {
next,
data,
};
}
// demo
(async () => {
const kenzaurosRepos = await getGithubRepos('users', 'kenzauros');
console.log(kenzaurosRepos);
const vuejsRepos = await getGithubRepos('orgs', 'vuejs');
console.log(vuejsRepos);
})();
※認証トークンを使わない場合は GITHUB_TOKEN
の宣言 (2行目) と Authorization
ヘッダー (10行目) を削除してください。
最後のほうに書いたように await getGithubRepos('users', 'kenzauros')
のように書くことで、「ユーザー kenzauros のリポジトリ一覧」を取得できます。
getGithubRepos
でやっていることは単純で rel="next"
を含む Link
ヘッダーがなくなるまで、繰り返し問い合わせしていくだけです。
どなたかの助けになれば幸いです。