プログラムの目的によっては外部に公開する必要があり、バージョンアップの際には都度、外部公開しているサーバーの中でプログラムを更新する必要があります。これを手作業でやるといずれミスを起こしやすいです。なるべく自動化したいものです。自動化の方法の一つとしてスクリプトを用いる方法があります。これはGitHubのようなリポジトリに起きたことを元に何かする仕組みが用意されていなくとも使えるのが便利です。またスクリプトを用意することによってcronの様な定期実行に限らず、atで深夜帯に一度だけ更新させる、手動でもコピペ一回で作業を完了させるといったことができ、これまた便利です。このようなスクリプトのパーツであるGitリポジトリのタグの比較スクリプトを紹介します(タグにセマンティックバージョンをつけて製品としてのバージョンを管理している前提の話です)。
コードが次です。
#!/bin/bash # スクリプトの絶対パスを取得し、ソースコードのあるディレクトリに移動 # `dirname "${BASH_SOURCE[0]}"` は、実行中のスクリプトのフルパスからディレクトリ部分だけを取り出します。 # `cd "$( dirname "${BASH_SOURCE[0]}" )"` は、取得したディレクトリに移動します。 cd "$( dirname "${BASH_SOURCE[0]}" )" || exit # リモートリポジトリの最新状況を取得 # `git fetch` はリモートリポジトリの変更をローカルリポジトリに取得しますが、 # 現在の作業ディレクトリの内容は更新しません。 git fetch # リモートのタグを取得 # `git fetch --tags` はリモートリポジトリの全てのタグを取得します。 # これにより、ローカルリポジトリがリモートのタグと同期されます。 git fetch --tags # 最新のタグを取得 # `git rev-list --tags --max-count=1` はリポジトリ内の最新のタグ付きコミットを見つけます。 # `git describe --tags` はそのコミットに関連するタグの情報を提供します。 latest_tag=$(git describe --tags "$(git rev-list --tags --max-count=1)") # 現在のコミットのタグを取得 # `git describe --tags --exact-match` は、現在のコミットに付与されたタグを取得します。 # タグがない場合は何も出力されず、エラーが発生するため、`2>/dev/null` でエラーメッセージを隠します。 current_commit_tag=$(git describe --tags --exact-match 2>/dev/null) # バージョンを比較して、現在のコミットのタグが最新のタグと異なる場合にのみ処理を実行 # このif文は、現在のコミットが最新のリリースと異なる場合に true になります。 if [ "$current_commit_tag" != "$latest_tag" ]; then # 最新のバージョンにチェックアウト # 最新のタグが示すコミットにワーキングディレクトリの状態を更新します。 git checkout "$latest_tag" # ここに実行したいコマンドを記述。 # 複雑なタスクは他の言語で書かれたスクリプトに処理を渡した方がより楽です。 fi
やってることはコメントの通りです。目的のディレクトリに入り、リモートリポジトリの情報を取得し、最新のタグと現在のタグを比較、タグが異なるならば更新処理実行、といった具合です。注意点としてリモートリポジトリへのアクセスに認証が必要な場合、最初のgit fetch
,git fetch --tags
のためにSSH認証を用意する必要がある点です。SSH認証をする必要がある場合はリモートリポジトリを管理する何かにあるであろう公開鍵の登録と次のように秘密鍵を使用できるようにする必要があります。
eval "$(ssh-agent -s)" ssh-add ~/.ssh/xxx.pem
こうすると cron で定期実行させたり、echo "/project_root/deploy.sh" | at 04:00 tomorrow
のようにして明日の午前4時にデプロイさせたりなどするのが楽になります。