こんにちは。サービス開発室の武田です。
GitHubで管理しているファイルをCLIで取得したいという要件がありました。手間を考えないのであれば、適当な場所にリポジトリをclone
してコピーすればいいでしょう。でも面倒だ!ということで簡単にできる方法を探しました。
パブリックリポジトリの場合
実はパブリックリポジトリの場合はとても簡単です。例としてboto3リポジトリのpyproject.toml
を取得してみましょう。
まず対象のファイルのURLはこちらです。
- https://github.com/boto/boto3/blob/develop/pyproject.toml
ドメインをraw.githubusercontent.com
に置き換えます。
- https://raw.githubusercontent.com/boto/boto3/develop/pyproject.toml
あとはこれを取得するだけです。
$ curl https://raw.githubusercontent.com/boto/boto3/develop/pyproject.toml
[tool.pytest.ini_options]
markers = [
"slow: marks tests as slow",
]
[tool.isort]
profile = "black"
line_length = 79
honor_noqa = true
src_paths = ["boto3", "tests"]
[tool.black]
line-length = 79
skip_string_normalization = true
簡単ですね!
プライベートリポジトリの場合
プライベートリポジトリの場合、認証が必要なため先ほどの方法が使えません。そこで今回はgh
コマンドを使用することにしました。
基本的なセットアップについてはteknocatのエントリを参照してください。
使用するのはリポジトリ コンテンツAPIです。
gh
コマンドで使用する場合は次のようにコマンドを実行します。
$ gh api /repos/{owner}/{repo}/contents/{path}
このコマンドの実行結果は例として次のようになります。
{
"type": "file",
"encoding": "base64",
"size": 5362,
"name": "README.md",
"path": "README.md",
"content": "IyBZb2d...(中略)",
"sha": "3d21ec53a331a6f037a91c368710b99387d012c1",
"url": "https://api.github.com/repos/octokit/octokit.rb/contents/README.md",
"git_url": "https://api.github.com/repos/octokit/octokit.rb/git/blobs/3d21ec53a331a6f037a91c368710b99387d012c1",
"html_url": "https://github.com/octokit/octokit.rb/blob/master/README.md",
"download_url": "https://raw.githubusercontent.com/octokit/octokit.rb/master/README.md",
"_links": {
"git": "https://api.github.com/repos/octokit/octokit.rb/git/blobs/3d21ec53a331a6f037a91c368710b99387d012c1",
"self": "https://api.github.com/repos/octokit/octokit.rb/contents/README.md",
"html": "https://github.com/octokit/octokit.rb/blob/master/README.md"
}
}
このcontent
フィールドが、base64エンコードされたファイルとなっています。そのため次のようにすればファイルが取得できます。
$ gh api /repos/{owner}/{repo}/contents/{path} | jq -r '.content' | base64 --decode
この方法の注意点として、 ファイルサイズが1MB までしかサポートされません。それを超える場合content
フィールドが空になってしまいます。
そこでそれ以上のファイルの場合はdownload_url
を使用して、次のようにしてやりましょう。
$ gh api /repos/{owner}/{repo}/contents/{path} | jq -r '.download_url' | xargs curl
これで問題なく取得できます!
まとめ
ケースバイケースで次のようなコマンドで取得できます。
curl https://raw.githubusercontent.com/{owner}/{repo}/{path}
gh api /repos/{owner}/{repo}/contents/{path} | jq -r '.content' | base64 --decode
gh api /repos/{owner}/{repo}/contents/{path} | jq -r '.download_url' | xargs curl
あとはリダイレクトでファイルに保存するなりすればOKです。なお、contents APIを使用する方法はパブリックリポジトリでも問題なく動作するため、こちらに寄せてしまうのもありでしょう。