書くコードがさまざまな OS で動くことを初めから想定しているような場合には、実際にその環境で動かしてみたい。タイトルのとおり Vagrant で仮想マシンを複数立ち上げて、それぞれの中でコンパイルおよびテストができればよいわけです。というので書いてみたのがこちら:
https://github.com/motemen/go-multi-vagrant
とはいえ別に golang に限った何かがあるというわけではないです。
*file
というファイル名が並んでいてかっこいいのですが、それぞれ以下のような役割を果たしています。
rake
% rake -T rake init # Initialize required tools (required once, a bit slow) rake setup # Setup required libraries rake vagrant:make[machine,target] # Run make on virtual machines rake vagrant:make_fast[machine,target] # Run make without starting up machines rake vagrant:up[machine] # Start virtual machines rake vagrant:watch[machine,target] # Watch local files to invoke make on virtual machines
rake
(rake default
)を実行すると
- 必要なプラグインおよびライブラリのインストールがおこなわれ(
rake init
,rake setup
) - 仮想マシンが起動し(
rake vagrant:up
) - それぞれの仮想マシンの中で make が実行される結果、テストとビルドが走ります(
rake vagrant:make
)。
make
vagrant ssh
して各マシンで make を実行してます。GOPATH
の設定のためにsh -l
してるのがポイントというくらいです。- 仮想マシンを扱う rake タスクでは
MACHINE
環境変数を設定することで特定のマシンのみを対象とすることができます。 - rake からは
TARGET
環境変数で make のタスクを指定できます。 vagrant:make
は毎回仮想マシンの起動をしようとするため少し遅くなっていますが、一度起動してしまったあとはvagrant:make_fast
を使うようにすると起動処理をすっ飛ばすようになり、こちらのほうが早いです。
% rake vagrant:make MACHINE='precise64 centos-6.5' bundle install --quiet bundle exec berks install --path=.vendor/cookbooks Installing golang (1.3.0) from git: 'git://github.com/NOX73/chef-golang.git' with branch: 'master' at ref: 'b062a3226a2ca1a14f0e62187a6ea870281988fc' Using build-essential (1.4.2) vagrant up precise64 Bringing machine 'precise64' up with 'virtualbox' provider... ==> precise64: Checking if box 'hashicorp/precise64' is up to date... ==> precise64: VirtualBox VM is already running. vagrant up centos-6.5 Bringing machine 'centos-6.5' up with 'virtualbox' provider... ==> centos-6.5: Checking if box 'chef/centos-6.5' is up to date... ==> centos-6.5: VirtualBox VM is already running. ---> Running on precise64 vagrant ssh precise64 -- $SHELL -l -c 'cd /vagrant && make 2>&1 | sed "s/^/[precise64] /"' ---> Running on centos-6.5 vagrant ssh centos-6.5 -- $SHELL -l -c 'cd /vagrant && make 2>&1 | sed "s/^/[centos-6.5] /"' [precise64] go get -d ./... [precise64] go test ./... [precise64] ok _/vagrant 0.014s [precise64] go build -o build/main.precise64.vagrant.dominica.local ./... [centos-6.5] go get -d ./... [centos-6.5] go test ./... [centos-6.5] ok _/vagrant 0.002s [centos-6.5] go build -o build/main.centos-6.5.vagrant.dominica.local ./...
ファイル監視
ここまで整えるとファイルの変更を監視してビルドを行いたくなるものですが、Vagrant のファイル共有はゲスト側で変更イベントを発生させないらしい。最近のだと rsync ってのもあるけど明示的に実行しないと同期されないので思わぬところでハマりそうなのと仮想マシンそれぞれに変更監視ツールを入れるのも面倒だ……というわけでホスト側で変更を監視し、ゲストはそれを受けて make するだけ、という風にしてみました。
vagrant:watch
とすると手元でファイルの変更が監視され、変更された時にそれぞれのマシンで make が走ります。仕組みは見たら分かりますが、標準入出力でイベントを伝えるというシンプルな実装です。
% rake vagrant:watch ---> Listening to changes on precise64 ---> Listening to changes on precise32 ---> Listening to changes on centos-6.5 ---> Files changed: main.go [centos-6.5] make [precise64] make [precise32] make [precise64] go get -d ./... [precise64] go test ./... [precise64] ok _/vagrant 0.006s [precise64] go build -o build/main.precise64.vagrant.dominica.local ./... [precise32] go get -d ./... [precise32] go test ./... [precise32] ok _/vagrant 0.002s [precise32] go build -o build/main.precise32.vagrant.dominica.local ./... [centos-6.5] go get -d ./... [centos-6.5] go test ./... [centos-6.5] ok _/vagrant 0.003s [centos-6.5] go build -o build/main.centos-6.5.vagrant.dominica.local ./...