Gitはソースコードのバージョン管理ツールとして用いられることが多いツールです。Gitを用いることでソースコードのデプロイ、ロールバックなど操作がやりやすくなります。GitによるソースコードのデプロイはGitHubの機能を用いるなどしてソースコードの自動反映などを用いる場合もありますが、単にサーバーの中に入って手作業でgit fetch、git checkout 最新バージョンとする場合もあります(深夜アップデートをしたい時にはatコマンドを使う、checkout以外も必要な場合はシェルスクリプトにまとめるなどただのcheckoutで終わらない場合もままあります)。そういったいささか雑な管理をする時、コマンド実行時に自動で確認してくれる機能が欲しくなります。そういったことをするシェルスクリプトを紹介します。
実際のシェルスクリプトが次です。これはシェルスクリプトと同ディレクトリの.envにAPP_ENV=productionとあり、金曜日にこのシェルスクリプト経由でGitを実行しようとしたら確認メッセージを出すシェルスクリプトです。
#!/bin/sh
# コマンド名を取得
COMMAND=$1
# .envファイルからAPP_ENVの値を読み込む
if [ -f .env ]; then
APP_ENV=$(grep -E "^APP_ENV=" .env | cut -d '=' -f2)
fi
# 現在の曜日を取得(0: 日曜日, ..., 6: 土曜日)
DAY_OF_WEEK=$(date +%u)
# 現在の曜日の日本語を得る
case "$DAY_OF_WEEK" in
"1") DAY_OF_WEEK_JP="月" ;;
"2") DAY_OF_WEEK_JP="火" ;;
"3") DAY_OF_WEEK_JP="水" ;;
"4") DAY_OF_WEEK_JP="木" ;;
"5") DAY_OF_WEEK_JP="金" ;;
"6") DAY_OF_WEEK_JP="土" ;;
"7") DAY_OF_WEEK_JP="日" ;;
esac
# 本番環境であり、曜日が金の場合は警告を表示
if [ "$APP_ENV" = "production" ] && [ "$DAY_OF_WEEK" -eq 5 ]; then
echo "警告: 本番環境で${DAY_OF_WEEK_JP}曜日に ${COMMAND} を実行しようとしています。"
printf "本当に実行しますか? [y/N]: "
read -r CONFIRM
if [ "$CONFIRM" != "y" ]; then
echo "操作がキャンセルされました。"
exit 1
fi
fi
# "${@}"は、スクリプトに渡されたすべての引数のリストを表します。
# git "${@}"とすることで、このスクリプトに渡された引数をそのままgitコマンドに渡すことができます。
git "${@}"
使用例は次です。
$ bash ./git-safe.sh checkout test 警告: 本番環境で月曜日に checkout を実行しようとしています。 本当に実行しますか? [y/N]: N 操作がキャンセルされました。 $ bash ./git-safe.sh checkout test 警告: 本番環境で月曜日に checkout を実行しようとしています。 本当に実行しますか? [y/N]: y error: pathspec 'test' did not match any file(s) known to git
こういったGitに連動するスクリプトはGitフックを使うのがよくある方法ですが残念ながら”checkout前”などの一部タイミングにはフックが用意されていません。そういった場合にも確認処理を入れたい時にこの記事に書いたようなスクリプトが役に立ちます。