namespace :deploy do desc "Deploys our application on heroku" task :run => [:off, :push, :migrate, :restart, :on, :tag] desc "Rolls previous deploy revision back" task :rollback => [:off, :push_previous, :restart, :on] task :test do puts "Running tests ..." # and look in $?.exitstatus throw "Tests failed!" if `cucumber`.match /\d+ scenarios \(.*?\d+ failed.*?\)/ end task :push do puts 'Deploying site to Heroku ...' system('git push heroku master') end task :restart do puts 'Restarting app servers ...' system('heroku restart') end task :tag do release_name = "heroku-build-#{Time.now.utc.strftime("%Y%m%d%H%M%S")}" puts "Tagging release as '#{release_name}'" system('git tag -a #{release_name} -m "Tagged release"') system('git push --tags heroku') end task :migrate do puts 'Running database migrations ...' system('heroku run rake db:migrate') end task :off do puts 'Putting the app into maintenance mode ...' system('heroku maintenance:on') end task :on do puts 'Taking the app out of maintenance mode ...' system('heroku maintenance:off') end task :push_previous do releases = `git tag`.split("\n").select{ |t| t[0..7] == 'heroku-build-' }.sort current_release = releases.last previous_release = releases[-2] if releases.length >= 2 if previous_release puts "Rolling back to '#{previous_release}' ..." puts "Checking out '#{previous_release}' in a new branch on local git repo ..." system('git checkout #{previous_release}') system('git checkout -b #{previous_release}') puts "Removing tagged version '#{previous_release}' (now transformed in branch) ..." system('git tag -d #{previous_release}') system('git push heroku :refs/tags/#{previous_release}') puts "Pushing '#{previous_release}' to Heroku master ..." system('git push heroku +#{previous_release}:master --force') puts "Deleting rollbacked release '#{current_release}' ..." system('git tag -d #{current_release}') system('git push heroku :refs/tags/#{current_release}') puts "Retagging release '#{previous_release}' in case to repeat this process (other rollbacks)..." system('git tag -a #{previous_release} -m "Tagged release"') system('git push --tags heroku') puts "Turning local repo checked out on master ..." system('git checkout master') puts "All done!" else puts "No release tags found - can't roll back!" puts releases end end end