2012年11月3日土曜日

[git] masterブランチにpushできる人を制限したい

背景



今の開発環境を軽く説明。
テストサーバに共有レポジトリがおかれていて、開発メンバはそこから、cloneしてきたローカルレポジトリで開発をおこなう。ブランチの構成は、masterブランチ1本と、機能ブランチが複数本。

開発を始める際、機能ブランチを切ってもらい、そこにガンガンコミットしていく。テスト環境で動作を確認する場合は、その機能ブランチを共有レポジトリにpushすれば、自動でdeployされて、確認できるようになる。

また、進捗状況の確認とかにも使えるかなとも思うので、メンバには定期的に共有レポジトリにpushしてもらっている。もし、masterに何かしらの更新がかかった場合、機能ブランチをrebaseしてもらっている。そして、開発が完了し、動作確認できたら、masterにmergeしていく。


このように、開発メンバはちょくちょく共有レポジトリにpushする。
しかし、gitに慣れていないメンバもいるので、間違って、ぶっ壊れた履歴を、masterにpushしちゃうこともある。

まぁ機能ブランチであれば、もし間違ったコミット達をpushしたとしても、gitなら割と簡単に履歴修正できるし、取り返しのつかない履歴上げられたとしても、最悪、masterからブランチ切り直して、必要なコミットだけ、cherry-pickで持っていく事もできる.

しかし、masterを壊されると結構厄介な事になりそう。
機能ブランチは、適度なタイミング(メンバが気づいた時)、masterの変更を取り込む作業をしてもらっているので、もし壊れたmasterを共有された場合、その影響が各機能ブランチまで波及してしまう可能性がある。

そのため、機能ブランチはいいけど、masterはpushされたくない。ということで、masterへのpushができるユーザを制限したかった。


方法


似たようなことやってるところ。
[Git] Git でサーバに認証したユーザと Author が同じであることを強制するフックスクリプト
やり方としては、pushされた時に走るhookを仕込んで置いて、
masterブランチへのpushの時だけ、
接続してきたユーザが許可されたユーザであればpushを実行、それ以外なら失敗させる。


pushを止めるhookとしては、「pre-receive」と「update」がある模様。
「pre-receive」は、push毎に実行される。
「update」は、pushが更新するリファレンス毎に実行される。
今回やりたいのは、masterブランチへのpushだけ止めて、
その他のブランチへのpushは許可したいので「update」を使ってみる。


ソース


① ユーザの取得

参考にしたところでは、environmentを使って環境変数を設定していたが、
今の僕の仕事上rootを持っていないので、この方法は使えない。
が、他の案件の人が、command使ってやっているのをみて、丸パクりした。

.ssh/authorized_keysには以下。
command="if test -n \"$SSH_ORIGINAL_COMMAND\"; then SSH_CLIENT_USER=karino-t eval $SSH_ORIGINAL_COMMAND; else SSH_CLIENT_USER=karino-t  exec /bin/bash -l ; fi" ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDCMi+sgejbfTsc8FR2fL+yIP2vbVCcwE5th0cI8HB9NG5NEe6VwH8VfbxVq7I/VOST09Ww+sWm6BgZCewNyJfV9GNsfEOVOC93VEeTDLudKzB2I+21ybvVa1A+/PtFdMY4trOeRMc6HwTbt0uwpVhZLJjGJxISoAoH9clF8I4x85qlXZeOsePoyW55uwHpyoojB+UhIxuzG60+mQutmMwgAQ5OF1tSBqAjB7fKVOievjKq/AZ8hGW3HuR5Yj6XE8RaUPWzu91wEqF/FSXrS0i8nUp2+ZZ2Loapu9xVhFxRASacVBLrwV+BnNhcC5lIV0/lClttVxY2eLCXxeVr4EFx karino@goldfish


② update hook

これで、masterにpushする時のみ止められることになる。
多分問題無いはず。


#!/bin/sh

BRANCH=${0}

echo
echo "SSH_CLIENT_USER : ${SSH_CLIENT_USER}"
echo "target branch   : ${1}"

                                           
PERMIT_USER=("karino-k" "karino-n" "karino-k")
STATUS=1                                   
                                           
# master以外はpush OK
if [ ! `echo ${1} | grep 'master'` ]; then
    STATUS=0
fi

# 特定ユーザはpush OK
for USER in ${PERMIT_USER[@]}
do
    if [ ${SSH_CLIENT_USER} = ${USER} ]; then
        STATUS=0
    fi
done

# エラーメッセージ
if [ $STATUS = 1 ]; then
    echo
    echo "You don't allow to push master"
    echo "Please contact to karino-t"
    echo
fi

exit ${STATUS}

0 件のコメント:

コメントを投稿