PullRequestがマージされたら自動でブランチを削除するGitHubApp(delete-branch-bot)を作った

# 2019/08/17 更新
Githubが公式にサポートしたようです。
[Managing the automatic deletion of branches](https://help.github.com/en/articles/managing-the-automatic-deletion-of-branches)

リリースして1年も経っていませんが、本体に必要とされる機能をBotとして作ることができて良い経験になりました。これをキッカケにまた何か作りたいと思います。

# ちゃんとブランチ消してますか？
あなたはGitHubでPRをマージした後、きちんとブランチを削除していますか？
GitHubにはマージ後に「Delete branch」ボタンを表示してくれるんですけどね
<img width="788" alt="スクリーンショット 2018-09-27 21.31.51.png" src="https://qiita-image-store.s3.amazonaws.com/0/37268/a13ed528-ce75-fdcc-e196-287f94172979.png">

なーんか押すの忘れちゃうんですよね
ついにはよく共同で開発している@chaspyに「運用変える？」と言われてしまう始末…ごめんなさい:head_bandage:
<img width="460" alt="スクリーンショット 2018-09-27 21.30.48.png" src="https://qiita-image-store.s3.amazonaws.com/0/37268/7eb70ce5-8c25-0347-1f5c-ab68ca4061cd.png">

「自動で消す方法なんてすぐ見つかるでしょ」と検索してみるもなかなか見つからず。
20,30分探しても有効な情報が見つけられなかったので、「作ろう」ということになり
@chaspy と一緒に`delete-branch-bot`を作りました。(もし他に方法があれば教えて下さい。)

GitLabはMergeRequestを作成する際にオプションでマージ後ブランチを削除するチェックボックスがあるのですが…
# What's delete-branch-bot?
GitHubのRepository単位でインストールが行えるGitHubAppです。
PullRequestがmergeもしくはcloseされると、自動で対象のブランチを削除します。(なんて分かりやすいAPP名なんだ)

# How to install?
GitHubの検索窓で、`delete-branch-bot`と検索するか、[Appのページ](https://github.com/apps/delete-branch-bot)へどうぞ。
[![delete-branch-bot](https://qiita-image-store.s3.amazonaws.com/0/37268/83e98e86-b020-f18c-30d5-434babe45496.png "delete-branch-bot")](https://github.com/apps/delete-branch-bot)

# 環境
簡単にご紹介します。

## 構成
AWSの`API Gateway`と`Lambda`を使っています。
GitHubAppからGitHubのPullRequestEventがPOSTされるので、API GatewayでLambdaにゲートウェイしてあげて、Lambda上でGitHubRepositoryに対してブランチを削除する`REST API`を叩くだけです。
![delete-branch.png](https://qiita-image-store.s3.amazonaws.com/0/37268/fce9e7d6-ab40-7b06-ac53-01aeb78baade.png)

## 言GO
Golangです。
最初はGithubが公式に出しているライブラリを使おうということで、Rubyが候補に上がったのですがLambdaがRubyには対応してなかったため、最近利用している&ライブラリも豊富なGolangを選択しました。
Googleがサードパーティとして公開している[go-github](https://github.com/google/go-github)を使えば安全&簡単にGithubAPIが使用できます。
ドキュメントは[go-github[doc]](https://godoc.org/github.com/google/go-github/github)に書いてあります。(Goのドキュメントは他のDocに比べて見づらい…)

## GitHubAppの認証
GitHubAppの認証にはGitHubAppに紐づくPrivateKeyを`JSON Web Tokens(JWT)`で署名して認証する必要があります。
ここはライブラリに力を借ります。
[ghinstallation](https://github.com/bradleyfalzon/ghinstallation)はGitHubAppの情報からJWT　Tokenを生成してHTTPリクエストにTOKENを付加してくれる非常に素晴らしいライブラリで、go-githubのドキュメントにもGitHubAppの認証をしたい場合はこれ使えと書いてます。

### ハマったところ
`ghinstallation`の使用例ですが、`integration ID`(例で`1`となっている引数)と`installation ID`(例で`99`となっている引数)に何を指定しているのか、ライブラリの中身を読んでもピンと来なかったところです。もちろん指定を間違っていると正しい署名が作成されないので、認証エラーとなりRepositoryに対してリクエストを送ることができません。
ちなみに、`integration ID`にはGitHubAppのAPPIDを指定します。`installation ID`はインストールされたRepositoryに紐づくインストールIDです。`installation ID`は動的に変動しますが、GitHubAppのWebhook先にPOSTされるJSONに記載されているので、Parseしてあげてると良いでしょう。

```golang
func main() {
    // Shared transport to reuse TCP connections.
    tr := http.DefaultTransport

    // Wrap the shared transport for use with the integration ID 1 authenticating with installation ID 99.
    itr, err := ghinstallation.NewKeyFromFile(tr, 1, 99, "2016-10-19.private-key.pem")
    if err != nil {
        log.Fatal(err)
    }

    // Use installation transport with github.com/google/go-github
    client := github.NewClient(&http.Client{Transport: itr})
}
```

GitHubAppの認証についての公式ページは[Authenticating with GitHub Apps](https://developer.github.com/apps/building-github-apps/authenticating-with-github-apps/)を参照下さい。

# 最後に
これで心理的なプレッシャーから開放されて、よりよいGitHubを用いた開発ができそうです。
アイコンは近々できる予定！