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