Posted at

GitHub Branch ProtectionをGitHub APIで設定


GitHub Branch Protection

GitHubのBranch Protectionという機能は以下のような機能が実現でき、GitHub運用のルールを強制的に守らせることができるので便利です。



  • masterブランチへの直接のpushの禁止

  • プルリクをマージする時、コードレビューを経ないとマージできないようにする

  • CIが正常終了しないとマージできないようにする


手動設定

Branch ProtectionはGitHubのWebサイトから手動で設定することができます。

[Your Repository] => [Settings] => [Branches]

と遷移していくと、設定画面にたどり着きます。

screen0.png

screen1.png

screen2.png

各項目の意味は https://dev.classmethod.jp/tool/github/protect-branch/ などを参考にしてください。


GitHub APIによる設定

ただ、新しいプロジェクトを作るたびにポチポチ設定するのってダサいですよね。

GitHub APIを使って、自動設定しましょう。

自動設定スクリプト( protect.sh )とBranch Protectionの設定ファイル( protections.json )を下記にように配置して、

.

└── .github
├── protect.sh
└── protections.json

下記のコマンドを実行すると、設定ができるようにします。

$ bash .github/protect.sh


自動設定スクリプト

スクリプトを実行するために下記のコマンドが必要なので入れてください。



  • hub : GitHub APIクライアント


  • jq : jsonをパースするコマンド

macの場合、下記コマンドで入ります。

$ brew install hub

$ brew install jq

スクリプトのコードは下記です。

基本、これをそのままコピペすれば動くはずです。


protect.sh

#!/bin/bash

DIR=$(cd $(dirname $0); pwd)

hub api user
echo -e "\nLogged in.\n\n"
TOKEN=`cat ~/.config/hub | grep oauth_token | sed "s/ //g" | sed "s/oauth_token://g"`

REPO=`git config --get remote.origin.url | sed s/git@github.com://g | sed s/.git$//g`

RES=`cat "${DIR}/protections.json" | jq -r 'to_entries[] | "\(.key)__DELIMITER__\(.value)"'`
for line in ${RES}; do
BRANCH=`echo ${line} | sed -e "s/__DELIMITER__.*$//g"`
BODY=`echo ${line} | sed -e "s/^.*__DELIMITER__//g"`
curl \
-X PUT \
-H "Accept: application/vnd.github.luke-cage-preview+json" \
-H "Authorization: token ${TOKEN}" \
"https://api.github.com/repos/${REPO}/branches/${BRANCH}/protection" \
-d ${BODY}
done


5行目の

hup api user

の箇所で GitHub APItokenを未取得であれば、id, passwordを聞いてくるので、入力すると、tokenを取得して設定ファイルに保存しています。


設定ファイル

設定ファイル(protections.json)は例えば、下記のように設定します。


protections.json

{

"dev": {
"required_status_checks": {
"strict": true,
"contexts": [
"ci/circleci"
]
},
"required_pull_request_reviews": {
"dismiss_stale_reviews": true,
"require_code_owner_reviews": false,
"required_approving_review_count": 1
},
"enforce_admins": true,
"restrictions": null
},
"master": {
"required_status_checks": {
"strict": true,
"contexts": [
"ci/circleci"
]
},
"required_pull_request_reviews": {
"dismiss_stale_reviews": true,
"require_code_owner_reviews": false,
"required_approving_review_count": 1
},
"enforce_admins": true,
"restrictions": null
}
}

これは

{

"ブランチ名1": { /* Branch Protectionの設定 */ },
"ブランチ名2": { /* Branch Protectionの設定 */ },...
}

という構造になっていて、Branch Protectionの設定の部分は

https://developer.github.com/v3/repos/branches/#update-branch-protection

にそれぞれのパラメータの詳細が載っています。

今回の例ではmasterブランチとdevブランチに対して、マージを行う時、1人以上のレビューを必須にし、CircleCIが正常終了していないとマージできないようにしています。


終わりに

今回のソースはhttps://github.com/Arahabica/GitHubProtectionSampleにも置いています。