Issue/PRに起こったイベントを取得できるGithub Timeline API
概要
最近GithubのIssue Trackerを自作してみようかなーと思っており、Issue/PullRequestで発生したイベントを取得できる Timeline API について調べたのでまとめておきます。
Timeline APIとは
GithubのIssue/PullRequestでは、誰かがアサインされたり、コメントがついたり、レビューされたりといったイベントが発生します。このイベントの一覧を取得できるのが Timeline API GET /repos/{owner}/{repo}/issues/{issue_number}/timeline
です。Issue/PRの状況を取得してなんらかの通知をするようなシステムを独自で作るときに便利だと思います。完全に正確ではありませんが、GithubのUIで見られる以下の一連の表示がそのままAPIで取得できると思っておけばOKです。
ちなみに、ほぼ同じような機能を持っている Events API というAPIもあって使い分けが謎ですが、調べた限り以下の差分がありました。
- Events API/Timeline API それぞれどちらかでしか取得できないイベントの種類/情報がある
- Events APIはIssue/PRに関するイベントに加えてRepositoryに関するイベントを別途取得できるが、Timeline APIはIssue/PRについてしか取得できない
この記事ではEvents APIのことは気にせずTimeline APIについてのみ書きます。
APIの叩き方
Timeline APIを単純に叩くと以下のレスポンスが返ってきます。
{ "message": "If you would like to help us test the Timeline API during its preview period, you must specify a custom media type in the 'Accept' header. Please see the docs for full details.", "documentation_url": "https://docs.github.com/rest/reference/issues#list-timeline-events-for-an-issue" }
このAPIはまだpreview stateなので、専用のヘッダをつける必要があるとのこと。 ドキュメント にしたがって以下のヘッダをつけて送ることでレスポンスを得ることができます。
Accept: application/vnd.github.mockingbird-preview+json
また、プライベートレポジトリのIssueのTimelineを取得するにはAccess Tokenが必要です。 GithubのSettings からrepoの権限のついたTokenを発行して、以下のヘッダを付与することで、自分が権限を持ったプライベートレポジトリのTimelineもAPIから取得できるようになります。
Authorization: token <発行したToken>
レスポンス
Timeline APIを叩くとだいたいどういうレスポンスが返ってくるのか把握するために、 適当なrails/railsのPullRequest のTimelineを取得してみます。PR番号が40114なので、
GET https://api.github.com/repos/rails/rails/issues/40114/timeline
を叩くと、以下のようなレスポンスが返ってきます。あくまでだいたいどういうレスポンスが返ってくるのかを見るためにここに示しているだけなので、大したことがなさそうなフィールドは全部省略しています。実際のフルのレスポンスをみたい場合は実際にAPIを叩いてみてください。rails/railsはパブリックレポジトリなのでTokenは不要です。
[ { "sha": "e0637a5a503fd624b5346c5c51adb447a23d8035", "node_id": "MDY6Q29tbWl0ODUxNDplMDYzN2E1YTUwM2ZkNjI0YjUzNDZjNWM1MWFkYjQ0N2EyM2Q4MDM1", "url": "https://api.github.com/repos/rails/rails/git/commits/e0637a5a503fd624b5346c5c51adb447a23d8035", "html_url": "https://github.com/rails/rails/commit/e0637a5a503fd624b5346c5c51adb447a23d8035", "author": { "name": "Adrianna Chang", "email": "adrianna.chang@shopify.com", "date": "2020-08-26T17:30:29Z" }, "message": "Add attr_writer for credentials to Rails::Application", "event": "committed", ... }, { "id": 475768545, "node_id": "MDE3OlB1bGxSZXF1ZXN0UmV2aWV3NDc1NzY4NTQ1", "user": { "login": "rafaelfranca", "id": 47848, ... }, "body": "", "state": "commented", "html_url": "https://github.com/rails/rails/pull/40114#pullrequestreview-475768545", "event": "reviewed" ... }, { "sha": "55a668db2937a5fe7b1c8b2f5e1913e54a16e427", "node_id": "MDY6Q29tbWl0ODUxNDo1NWE2NjhkYjI5MzdhNWZlN2IxYzhiMmY1ZTE5MTNlNTRhMTZlNDI3", "url": "https://api.github.com/repos/rails/rails/git/commits/55a668db2937a5fe7b1c8b2f5e1913e54a16e427", "html_url": "https://github.com/rails/rails/commit/55a668db2937a5fe7b1c8b2f5e1913e54a16e427", "author": { "name": "Adrianna Chang", "email": "adrianna.chang@shopify.com", "date": "2020-08-26T17:30:40Z" }, "message": "Remove references to secrets.yml from documentation", "event": "committed", ... }, { "id": 3696199379, "node_id": "MDIzOkhlYWRSZWZGb3JjZVB1c2hlZEV2ZW50MzY5NjE5OTM3OQ==", "url": "https://api.github.com/repos/rails/rails/issues/events/3696199379", "actor": { "login": "adrianna-chang-shopify", "id": 22918438, ... }, "event": "head_ref_force_pushed", "created_at": "2020-08-26T18:59:38Z", ... }, { "id": 3696281850, "node_id": "MDE1OlJlZmVyZW5jZWRFdmVudDM2OTYyODE4NTA=", "url": "https://api.github.com/repos/rails/rails/issues/events/3696281850", "actor": { "login": "rafaelfranca", "id": 47848, ... }, "event": "referenced", "created_at": "2020-08-26T19:22:34Z", ... }, { "id": 3696281853, "node_id": "MDExOk1lcmdlZEV2ZW50MzY5NjI4MTg1Mw==", "url": "https://api.github.com/repos/rails/rails/issues/events/3696281853", "actor": { "login": "rafaelfranca", "id": 47848, ... }, "event": "merged", "created_at": "2020-08-26T19:22:34Z", ... }, { "id": 3696281858, "node_id": "MDExOkNsb3NlZEV2ZW50MzY5NjI4MTg1OA==", "url": "https://api.github.com/repos/rails/rails/issues/events/3696281858", "actor": { "login": "rafaelfranca", "id": 47848, ... }, "event": "closed", "created_at": "2020-08-26T19:22:34Z", ... }, { "id": 3696425655, "node_id": "MDE5OkhlYWRSZWZEZWxldGVkRXZlbnQzNjk2NDI1NjU1", "url": "https://api.github.com/repos/rails/rails/issues/events/3696425655", "actor": { "login": "adrianna-chang-shopify", "id": 22918438, "node_id": "MDQ6VXNlcjIyOTE4NDM4", ... }, "event": "head_ref_deleted", "created_at": "2020-08-26T20:07:17Z", ... } ]
イベントのリストが返ってきていますね。リスト要素のevent
フィールドが、そのオブジェクトが表すイベントの種別です。今回の例だと、イベント種別は、上からcommitted
、reviewed
、committed
、head_ref_force_pushed
、referenced
、merged
、closed
、head_ref_deleted
ですね。それぞれのイベント種別についてはこの記事の次項でまとめますが、 公式のドキュメント によくまとまってます。
event
以外のフィールドを見ると、該当のイベントの詳細がわかります。例えば、committed
イベントだと、sha
からコミットハッシュが、message
からコミットメッセージがわかりますね。
イベント一覧
どのようなイベント種別が存在するか、それぞれのイベント種別にどのようなフィールドが存在するかを簡単にまとめておきます。自分から見て重要そうなイベントの重要そうなフィールドについてのみ書くので、この記事ではだいたいこんな情報が取れるんだなということを把握するのにとどめて、すべてのイベント種別についてちゃんと知りたい場合は 公式ドキュメント を参照してください。ただし、自分が見つけた範囲でもforce pushを表すhead_ref_force_pushed
というイベント種別がドキュメントになかったり、イベント種別によって実際のAPIレスポンスとフィールドのキーが異なったりしたのでもしかしたら公式ドキュメントが実際の仕様に追従できていない部分があるかもしれません。
共通
ほとんどのイベント種別に共通のフィールド。
event
: イベント種別node_id
:global node id
。id
というフィールドも存在するが、イベント種別によってはid
がないこともあるのでイベントのユニークなIDがほしいときはnode_id
を使うのが良さそう(たぶん)created_at
: イベントの発生日時
assigned
Issue/PRがアサインされたこと。
committed
コミットのこと。
sha
: コミットハッシュurl
: コミットを取得するAPIのURLhtml_url
: コミットを表示するHTMLのURLauthor
: コードを書いた人name
email
date
committer
: コミットした人。author
との違いは https://stackoverflow.com/questions/18750808/difference-between-author-and-committer-in-git 参照name
email
date
message
: コミットメッセージ
commented
Issue/PRにつくコメントのこと。
url
html_url
actor
: コメントした人login
id
avatar_url
body
: コメントの本文
mentioned
メンションのこと。
actor
: メンションされた人login
id
avatar_url
メンションされた人の情報しかなく、メンションした人やメンションがあったコメントに関してはこのイベントでは取得できないみたいです。
review_requested
レビューリクエストのこと。
review_requester
: レビューをリクエストした人login
id
avatar_url
requested_reviewer
: レビューをリクエストされた人login
id
avatar_url
reviewed
レビューのこと。
user
: レビュアーlogin
id
avatar_url
body
: レビュー時につけたコメントstate
: レビューのstate。commented
changes_requested
approved
のいずれかhtml_url
author_association
: レビュアーレポジトリ権限。OWNER
COLLABORATOR
など
merged
PRのマージのこと。
actor
: マージした人login
id
avatar_url
commit_id
: マージコミットのコミットハッシュ
closed
Issue/PRのクローズのこと。
actor
: クローズした人login
id
avatar_url
結論
Timeline APIはIssue/PRの流れがわかってうれしい。Issue/PRを定期的に監視してなにかあったらいい感じで通知するみたいなツールを自分で作りたいときに使えそうです。