Gitリポジトリへのpush時にrubocopでコードチェックを実行
0. 動機
Gitのpre-commitフックで、コードチェックをかけるのは、個々人の設定に依存してしまうので、リモートへのpush時にもコードチェックをかけたい。
1. 下準備
Gitリポジトリのユーザー環境に、コードチェックに使用するrubocop
をインストールする。
2. 対象のプロジェクトでの修正
コードのpush前に、チェックを実行させるので、Git
のpre-receiveフックを作成する。
pre-receiveフックのスクリプトの方針は、下記。
- プルリクエスト方式で開発を行っているので、ブランチが存在しない状態でもpushされるので、その場合は、プルリクエストをおこすベースの開発ブランチとの差分を対象にコードチェックする
- 差分が大量に発生するケースについては、ブランチ指定でコードチェック自体を行わないように指定できるようにする
pre-receiveフックのスクリプトに指定する内容は、下記(GitLabで、動作させる為に、環境変数の対応を行っているので、適宜、調整)。
#!/bin/bash
UNCHECK_BRANCH=(master staging)
DEV_BASE_BRANCH="dev"
exists_branch() {
git show-ref --verify --quiet refs/heads/${1}
status=$?
return $status
}
check_code() {
TEMPDIR=`mktemp -d`
# マージリクエスト系のように、ブランチが存在しない時は、開発用ベースブランチを使用する
if exists_branch ${4}; then
oldrev=$(git rev-parse ${1})
else
oldrev=$(git rev-parse refs/heads/${DEV_BASE_BRANCH})
fi
newrev=$(git rev-parse ${2})
for file in $(git diff ${oldrev} ${newrev} --name-only | grep '\.rb$' | grep -v 'schema\.rb'); do
object=`git ls-tree --full-name -r ${newrev} | egrep "(\s)${file}\$" | awk '{ print $3 }'`
if [ -z ${object} ]; then continue; fi
mkdir -p "${TEMPDIR}/`dirname ${file}`" &> /dev/null
git cat-file blob ${object} > ${TEMPDIR}/${file}
done;
# 開発用ブランチにあるrubocopの定義ファイルをコピー
git show refs/heads/${DEV_BASE_BRANCH}:.rubocop.yml > ${TEMPDIR}/.rubocop.yml
# GitLab経由のマージリクエスト処理時の環境変数を指定しない状態で実行する
DEFAULT_RUBYOPT=${RUBYOPT}
DEFAULT_GEM_PATH=${GEM_PATH}
unset RUBYOPT GEM_PATH
# rubocopの実行
rubocop -c ${TEMPDIR}/.rubocop.yml ${TEMPDIR}
RET_VALUE=$?
RUBYOPT=${DEFAULT_RUBYOPT}
GEM_PATH=${DEFAULT_GEM_PATH}
rm -rf ${TEMPDIR} &> /dev/null
return ${RET_VALUE}
}
while read oldrev newrev refname
do
branch_name=$(basename ${refname})
if [[ -z $(echo "${UNCHECK_BRANCH[@]:0}" | grep -o ${branch_name}) ]]; then
check_code ${oldrev} ${newrev} ${reframe} ${branch_name}
exit $?
else
exit 0
fi
done
pre-receiveフック用のスクリプトを作成したら、フック用のスクリプトに実行権限を付与する。
$ chmod +x pre-receive