Itamae + Serverspecでローカル環境を構築する(Homebrew編)

# はじめに
下記の記事に感化され、ローカル環境構築を Bash -> [**Itamae**](http://itamae.kitchen/) に移行することにしました。第一段階として、[Homebrew](http://brew.sh/index_ja.html)周りから手つけ、確認は [**Serverspec**](http://serverspec.org/) で行いました。

参考: [OSXのHomebrewでインストールするのをitamaeでやるようにした](http://sugamasao.hatenablog.com/entry/2015/01/11/163243)

5/27追記: 少し前にgemリリースしたので、ご活用ください
https://rubygems.org/gems/itamae-plugin-recipe-homebrew


# 前提条件
* Mac環境



# 実施
### Gemfileを用意する

```ruby:Gemfile
source "https://rubygems.org"

gem "itamae"
gem "serverspec"
gem "rake"

# 以下はGuardを使用する場合
gem "guard-rspec"
gem "terminal-notifier"
gem "terminal-notifier-guard"
```

### bundle installする

```bash
$ bundle install --path vendor/bundle
```

### ノードを用意する [^1]

[^1]: ノードはjsonでも定義可能です

```yaml:nodes/local.yml
brew:
  enable_update: false
  enable_upgrade: false
  add_repositories:
    - homebrew/dupes
    - homebrew/versions
    - homebrew/binary
    - peco/peco
    - motemen/ghq
  install_packages:
    - brew-cask
    - coreutils
    - findutils
    - zsh
    - bash
    - vim
    - tmux
    - git
    - hub
    - tig
    - ghq
    - imagemagick
    - wget
    - rsync
    - curl
    - tree
    - openssl
    - libyaml
    - readline
    - markdown
    - jq
    - peco
    - ctags
    - z
    - rbenv
    - ruby-build
  install_apps:
    - atom
    - alfred
    - google-chrome
    - iterm2
    - skype
    - slack
    - virtualbox
    - vagrant
    - vagrant-manager
    - google-japanese-ime
    - dash
    - github
    - dropbox
    - xtrafinder
    - appcleaner
    - caffeine
```



### レシピを用意する

```ruby:recipes/brew.rb
BREW_INSTALL_URL = "https://raw.githubusercontent.com/Homebrew/install/master/install"

# Update brew
enable_update = node["brew"]["enable_update"] ? node["brew"]["enable_update"] : false
if enable_update
  execute "Update brew" do
    command "brew update"
  end
else
  Logger.info('Execution skipped Update brew because of not true enable_update')
end

# Upgrade brew
enable_upgrade = node["brew"]["enable_upgrade"] ? node["brew"]["enable_upgrade"] : false
if enable_upgrade
  execute "Upgrade brew" do
    command "brew upgrade"
  end
else
  Logger.info('Execution skipped Upgrade brew because of not true enable_upgrade')
end

# Install brew
execute "Install brew" do
  command "ruby -e \"$(curl -fsSL #{BREW_INSTALL_URL})\""
  not_if "test $(which brew)"
end

# Add Repository
node["brew"]["add_repositories"].each do |repo|
  execute "Add Repository" do
    command "brew tap #{repo}"
    not_if "brew tap | grep -q '#{repo}'"
  end
end

# Install bin packages
node["brew"]["install_packages"].each do |package|
  execute "Install bin packages" do
    command "brew install #{package}"
    not_if "brew list | grep -q #{package}"
  end
end

# Install apps
node["brew"]["install_apps"].each do |app|
  execute "Install apps" do
    command "brew cask install #{app} --appdir=\"/Applications\""
    not_if "brew cask list | grep -q #{app}"
  end
end

# Setup alfred
execute "Setup alfred" do
  command "brew cask alfred link"
end
```

### Itamaeを実行する [^2]

[^2]: `-l debug`オプションは好みで

```bash
$ bundle exec itamae local recipes/brew.rb -y nodes/local.yml -l debug 
```



# 確認
### specを用意する

```ruby:spec/localhost/brew_spec.rb
require "spec_helper"
require "yaml"

nodes_dir_path = File.expand_path(File.dirname(__FILE__) << "/../../nodes")
node = YAML.load_file("#{nodes_dir_path}/local.yml")

describe command "test $(which brew)" do
  its(:exit_status) { should eq 0 }
end

node["brew"]["add_repositories"].each do |repo|
  describe command "brew tap | grep -q '#{repo}'" do
    its(:exit_status) { should eq 0 }
  end
end

node["brew"]["install_packages"].each do |package|
  describe command "brew list | grep -q #{package}" do
    its(:exit_status) { should eq 0 }
  end
end

node["brew"]["install_apps"].each do |app|
  describe command "brew cask list | grep -q #{app}" do
    its(:exit_status) { should eq 0 }
  end
end
```

### Serverspecを実行する
```bash
bundle exec rake spec
```

##### 備考
都度確認しながら進める場合は [**Guard**](https://github.com/guard/guard) を起動しておくと、わざわざコマンドを叩かなくてもServerspecが走るので捗ります。一応Guardfileと実行コマンドを載せておきます。この辺りは、[サーバ/インフラ徹底攻略](http://gihyo.jp/book/2014/978-4-7741-6768-8)を合わせて読んでおくといいかもしれません。

```ruby:Guardfile
guard :rspec, cmd: 'bundle exec rspec' do
  watch(%r{^spec/.+_spec\.rb$})
  watch('spec/spec_helper.rb')  { "spec" }
end
```

```bash:guardの実行
$ bundle exec guard
```



# 最終的なディレクトリ構成
```bash
$ tree .
.
├── Gemfile
├── Gemfile.lock
├── Guardfile
├── Rakefile
├── nodes
│   ├── local.yml
├── recipes
│   └── brew.rb
├── spec
│   ├── localhost
│   │   └── brew_spec.rb
│   └── spec_helper.rb
└── vendor
    └── bundle
```



# リポジトリ
https://github.com/fukuiretu/fukuiretu-sandbox/tree/master/local_setup



# おわりに
* Itamae, Serverspec最高
* [Serverspec本](http://www.oreilly.co.jp/books/9784873117096/)読んでおくと色々良さそう（かくいう自分も買ったけどまだ読了できてないです:bow:）
* 今回は`execute`リソースしか使用していませんが、Itamaeに他にどんなリソースがあるのか知りたい場合は、合わせて以前私がポストした[Itamaeチートシート](http://qiita.com/r82/items/170aa956731f2ffb5715)もご参照ください
* 次はzsh周りの設定をItamaeに移行しようと思います