マイネット Advent Calender22日目の記事です。
はじめに
現在私が所属している、会社のプロジェクトでは、Ruby on RailsのアプリケーションをCapistranoでdeployしています。
また、開発環境と本番環境問わずcapistranoでエンジニアがデプロイしていました。
しかし、アプリケーション内に企画やデザイナーの人が触るマスタデータやバイナリデータが含まれており、
エンジニアが行う開発環境へのdeploy作業が非常に多い上に、エンジニアがいない時に作業が止まってしまうため、
誰でもデプロイできるようにしようという背景で、
以下のようなデプロイ方式にすることでエンジニア以外もアプリケーションのデプロイを可能にしました。
概要
- chatworkにデプロイに必要なパラメータを記述した下記のようなテンプレを貼り付ける。
deploy----------------------------
リポジトリ: hoge
デプロイ先環境: development
ブランチ: fuga
----------------------------yolped
2. botがテンプレを解析して、デプロイ用シェルスクリプトを走らせる。
- テンプレを受け取ったbotは入力チェックを行うスクリプトを走らせます。
- テンプレが問題なければ、デプロイを行う旨をchatworkに通知し、実際にデプロイを行うシェルスクリプトを走らせる。
- デプロイ用シェルスクリプトはbotのサーバーでマスタやバイナリをリモートリポジトリにpushした後、2回のsshを行い、その先でsuを行い、capistranoを動かします。
- デプロイの成功/失敗のパラメータをbotに返します。
3. botがデプロイ結果をchatworkに通知する。
本記事では、このスクリプトについての詳細と、ハマったことと気をつけた点について紹介しようと思います。
用意したもの
- chatworkのAPI KEY
- GASでもhubotでもいいのでchatworkのログを拾えるbot
デプロイ用シェルスクリプトでハマったところ
デプロイシェルスクリプト部分は、bot用のサーバーからデプロイを行う際、多段sshからのsuコマンドでユーザーを切り替えた先でcapコマンドを叩いています。
上記の操作に関しては、シェルスクリプトを書く際にかなりハマってしまったので、ハマったところをまとめておきます。
- 2段ssh
2段でsshを行う際には、expectコマンドとssh -tを使用します。下記のように書くことで実現可能です。
1回のsshはシェルスクリプトで書いたことあったので、expectを入れ子にすればなんとかなると思ってハマってしまいました。
expect -c "
set timeout 60
spawn ssh -t $HOST1 \"ssh $HOST2 'コマンド'\"
expect \"$HOST1's password:\";
send \"$PASSWORD1\n\"
expect \"'s password:\"
send \"$PASSWORD2\n\"
interact
"
- su - username
こちらも、シェルスクリプト内に単純に記述すれば動くと思っておりましたが、そのままだとスクリプトが止まってしまいました。
下記のように書くことで解決します。
su - username -c "コマンド"
- su - username -c内での変数の挙動
su - username -c "" を行っている際、シェルスクリプト実行側の変数を使いたい場合と、username側の変数を使いたい時がありました。
通常のように変数を使うと実行側の変数として扱われ、su内で実行しているコマンドの終了ステータスなどがとれずに苦労しました。
下記のような記述にすることで、変数を使い分けることができました。
上手くいかない例
$ sudo su -l root -c "aaaaa;echo $?"
-sh: aaaaa: command not found
0
上手くいく例
$ sudo su -l root -c "aaaaa;echo `echo '$?'`"
-sh: aaaaa: command not found
127
本機能を作る上で注意したこと
- テンプレの入力チェックをかなり厳しく行った
間違って本番環境へ上げてしまったり、テンプレが間違ってて意図しない動作にならないように、入力チェックは厳しく行いました。
コロンの右側以外の編集があった場合や、production指定などがあった場合、存在しないブランチや環境に指定があった場合にエラーを返すようにしています。 - 予期せぬ不具合を防止するため、異常系の動作チェックは念入りに行った
botが止まってしまってはエンジニア作業がなくならないので、ここは各コマンドについて異常系を考えました。
終わりに
弊社のカレンダーの記事に定時退社ネタが幾つかあったので、エンジニアがルーチンワークに縛られずに帰るためについ最近行ったアクションについて記事にしてみました。