octokit.rbの使い方まとめ


## 概要
octokit.rbとは、GitHub API v3に対応したRubyのクライアントである。リポジトリのREADMEを見てもわからなかった部分が多いので、メモ

### リポジトリの場所
github:octokit/octokit.rb

## 基本的な使い方

### アカウント設定
#### username/passwordでログイン
usernameとpasswordを記述するシンプルな例です。

```ruby:Ruby
client = Octokit::Client.new login: "USER_NAME", password: "PASSWORD"
client.user # GitHub上のユーザー情報を取得
```

#### 2段階認証を有効にしている場合
GitHubのログインに2段階認証を有効にしている場合、下記のようにリクエストヘッダーを追加しなければなりません。

```ruby:Ruby
client = Octokit::Client.new login: "USER_NAME", password: "PASSWORD"
user = client.user("defunkt", :headers => { "X-GitHub-OTP" => "<your 2FA token>" }) # GitHub上のユーザー情報を取得
```

毎回リクエストする度にX-GitHub-OTPをヘッダーに追加しなければならないので、下記のようにOAuth tokenを発行すると良いです。

```ruby:Ruby
client = Octokit::Client.new login: "USER_NAME", password: "PASSWORD"
token = client.create_authorization(:scopes => ["user"], :headers => { "X-GitHub-OTP" => "<your 2FA token>", :note => "<name of token>" })
# => <your new oauth token>
```

`note`には任意の名前を指定します。ここで発行されたトークンは、[Personal access tokens](https://github.com/settings/tokens)に反映されます。

#### oauth tokenでログインする

発行したOAuth Tokenは下記のようにクライアントで利用します。

```ruby:Ruby
client = Octokit::Client.new access_token: token
```

僕はaccess_tokenというキー名を忘れがちです。何かいい方法があれば良いのですが…。

#### .netrcにusername/passwordを書く
まず~/.netrcに下記のように書きます。

```.netrc
machine api.github.com
  login USER_NAME
  password PASSWORD
```

PASSWORDにはOAuth Tokenを指定することもできます。

clientは下記のように作成します。

```ruby:Ruby
client = Octokit::Client.new netrc: true
client.user # GitHub上のユーザー情報を取得
```

.netrcを利用する場合はnetrc gemが必要だそうです。(未確認)

## GitHubから情報を取得する

developer.github.com に公開されているAPIと対になるメソッドがOctokit::Clientに定義されています。例えばIssueの取得であれば、

```ruby:Ruby
client = Octokit::Client.new
client.issues 'kompiro/hoge' # => kompiro/hogeリポジトリのissueを取得
```

と言った感じ。何も指定しないと、1ページ辺り50件で取得する。ページングをするには、後述するrelationの理解が必要。

このissuesメソッドは```Octokit::Client::Issues```に定義されている。同様にRepositoryの操作であれば、```Octokit::Client::Repositories```に定義されている。

## 取得したオブジェクトの属性にアクセスする

octokit.rbで取得したデータは、そのオブジェクトの属性であれば、直接アクセスできます。

```ruby:Ruby
user = client.user
user.login
# => "kompiro"

user.name
# => "Hiroki Kondo"
```

## 関連するオブジェクトを取得する

octokit.rbは、関連するオブジェクトの取得は属性「rels」を経由して取得します。これはoctokit.rbの内部で使っている「Sawyer」の特徴です。

例えば、ユーザーの所有するリポジトリの一覧を取得するには

```ruby:Ruby
repos_rel = client.user.rels[:repos]
repos_rel.href
# => ""https://api.github.com/users/USER_NAME/repos

repos_rel.get.data
# => ユーザーの所有しているリポジトリのデータを取得
```

### ページングで前のページ/次のページの取得をするには？

例えば取得したIssuesの次のページを取得するには、下記のようにアクセスします。

```ruby:Ruby
issues = client.issues 'kompiro/hoge'
next_page = client.last_response.rels[:next].get.data
```

全てのページを取得するには、

```ruby:Ruby
last_response = client.last_response
while last_response.rels[:next]
  last_response = last_response.rels[:next].get
  issues.concat last_response.data
end
```

というようにすれば取得できるけど、```client.auto_paginate = true```とすると、全てのページを走査して単一の配列にします。


## その他
### ユーザーアイコンを表示するには？

GitHubに表示されているユーザーアイコンは、Gravatarに登録したアイコンが表示されているはずです。つまり、ユーザーアイコンを表示するには、Gravatarにアクセスするのが手っ取り早いです。

GravatarのIDはclient.user.gravatar_idで取得できます。

```ruby:Ruby
client.user.gravatar_id
# => "e7bf914803991968f32535ff47cee5d2"
```

これは、Gravatarの画像用のハッシュなので、そのまま下記のようにURLを作るメソッドがあると、Gravatarに登録されたアイコンを取得できるURLがわかる。helperにしておくと便利。

```ruby:Ruby
def gravatar_url gravatar_id
  "http://www.gravatar.com/avatar/#{gravatar_id}"
end
```

## GitHub GraphQL にアクセスする(2018/03/25 加筆)

`graphql-client` という gem もあってschemaのチェックとかしてくれるけど、基本 GraphQL Explorer を使ってクエリは作ると思う。octokitでやっちゃいましょ

```ruby
require 'octokit'
require 'json'

client = Octokit::Client.new(access_token: ENV.fetch('GITHUB_TOKEN'))

query = <<GRAPHQL
      query($owner: String!, $repo: String!) {
        repository (owner: $owner, name: $repo){
          pullRequests(
            first: 100,
            states: MERGED) {
            nodes {
              number
              title
              mergeCommit {
                oid
              }
              author {
                login
              }
              mergedAt
              participants(first: 100) {
                nodes {
                  login
                }
              }
            }
            pageInfo {
              hasNextPage
              hasPreviousPage
              startCursor
              endCursor
            }
          }
        }
      }
GRAPHQL

variables = { owner: 'kompiro', repo: 'pr-summary' }
param = {query: query, variables: variables}.to_json
result = client.post '/graphql', param
```