Herokuのデプロイ作業をRakeで管理する

最近、システム自動管理ツールであるところのPuppetや、デプロイ自動化ツールのCapistranoやMinaやCinnamonを調べていて、そういえばHerokuにデプロイする時に行なっている行動もファイルに記述してから実行した方が良いのでは、と思ったので簡単な奴を書き記しておく。

初めての時はrake deploy:setupを1度だけ試行して、以降はデプロイの度にrake deployを繰り返す。1度しか実行しないのであればdeploy:setupは必要ないのではと言われそうだが、では1箇所からしか参照されないメソッドは抽象化する必要はないのかと言えばそうではないし、後からアアこう設定されているのねということを把握するために必要だったり、生きていれば何もしていないのに壊れたということもあるだろうし、後は他のプロジェクトで使うときに案外便利だったりする。

$ rake -T deploy
rake deploy               # Deploy application to production server
rake deploy:migrate       # Migrate the database
rake deploy:precompile    # Compile assets and git commit public/assets
rake deploy:push          # Push code to production server
rake deploy:setup         # Setup environments
rake deploy:setup:addons  # Setup addons
rake deploy:setup:env     # Setup ENV from .env
rake deploy:tag           # Mark a git tag to remember release version
# lib/tasks/deploy.rake
define_method(:`) {|command| puts "$ #{command}" } if ENV["DRYRUN"]

desc "Deploy application to production server"
task :deploy => %w[
  deploy:precompile
  deploy:push
  deploy:migrate
  deploy:tag
]

namespace :deploy do
  desc "Compile assets and git commit public/assets"
  task :precompile do
    puts
    puts "Compile assets to public/assets/"
    puts `RAILS_ENV=production rake assets:precompile`
    puts `git reset`
    puts `git add public/assets`
    puts `git commit -m "Update public/assets/"`
  end

  desc "Push code to production server"
  task :push do
    puts
    puts "Deploy application to production server"
    puts `git push heroku master`
  end

  desc "Migrate the database"
  task :migrate do
    puts
    puts "Migrate the database"
    puts `heroku rake db:migrate`
  end

  desc "Mark a git tag to remember release version"
  task :tag do
    name = "release-#{Time.now.utc.strftime("%Y%m%d%H%M%S")}"
    puts
    puts "Mark a git tag to remember release version"
    puts "Tagging release as [#{name}]"
    puts `git tag -a #{name} -m "Tagged release"`
    puts `git push --tags heroku`
  end

  desc "Setup environments"
  task :setup => %w[
    deploy:setup:addons
    deploy:setup:env
  ]

  namespace :setup do
    desc "Setup addons"
    task :addons do
      puts
      puts "Setup addons"
      puts `heroku addons:add memcache`
    end

    desc "Setup ENV from .env"
    task :env do
      vals = File.read(".env").gsub("\n", " ")
      puts
      puts "Setup ENV from .env"
      puts `heroku config:add #{vals}`
    end
  end
end

因みにrake deploy DRYRUN=1すると実行せずに内容だけ出力する。

Compile assets to public/assets/
$ RAILS_ENV=production rake assets:precompile

$ git reset

$ git add public/assets

$ git commit -m "Update public/assets/"


Deploy application to production server
$ git push heroku master


Migrate the database
$ heroku rake db:migrate


Mark a git tag to remember release version
Tagging release as [release-20130120103054]
$ git tag -a release-20130120103054 -m "Tagged release"

$ git push --tags heroku

descに書かれた内容を必ずtaksの中で標準出力するようにしているんだけど、task内部で自身に対して設定されたdescの中身を参照出来ればもっとかっこ良くなりそうなので、参照方法をご存じの方はご一報ください。