LoginSignup
8
6

More than 3 years have passed since last update.

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

Last updated at Posted at 2018-10-01

2019/08/17 更新

Githubが公式にサポートしたようです。
Managing the automatic deletion of branches

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

ちゃんとブランチ消してますか?

あなたはGitHubでPRをマージした後、きちんとブランチを削除していますか?
GitHubにはマージ後に「Delete branch」ボタンを表示してくれるんですけどね
スクリーンショット 2018-09-27 21.31.51.png

なーんか押すの忘れちゃうんですよね
ついにはよく共同で開発している@chaspyに「運用変える?」と言われてしまう始末…ごめんなさい:head_bandage:
スクリーンショット 2018-09-27 21.30.48.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のページへどうぞ。
delete-branch-bot

環境

簡単にご紹介します。

構成

AWSのAPI GatewayLambdaを使っています。
GitHubAppからGitHubのPullRequestEventがPOSTされるので、API GatewayでLambdaにゲートウェイしてあげて、Lambda上でGitHubRepositoryに対してブランチを削除するREST APIを叩くだけです。
delete-branch.png

言GO

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

GitHubAppの認証

GitHubAppの認証にはGitHubAppに紐づくPrivateKeyをJSON Web Tokens(JWT)で署名して認証する必要があります。
ここはライブラリに力を借ります。
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してあげてると良いでしょう。

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を参照下さい。

最後に

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

8
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
6