概要
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して使ってみてもらえると嬉しいです。