#書いてあること
GitLabでサーバサイドhookでpush時にスクリプトを実行して許可/拒絶を制御する方法。
#きっかけ
パートナーさんと1つのリポジトリを使って協業するプロジェクトで、パートナーさんにはdevelopとfeature以外は触ってほしくなかった。注意喚起だけでは弱いのでできたら機械的にできないかと考えた。
#要約
GitLabにはpush等のアクションに応じてイベント検知しスクリプトを走らせることができる。
イベント名(スクリプトファイル名) | 説明 |
---|---|
pre-receive | クライアントからのプッシュを処理するときに最初に実行されるスクリプトが pre-receive です。 |
update | update スクリプトは pre-receive スクリプトと似ていますが、プッシュしてきた人が更新しようとしているブランチごとに実行されるという点が異なります。 複数のブランチへのプッシュがあったときに pre-receive が実行されるのは一度だけですが、update はブランチ単位でそれぞれ一度ずつ実行されます。 |
post-receive | post-receive フックは処理が終了した後で実行されるもので、他のサービスの更新やユーザーへの通知などに使えます。 |
今回はブランチごとに制御を行いたいので、upateスクリプトで対応しました。
#やったこと
GitLabサーバ上に以下のシェルスクリプトを新規作成。配置場所は決まっている模様。
[/srv/gitlab/data/git-data/repositories/(リポジトリグループ名)/(プロジェクト名).git/custom_hooks/update]
#!/bin/sh
#
# Git's update hook for submit control [2011-07-12]
#
# User setting file
readonly AUTH_USERS_FILE='authorized_users'
# Branch name the user is about to push to.
target_branch="$1"
# Fullpath of hooks dir.
self_dir=$(cd $(dirname $0); pwd)
# 1 if the target branch name can be found in the $AUTH_USERS_FILE.
is_restricted=0
# Parenthetic section which represents a branch name in the $AUTH_USERS_FILE.
current_section=''
echo "user-id:"$GL_ID
echo "user-name:"$GL_USERNAME
# Search user names.
while read line
do
# Remove comment.
line=${line%%#*}
# Remove trailing spaces.
line=$(echo $line | sed -e 's/ *$//')
# Empty line.
if [ -z "$line" ]; then
continue
fi
# ここのブロックでpushしようとしているブランチを特定
# Parse section name. e.g. 'refs/heads/master'.
section=$(echo $line | sed -n -e 's/\[\(.\+\)\]/\1/p')
if [ -n "$section" ]; then
if [ "$section" = "$target_branch" ]; then
is_restricted=1
fi
current_section="$section"
continue
fi
# 後術するホワイトリストにユーザー名があるかで許可判断
# Check if the user is listed.
if [ "$current_section" = "$target_branch" ]; then
if [ "$GL_USERNAME" = "$line" ]; then
# The user can push to the branch.
exit 0
fi
fi
done < "$self_dir/$AUTH_USERS_FILE"
if [ $is_restricted = 0 ]; then
# No restriction. The user can push to the branch.
exit 0
fi
echo ""
echo "----------------------------------------------"
echo "[$target_branch] is in submit control."
echo "You do not have access to this branch."
echo "Please wait until the submit control finishes."
echo "----------------------------------------------"
echo ""
# The user cannot push to the branch.
echo "GL-HOOK-ERR: You aren't allow push to $target_branch branche."
exit 1
同じ場所にブランチごとに許可するユーザー名をファイルで記述します。ホワイトリスト形式です。
[/srv/gitlab/data/git-data/repositories/(リポジトリグループ名)/(プロジェクト名).git/custom_hooks/authorized_users]
[refs/heads/master]
userA
[refs/heads/develop]
userA
userB
[refs/heads/release]
userA
[refs/heads/hotfix]
userA
[refs/heads/feature]
userA
userB
userC
上記の例だと、userAが開発~リリースまで全てを行う人、userBが開発~マージまでの人、userCが開発のみと、
役割に応じてpushできるブランチが制御できる。