
GitHub API v3を使ってPull Requestから変更差分のあるファイルの一覧とファイル内容を取得する
この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは、CX事業本部の若槻です。
GitHubでは現在REST APIとしてGitHub API v3を使用することが可能です。
今回は、GitHub API v3を使ってPull Requestから変更差分のあるファイルの一覧とファイルの内容の取得をShell(curl)によりしてみました。
やってみた
アクセストークンの発行
まず、GitHub APIアクセス時の認証に使用するOAuth2アクセストークンを発行します。
https://github.com/settings/tokens/new にアクセスしてアクセストークンの新規発行ページを開きます。
[Note]でトークン名(または用途)を入力して、[Select scopes]でrepoにチェックを入れます。(repoではなく、その配下のスコープのみチェックした場合は「List pull requests」の時点でアクセスができませんでした)

同じページ下部の[Generate token]をクリックします。

アクセストークンが新規発行されました。トークン値が表示されるので控えておきます。

GitHub APIアクセス時のお決まり
APIを実際に叩く前に、GitHub APIアクセス時のお決まりについて確認します。
各種APIアクセス時にアカウント固有で共通で必要となる情報は以下となります。これらは変数で予め指定しておきます。
% TOKEN=<先ほど控えたアクセストークン値> % REPOSITORY=<取得するPull RequestがあるRepository名> % OWNER=<RepositoryのOwnerアカウント名>
また、APIホストはhttps://api.github.comとなります。
APIアクセス時にはAcceptヘッダーを次のように指定して利用するAPIバージョンを明示的に指定することが推奨されています。
"Accept: application/vnd.github.v3+json"
認証が必要なGitHub APIへのアクセス時にはAuthorizationヘッダーを次のように指定して認証を行います。
"Authorization: token OAUTH-TOKEN"
詳細については次のドキュメントを参照ください。
Pull Requestの取得
ここから実際にAPIを叩いていきます。
まず、変更差分を取得したいPull Requestを取得します。Pull Requestの取得方法には次の2つがありますが、
今回は「List pull requests」により直近で更新されたopen状態のPull Requestを取得してみます。「List pull requests」のメソッドおよびエンドポイントは以下となります。
GET /repos/{owner}/{repo}/pulls
また今回は「List pull requests」で使用可能な以下のParameterを指定します。
- state:- open(Pull Requestの状態を- open,- closeまたは- allで指定できる)
- sort:- updated(- created,- updated,- popularityまたは- long-runningで指定できる)
- direction:- desc(ソート方向を指定できる。既定は- asc。)
curlでAPIにアクセスしてPull Request一覧を取得してみます。取得結果は変数pullsに格納します。
% pulls=$(curl \
  -H "Accept: application/vnd.github.v3+json" \
  -H "Authorization: token ${TOKEN}" \
  "https://api.github.com/repos/${OWNER}/${REPOSITORY}/pulls?state=open&sort=updated&direction=desc")
ここで取得したい情報は直近に更新されたPull Requestの番号です。pullsからjqで取得して変数pull_numberに格納します。今回は16となります。
% pull_number=$(echo $pulls | jq '.[0].number') % echo $pull_number 16
Pull Requestから変更差分のあるファイル一覧を取得
次に先ほど取得したPull Requestの番号を元に、Pull Requestから変更差分のあるファイル一覧を取得します。その場合は「List pull requests files」を使用します。
「List pull requests files」のメソッドおよびエンドポイントは以下となります。
GET /repos/{owner}/{repo}/pulls/{pull_number}/files
curlでAPIにアクセスしてPull Requestから変更差分のあるファイルのファイル一覧を取得してみます。ただしここでは後続の処理で使うためコンテンツURL(contents_url)を取得します。このコンテンツURLの文字列内にファイルの情報も含まれています。また先ほどと違い変数を介すとURLエンコードが必要な文字が含まれている場合にデコードが面倒なので直接jqに流し込んでコンテンツURLのリストを変数contents_urlsに格納します。
% contents_urls=$(curl \
  -H "Accept: application/vnd.github.v3+json" \
  -H "Authorization: token ${TOKEN}" \
  "https://api.github.com/repos/${OWNER}/${REPOSITORY}/pulls/${pull_number}/files" | \
jq '[.[].contents_url]')
取得できたコンテンツURLは以下となります。
% echo $contents_urls [ "https://api.github.com/repos/<オーナー名>/<リポジトリ名>/contents/dir1/article.md?ref=301c68a9ebad2c591bdfd0b124f8e4d73175a96a", "https://api.github.com/repos/<オーナー名>/<リポジトリ名>/contents/dir1/dir2/config.json?ref=301c68a9ebad2c591bdfd0b124f8e4d73175a96a" ]
今回はPull Requestでdir1/article.mdおよびdir1/dir2/config.jsonの2ファイルに差分が発生していることが分かります。またここでrefに指定されている値はPull RequestのHEADの参照を表しています。
変更差分のあるファイルの内容を取得
次に先ほど取得したコンテンツURLを使用して、Pull Requestで変更されたファイルの内容を取得します。
コンテンツURLにアクセスした際のレスポンスでは、ファイルの内容はcontentにBase64暗号化されて指定されるので復号する必要があります。1つ目のコンテンツURLから復号した内容を取得してみます。
% contents_url=$(echo $contents_urls | jq -r '.[0]')
% curl \
  -H "Accept: application/vnd.github.v3+json" \
  -H "Authorization: token ${TOKEN}" \
  "${contents_url}" | jq -r '.content' | base64 -d
こんにちは、CX事業本部の若槻です。
今回は、GitHub APIを使ってPull Requestから変更差分のあるファイル一覧を取得してみました。
こんにちはから始まるファイル内容を取得することができました。
おわりに
GitHub API v3を使ってPull Requestから変更差分のあるファイルの一覧とファイルの内容を取得してみました。
今回確認したGitHub APIを使用して作成したいChrome拡張があったのでこれで何とか作れそうです。作れ次第共有したいと思います。
参考
- Pulls - GitHub Docs
- Repositories - GitHub Docs
- Scopes for OAuth Apps - GitHub Docs
- Resources in the REST API - GitHub Docs
- 変数を使用する | UNIX & Linux コマンド・シェルスクリプト リファレンス
- シェル芸で使いたい jqイディオム - Qiita
- jq コマンドを使う日常のご紹介 - Qiita
- bashで文字列を変数名に展開する方法 - Qiita
- 環境変数の設定を間違えてほとんどのコマンドが "command not found" になってしまったときの対処法 - Qiita
- コマンドラインでURLエンコードをする (他コマンド未使用) - _RJ 技術メモ
- Shellでもbase64 - Qiita
以上













