GitHub APIの仕組みを知り、APIでrepositoryを作成しよう

## はじめに

[ローカルのGitリポジトリをGItHub等他サービスに丸ごと移植する](https://qiita.com/developer-kikikaikai/items/b9e4fe4337bae3eab01b)方法をスクリプト化したのはいいのですが、一つ一つ手動でUIから空リポジトリ作成するの？めんどくさくない？
というわけでGitHubのリポジトリをコマンドベースで作成する方法を探しました。結論を言うと **GitHub API v3** を使えばいいです。
また、APIを使う為には **OAuth認証** を行う必要があります。

## GitHubの認証 - [Authorizing OAuth Apps](https://developer.github.com/apps/building-oauth-apps/authorizing-oauth-apps/)

### Access Tokenを発行して使う。発行はUIから可能
GitHubでは、APIを利用する為にAccess Tokenを取得する必要があります。
ちょっとAPIを使いたいだけなら[tokens](https://github.com/settings/tokens) から `New personal access token`を選択すればOKです。

### APIを利用したAccess Tokenの生成も可能
例えばアプリケーション等でAccess Tokenを発行する仕組みを作る場合の流れは以下となります。

1. OAuth Appsを登録⇒Client IDとClient Secretを取得
2. Client IDを使い、Authorize APIで認証⇒Codeを取得
3. Client ID, Client Secret, Codeを使い、access_token APIを実行⇒Access Tokenを取得
3. 以降はAccess Tokenを使ってリポジトリの操作

OAuth的に言うと、OAuth Appsを登録する場所が認可サーバー

最初に[こちら](https://github.com/settings/applications/new)からOAuth Appsの登録を行います。

<img width="614" alt="auth.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252277/ee8f26e0-37b7-05a3-a56e-63a27ee0143a.png">

この時に **Authorization callback URL** というのを登録するのですがこれが特徴的です。次のAuthorization API (`https://github.com/login/oauth/authorize?client_id=$CLIENT_ID&scope=repo`) を実行するとその応答にCodeが入ってくるわけではなく、**Authorization callback URLにcode=${code}のqueryとして渡されます**

そのままAccess Tokenが発行されるわけではなく一旦Codeがクライアント側が登録したアプリケーションに送信されるというのが面白いですね。容易にAccess Tokenが発行できないようガードを強固にしたい場合に考慮したとかそんな感じなのかなと予想。

また、Codeはqueryで指定され、該当ページにリダイレクトされる形になるので、callback URL用のサーバーを用意しなくても、頑張ってqueryを覗いて自分でAPIをコールしてもOKです。

#### Private repositoryの参照について

Defaultだと、このaccess tokenではprivate repositoryが参照できません。これも上記access token設定の為です。
`repo: Full control of private repositories` を設定すればOK。

参考: [GitHub API v3 でプライベートリポジトリの情報が取れない問題の解決方法](https://gotohayato.com/content/460)

#### 利用サンプル

[GitHub API v3 でリポジトリを作成して、ファイルをコミットする](https://qiita.com/ngs/items/34e51186a485c705ffdb)を参考にさせていただき、[サンプルツール](https://github.com/developer-kikikaikai/githubapi)を作りました。
外部サーバーに置いてcallback URLに登録しておけば、`https://github.com/login/oauth/authorize?client_id=$CLIENT_ID&scope=repo` のresponseで `{"access_token":"yyyy"}` が取れます。

シーケンスに起こすとこんな感じですね。
<img width="1062" alt="sequence.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252277/ec86aef5-a5b3-848f-5409-ecf44ad0604c.png">


## Access Tokenが取れたら [GitHub API v3](https://developer.github.com/v3/)を利用

上記のAPI仕様書を見ていると、RESTだけでなく色々な用途が充実してますが、とりあえずrepositoryの作り方だけ紹介。同じく[GitHub API v3 でリポジトリを作成して、ファイルをコミットする](https://qiita.com/ngs/items/34e51186a485c705ffdb)に詳しく使い方が紹介されています(もう全部参考元を見ればいいんじゃないかな)

APIの認証は、Access Tokenを`Authorization: bearer AccessToken` でHTTP headerに設定することで成立します。
後は `https://api.github.com/user/repos` APIにBodyでrepository名を指定してPOSTすればOKです。

```
curl -H "Authorization: bearer $TOKEN" -X POST \
    -d "{"name":"repository name","auto_init":true or false, "private": true or false}" \
    https://api.github.com/user/repos
```

一応こちらも[サンプルツール](https://github.com/developer-kikikaikai/githubapi/tree/master/repos)にスクリプト化して入れています。

## 参考

公式
[GitHub API v3](https://developer.github.com/v3/)
[Authorizing OAuth Apps](https://developer.github.com/apps/building-oauth-apps/authorizing-oauth-apps/)

参考記事
[GitHub API v3 でプライベートリポジトリの情報が取れない問題の解決方法](https://gotohayato.com/content/460)
[GitHub API v3 でリポジトリを作成して、ファイルをコミットする](https://qiita.com/ngs/items/34e51186a485c705ffdb)
アプリ目線でのGitHub OAuthの話[[iOS]OAuth認証を極める（GitHubAPIで学ぶOAuth認証のフロー）](https://qiita.com/yyokii/items/87d4975716f1a6ed620c)
こんな感じでとても分かりやすくまとめられていました。

<img width="800" alt="repos.png" src="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.amazonaws.com%2F0%2F138735%2Fe9bf04a9-8dad-4c03-a20a-122030af69c1.png?ixlib=rb-1.2.2&auto=compress%2Cformat&gif-q=60&s=15039251d7c9f21e1831a87585c3d748">