Walterは, Goで書かれた「ビルドパイプライン」ツールです.
JenkinsなどでCIを行う場合, 複数のジョブを連携して, 一連の処理の流れを作ることがあります. これを「ビルドパイプライン」と呼び, Jenkinsにはビルドパイプラインを作る為のプラグインが幾つか提供されています.
Walterは, Jenkinsに依存しない形で, 「ビルドパイプライン」をよりシンプルに, かつコードで指定出来るようにしたツールです(Jenkinsで「ビルドパイプライン」を設定する場合, 大抵ブラウザでJenkinsをポチポチする必要があります...).
詳しくは,
- walter/README.md
- Walter ファミリーの紹介 at Shibuya.go#1
- シンプルなビルドパイプラインツールwalterをリリースしました | Advanced Technology Lab
などなど参考にしながら, 実際に手を動かしながら試してみるのが良さそうです.
インストール
というわけで早速インストールしましょう. WalterはGo製のツールであり, ワンバイナリで動作します.
バイナリは, Walterのリポジトリで配布されているので, ここからダウンロードするのが手っ取り早いでしょう. Linux系の64bit OSであれば, 「walter_x.x.x_linux_amd64.tar.gz」でOKです.
また, Homebrewでインストールすることも可能です:
$ brew tap higanworks/homebrew-walter-binary $ brew install walter
問題なくインストールできれば, walter
というコマンドが利用可能になります. これで準備OKです.
設定ファイル: pipeline.yml
Walterは, pipeline.yml
という設定ファイルを利用します.
pipeline: - name: command_stage_1 type: command command: echo "hello, world"
pipeline.yml
を設置したディレクトリで, walter
コマンドを実行すると, この設定に従って処理を実行してくれます(-c
オプションで, 任意のYAMLファイルを利用することもできます).
$ walter 11:34:30 INFO Pipeline file path: "./pipeline.yml" 11:34:30 INFO not found "require" block 11:34:30 INFO not found "service" block 11:34:30 INFO local client was created 11:34:30 INFO not found messenger block 11:34:30 INFO not found cleanup block in the input file 11:34:30 INFO running Walter 11:34:30 INFO Starting Walter in local mode 11:34:30 INFO Preparing to run pipeline process... 11:34:30 INFO [command] exec: command_stage_1 11:34:30 INFO [command_stage_1][command] exec output: hello, world 11:34:30 INFO Finished running pipeline process... 11:34:30 INFO Preparing to run cleanup process... 11:34:30 INFO Finished running cleanup process... 11:34:30 INFO succeded to finish Walter
pipeline.yml
で指定したコマンド(単なるecho
ですが...)が, ここで実行されていることがわかります.
11:34:30 INFO [command] exec: command_stage_1 11:34:30 INFO [command_stage_1][command] exec output: hello, world
処理の逐次実行
次のように記述すれば, 処理を逐次(上から順番に)実行することができます.
pipeline: - name: command_stage_1 type: command command: echo "hello, world" - name: command_stage_2 type: command command: echo "こんにちは世界"
実行すると, 次のようになります:
11:37:53 INFO Pipeline file path: "./pipeline.yml" 11:37:53 INFO not found "require" block 11:37:53 INFO not found "service" block 11:37:53 INFO local client was created 11:37:53 INFO not found messenger block 11:37:53 INFO not found cleanup block in the input file 11:37:53 INFO running Walter 11:37:53 INFO Starting Walter in local mode 11:37:53 INFO Preparing to run pipeline process... 11:37:53 INFO [command] exec: command_stage_1 11:37:53 INFO [command_stage_1][command] exec output: hello, world 11:37:53 INFO [command] exec: command_stage_2 11:37:53 INFO [command_stage_2][command] exec output: こんにちは世界 11:37:53 INFO Finished running pipeline process... 11:37:53 INFO Preparing to run cleanup process... 11:37:53 INFO Finished running cleanup process... 11:37:53 INFO succeded to finish Walter
command_stage_1
の後に, command_stage_2
が実行されていることがわかります.
処理の並列実行
次のように記述すると, 幾つかの処理を並列に実行することができます.
pipeline: - name: parallel command parallel: - name: parallel 1 type: command command: sleep 1 - name: parallel 2 type: command command: sleep 2 - name: parallel 3 type: command command: sleep 3
こうすると, parallel
下に設定した3つの処理が, 同時に実行されます.
もし, これを逐次実行した場合は6秒(1 + 2 + 3)のスリープになりますが, 並列に実行した場合は3秒で終了するはずです.
というわけで, time
コマンドを使って処理時間を確認してみます.
$ time walter 11:39:04 INFO Pipeline file path: "./pipeline.yml" 11:39:04 INFO not found "require" block 11:39:04 INFO not found "service" block 11:39:04 INFO local client was created 11:39:04 INFO not found messenger block 11:39:04 INFO not found cleanup block in the input file 11:39:04 INFO running Walter 11:39:04 INFO Starting Walter in local mode 11:39:04 INFO Preparing to run pipeline process... 11:39:04 INFO [command] exec: parallel command 11:39:04 INFO [command] exec: parallel 1 11:39:04 INFO [command] exec: parallel 2 11:39:04 INFO [command] exec: parallel 3 11:39:07 INFO Finished running pipeline process... 11:39:07 INFO Preparing to run cleanup process... 11:39:07 INFO Finished running cleanup process... 11:39:07 INFO succeded to finish Walter walter 0.01s user 0.03s system 1% cpu 3.043 total
3.043 total
ということで, 確かに3秒で処理が終わっていることがわかります.
この並列処理の利用シーンですが, 例えば, carton install
によるCPANモジュールのインストールと, npm install
によるJavaScriptのライブラリのインストールを並列実行して, ビルドにかかる時間を節約する, といった使い方が出来ると思います.
コマンド実行時のオプション
1つの処理(Walterでは「ステージ」と言うそうです)の設定には, 次のようにオプションを指定することができます:
pipeline: - name: command_stage_1 type: command only_if: test -e file.txt directory: dir command: cat file.txt
directory
は, そのステージで設定されたコマンドを実行するディレクトリを, only_if
はそのステージで設定されたコマンドを実行する条件(前提条件)を意味します.
例えばこの場合, only_if
及びcommand
で設定されたコマンドは, directory
で指定したdir
というディレクトリをカレントディレクトリとして実行されます.
そして, only_if
でtest -e file.txt
をしているので, このタスクはdir
ディレクトリ内にfile.txt
が存在する場合のみ実行されるようになります.
まず, 失敗例から.
$ walter 11:46:49 INFO Pipeline file path: "./pipeline.yml" 11:46:49 INFO not found "require" block 11:46:49 INFO not found "service" block 11:46:49 INFO local client was created 11:46:49 INFO not found messenger block 11:46:49 INFO not found cleanup block in the input file 11:46:49 INFO running Walter 11:46:49 INFO Starting Walter in local mode 11:46:49 INFO Preparing to run pipeline process... 11:46:49 INFO [command] only_if: found "only_if" attribute in stage "command_stage_1" 11:46:49 INFO [command] only_if: command_stage_1 11:46:49 WARN [command] only_if err: exit status 1 11:46:49 WARN [command] exec: skipped this stage "command_stage_1", since only_if condition failed 11:46:49 INFO Finished running pipeline process... 11:46:49 INFO Preparing to run cleanup process... 11:46:49 INFO Finished running cleanup process... 11:46:49 INFO succeded to finish Walter
only_if
でerr: exit status 1
になっており, これによってexec: skipped this stage "command_stage_1", since only_if condition failed
となっていることがわかります.
次に, 「Hello, walter!」という内容のファイルをdir
ディレクトリ内部にfile.txt
として設置して実行してみます.
$ walter 11:51:36 INFO Pipeline file path: "./pipeline.yml" 11:51:36 INFO not found "require" block 11:51:36 INFO not found "service" block 11:51:36 INFO local client was created 11:51:36 INFO not found messenger block 11:51:36 INFO not found cleanup block in the input file 11:51:36 INFO running Walter 11:51:36 INFO Starting Walter in local mode 11:51:36 INFO Preparing to run pipeline process... 11:51:36 INFO [command] only_if: found "only_if" attribute in stage "command_stage_1" 11:51:36 INFO [command] only_if: command_stage_1 11:51:36 INFO [command] exec: command_stage_1 11:51:36 INFO [command_stage_1][command] exec output: Hello, walter! 11:51:36 INFO Finished running pipeline process... 11:51:36 INFO Preparing to run cleanup process... 11:51:36 INFO Finished running cleanup process... 11:51:36 INFO succeded to finish Walter
先ほどと異なり, only_if
でエラーになっておらず, 正しくコマンド(cat file.txt
)が実行され, それによってexec output: Hello, walter!
になっていることがわかります.
「ステージ」が失敗した場合
もし, ステージで設定されたコマンドが失敗した場合, その時点で全ての処理が中断します.
例えば, 次のpipeline.yml
では, 最初のステージで存在しないfailed_command
というコマンドを実行しようとしています.
pipeline: - name: command_stage_1 type: command command: failed_command - name: command_stage_2 type: command command: echo "hi!" - name: command_stage_3 type: command command: echo "hi! hi!"
これを実行すると,
$ walter 11:55:09 INFO Pipeline file path: "./pipeline.yml" 11:55:09 INFO not found "require" block 11:55:09 INFO not found "service" block 11:55:09 INFO local client was created 11:55:09 INFO not found messenger block 11:55:09 INFO not found cleanup block in the input file 11:55:09 INFO running Walter 11:55:09 INFO Starting Walter in local mode 11:55:09 INFO Preparing to run pipeline process... 11:55:09 INFO [command] exec: command_stage_1 11:55:09 INFO [command_stage_1][command] exec output: sh: failed_command: command not found 11:55:09 WARN [command] exec err: exit status 127 11:55:09 ERROR [command] exec: failed stage "command_stage_1" 11:55:09 WARN Execution is skipped: command_stage_2 11:55:09 WARN Execution is skipped: command_stage_3 11:55:09 INFO Finished running pipeline process... 11:55:09 INFO Preparing to run cleanup process... 11:55:09 INFO Finished running cleanup process... 11:55:09 INFO more than one failures were detected running Walter
このように, exec output: sh: failed_command: command not found
でステージの実行が失敗していて, これによってExecution is skipped: command_stage_2
そしてExecution is skipped: command_stage_3
になっていることがわかります.
クリーンアップ
パイプラインの一番最後(処理が最後まで終了したか, そうでないかに関わらず)に行う処理は, cleanup
で指定できます.
pipeline: - name: command_stage_1 type: command command: touch file.txt - name: command_stage_2 type: command command: ls - name: command_stage_3 type: command command: echo "hi!" cleanup: - name: cleanup command: rm file.txt
このように記述すると, command_stage_1
で作成したfile.txt
というファイルを, 一番最後に削除してくれます.
$ walter 11:57:30 INFO Pipeline file path: "./pipeline.yml" 11:57:30 INFO not found "require" block 11:57:30 INFO not found "service" block 11:57:30 INFO local client was created 11:57:30 INFO not found messenger block 11:57:30 INFO found cleanup block 11:57:30 INFO running Walter 11:57:30 INFO Starting Walter in local mode 11:57:30 INFO Preparing to run pipeline process... 11:57:30 INFO [command] exec: command_stage_1 11:57:30 INFO [command] exec: command_stage_1 11:57:30 INFO [command_stage_1][command] exec output: file.txt pipeline.yml 11:57:30 INFO [command] exec: command_stage_2 11:57:30 INFO [command_stage_2][command] exec output: hi! 11:57:30 INFO [command] exec: command_stage_3 11:57:30 INFO [command_stage_3][command] exec output: hi! hi! 11:57:30 INFO Finished running pipeline process... 11:57:30 INFO Preparing to run cleanup process... 11:57:30 INFO [command] exec: cleanup 11:57:30 INFO Finished running cleanup process... 11:57:30 INFO succeded to finish Walter $ ls pipeline.yml
command_stage_1
でls
を実行したタイミングでは, file.txt
が存在しますが, walter
コマンドによる処理が終了した後にls
で確認すると, cleanup
でfile.txt
を削除しているので, pipeline.yml
しか残っていないことがわかります.
まとめ
Walter, 他にもHipChatやSlack, Githubとの連携などなど, いろいろ機能があるのでこちらも試してみたいなーと思っています.