はじめに
この記事はand factory.inc Advent Calendar 2022 2日目の記事です。
昨日は @y-okudera さんの SnapshotTestingでURLで取得するリモートの画像の代替品としてAsset Catalogの画像を使用する でした。
目的
Dangerの公式ガイドでは、GitHubのユーザーのPersonal Access Tokenを用いることを推奨していますが、個別にユーザーを作る必要があり、以下の観点でよくないです。
- Parsonal access token はその性質上権限が強すぎるので、流出した時のセキュリティ的なリスクが高い。
- BOTとはいえ、ユーザー扱いであることに変わりはないので、Organizationのシート(人数)を1枠使ってしまう。
そこでGitHub Appsを経由して用いれば、ユーザー作成なしかつ、Botとして扱えるとのことなので、やってみました。
概要
Personal Access Tokenでは対象ユーザーのAccess TokenをGitHub上で作成した後はCIなどの環境変数として取り回すだけですが、GitHub AppsはAppの作成&連携やAccess Token生成を自前でコネコネやる必要があります。
弊社ではCircleCIを用いてますので、CircleCIで行っていきます。
Personal Access Token使用 | GitHub Apps使用 |
---|---|
GitHub Apps(Danger ボット)作成手順
では、Dangerで走るところまでやっていきましょう。
GitHub上での設定
まずはGitHubからです。
GitHubの設定より、「Settings」→「Developer settings」を開く。
「New GitHub Apps」より新規作成
それぞれ項目を埋める
-
基本情報
- 以下は必須ですが、適当につける
- GitHub App name
- 説明
- Homepage URLはGitHub上にページが作られる
- Expire user authorization tokens のチェックを入れることで「refresh_token」を使用できる
- 以下は必須ですが、適当につける
-
Permissions
- MetadataRead-only
- Issues,PullRequests,Commit statusesをRead and write
-
Subscribe Eventsは特にいじらず
-
GitHubを他のorganizationに連携できるように
Appsページで「AppID」「Installation ID」を確認、「Private Key」を作成
-
AppID
-
Private Key
- 以下のボタンPrivate Keyが生成され、
.pem
ファイルがダウンロードされます。
- 以下のボタンPrivate Keyが生成され、
-
Installation ID
-
サイドメニューの「Install App」より、連携先のorganaizationを選択
-
連携リポジトリを選択後、「Install & Request」
-
出てくるURLの末尾が「Installation ID」です
- APIから取る方法が一般的ですが、めんどくさかったので
-
Circle CIの設定
「Project Settings」→「Environment Variables」より設定
- 先程控えた値を投入
「Project Settings」→「Advanced」で「Only build pull requests」をOnにする
- OnにしないとPR作成した後に流れなくなるため
ソースコード側の修正
スクリプトを作成
- 要はGitHub Appsのaccess tokenを取得している
- JWT作成→access token取得→環境変数に入れる
#!/usr/bin/env bash
echo -e "\n>>> generate a JWT\n"
JWT=$(ruby << EOF
require 'openssl'
require 'jwt' # https://rubygems.org/gems/jwt
require 'base64'
# Private key contents
pem = Base64.decode64(ENV['GITHUB_APP_PEM_BASE64'])
private_key = OpenSSL::PKey::RSA.new(pem)
# Generate the JWT
payload = {
# issued at time, 60 seconds in the past to allow for clock drift
iat: Time.now.to_i - 60,
# JWT expiration time (10 minute maximum)
exp: Time.now.to_i + (10 * 60),
# GitHub App's identifier
iss: ENV['GITHUB_APP_ID']
}
jwt = JWT.encode(payload, private_key, "RS256")
puts jwt
EOF
)
echo -e "\n>>> create an installation access token\n"
echo $JWT
TOKEN=$(curl -s -D /dev/stderr -X POST \
-H "Authorization: Bearer ${JWT}" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/app/installations/${GITHUB_APP_INSTALLATION_ID}/access_tokens \
| jq -r .token)
echo export DANGER_GITHUB_API_TOKEN="${TOKEN}" >> $BASH_ENV
.circleci/config.yml
にdangerのコマンド用意
- 方法は色々あるけど、今回はfastlaneを利用します
- 先程のスクリプトでAccessToken生成後、それを用いてDanger走らせる
lane :run_danger do
danger(
danger_id: "test",
dangerfile: "./DangerFile",
github_api_token: ENV["DANGER_GITHUB_API_TOKEN"],
verbose: true
)
end
# circle ci
danger:
description: "Run danger"
steps:
- run:
name: Refresh token
command: sh scripts/refresh_github_apps_token.sh # 先程のアクセストークン取得
- run:
name: Echo check token
command: echo $DANGER_GITHUB_API_TOKEN # テスト
- run:
name: Run danger
command: bundle exec fastlane run_danger
実行してみる!
まとめ
- GitHub Apps1つでOrgnization連携を複数行い、スクリプト共有すれば簡単に導入できそう!
- 今回はDanger BotをGitHub Appsで作成してみるでしたが、GitHub Appsは他にも色々できる!
- ブランチ操作、issue作成&ブランチ作成などなど、便利!
参考