概要
GithubのPRがレビュー済みになった際にラベルを付けておくと、レビュー済みPRが見分けやすくて便利です。
今回その作業をGithub Appで自動化することにしました。
以下はその作業ログです。
Github Appの作成
作成するAppの仕様
今回作成するAppは
すべてのreviewerがApproveしたらreviewedラベルをPRに追加する
という仕様にします。
Probot
ProbotはGithub Appのframeworkです。
ドキュメントも充実していて、Github Appの作成を効率良く行えるので、今回はこれを使うことにしました。
Node.js
Probotを使うにはNode.jsが必要になります。
このページを参照して、動作に必要なバージョンをインストールしておきます。
雛形の作成
yarnとnpmを使う方法がドキュメントにはありますが、今回はnpmを使っていきます。
下記コマンドを実行すると、Probotが雛形を作ってくれます。
npx create-probot-app {app-name}
対話形式でApp nameなどを聞かれるので答えていきます。
Gihub repositoryへのpush
ここまでのソースをGithubのrepositoryへpushしておきます。
smee.io
ローカルでの開発時にもGithubのwebhookを受け取れるようにするため、
smee.ioを利用します。
Start a new channel
ボタンを押すと、Webhook Proxy URL
が生成されるので、
このURLとローカルのappを結びつけて開発していきます。
Probotはsmee.ioと簡単に連携できるようになっています。
Github Appの作成
https://github.com/settings/apps/new
から新規Appを作成します。
Homepage URL
にはgithub repositoryのURLを、
Webhook URL
にはsmee.ioで生成したURLを、
Webhook secret (optional)
にはひとまずdevelopment
をいれておきます。(あとで書き換えます)
Permissions
はGithub Appでアクセスできる権限を指定します。
今回作成するAppはPull Requestのreviewの内容をみて、labelを追加するので
Pull requests
にRead-only
,labelを操作するのはIssueのpermissionのようなので
Issue
にRead & Write
を設定します。
それ以外はデフォルトのままにしておきます。
Subscribe to events
はApprove
されたことの通知を受けるためにPull request review
を、それとPRのheadブランチ更新のタイミングでApprove
が無効になることがあるので、それも検知するためにPull request
もsubscribeしておきます。
Where can this GitHub App be installed?
はAppの公開範囲をどこまでにするのかの設定ですが、一般に公開されて問題なければ
Any account
にしておきます。
設定が終わったらCreate Github App
ボタンを押してAppを作成します。
private keyの生成
Appの作成後の画面で、Generate a private key
ボタンがあるので、
ボタンを押してprivate keyを発行しておきます。
このkeyはAppの実行に必要になります。
発行すると自動的にkeyがダウンロードされるので、レポジトリ直下に移動しておきます。
(既に.gitignoreで*.pemが指定されているので、git管理外になります。)
.envの設定
.env.example
をコピーして.env
を作ります。
.env内のAPP_IDとWEBHOOK_PROXY_URLを設定します。
APP_IDはhttps://github.com/settings/apps/{app-name}
ページ内に書かれているID
の値で、WEBHOOK_PROXY_URL
にはsmee.ioのURLをいれておきます。
Appの起動
npm run dev
で起動できることを確認します。
webhookの取得
今回作成する AppはPRがApproveされたタイミングで、全てのreviewerがApproveしたかをチェックします。
そのため、reviewがsubmitされたタイミングの通知を監視します。
app.on('pull_request_review.submitted', async context => {
app.log('submitted')
}
Approve回数の取得
Approveされたreviewを取得するために、reviewのリストを取得します。
const params = context.issue()
const reviews = await context.github.pullRequests.getReviews(params)
context.github
はocotokit/restのインスタンスで、これを使うと簡単にGithub APIにアクセスできます。
reviewのstatusがAPPROVED
になっているものがApproveされた際のreviewなので、この回数をカウントしておきます。
reviewerの取得
reviewerを直接取得するAPIは存在しないようなので、reviewerに指名されてまだ一度もreviewしていないuserを取得するgetReviewRequests
の数と、reviewしたすべてのuser数を組み合わせることでreviewerの総数とします。
PRを作成したuserもreviewはできるので、PRの作成者はカウントしないようにしておきます。
PRの作成者は
const params = context.issue()
const pull_request = await context.github.pullRequests.get(params)
const creator = pullRequest.data.user.login
として取得できます。
ラベルの追加
reviewerの数==Approveの数
になったらラベルを追加します。
ラベル名はひとまずreviewed
としておきます。
ラベルの追加は
const labels = context.issue({ labels: ['reviewed'] })
context.github.issues.addLabels(labels)
で行います。
labelsの配列に複数ラベルを指定すれば、一度にまとめてラベルを追加することもできます。
ラベルの削除
Githubのレポジトリの設定でDismiss stale pull request approvals when new commits are pushed
にチェックがついていると、reviewがApproveされたあと、再度該当branchにpushが走ると、そのタイミングでApproveが無効になります。
その際は再度Approveしてもらう必要があるので、ラベルも取り除いておきます。
PRの対象branch更新のeventは pull_request.synchronize
を監視することで取得できます。
この際にreviewer数 !== Approve数
になっていて、かつreviewed
ラベルがついていたらラベルの削除APIを投げておきます。
const rmLabel = context.issue({ name: 'reviewed' })
context.github.issues.removeLabel(rmLabel)
ラベル名の変更
ここまではラベルをreviewed
固定にしていましたが、設定で変えられるようにしておきます。
このGithub Appをインストールしたレポジトリに.github/reviewed.yml
があった場合、そこに書かれているラベルを使用し、なければデフォルトのreviewed
ラベルを使うようにします。
labelName: ok
probot-config
を使うと簡単にymlにアクセスできるので、package.jsonに追加しておきます。
npm install -S probot-config
probot-configを使ってreviewed.ymlを取得します。
const getConfig = require('probot-config')
const defaultConfig = {
labelName: 'reviewed'
}
const config = await getConfig(context, 'reviewed.yml') || defaultConfig
const label = config.labelName
deploy
Probotのdocumentにはdeploy先として、Glitch,Heroku,Nowが紹介されていますが、今回はNowを使用します。
https://probot.github.io/docs/deployment/#now
上記URLにdeployの手順が書いてありますが、この手順ではエラーが出てしまったので、
https://github.com/probot/probot/blob/master/docs/deployment.md#now
側の手順を実行します。
違いはprivate_keyをbase64エンコードしてNowに送っている箇所です。
なお、デプロイの度に生成されるURLが変わるみたいなので、毎回aliasを付け直す必要があるようです。
Webhook APIの書き換え
Nowでaliasを振ったAPIのURLでGithub AppのWebhook URL
を変更します。
併せてWebhook secret
も変更しておくと安全です。
Webhook secret
を変更した際には、再度Nowのdeployが必要になります。
repository & app
今回作成したAppのレポジトリはこちらになります。
Appのリンクはこちらになります。
気に入って頂けたらInstallして使ってみてもらえると嬉しいです。