Skip to content

Instantly share code, notes, and snippets.

@fgrehm
Forked from njvitto/deploy.rake
Last active July 27, 2018 23:31
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fgrehm/4253885 to your computer and use it in GitHub Desktop.
Save fgrehm/4253885 to your computer and use it in GitHub Desktop.
Rakefile to deploy and rollback to Heroku in two different environments (staging and production) for the same app
# Deploy and rollback on Heroku in staging and production
namespace :deploy do
PRODUCTION_APP = 'YOUR_PRODUCTION_APP'
STAGING_APP = 'YOUR_STAGING_APP'
REMOTE = ENV["REMOTE_HOST"] || "git@heroku.com"
def heroku_cmd(cmd)
Bundler.with_clean_env do
sh "heroku #{cmd}"
end
end
desc 'Deploy app to staging'
task :staging => [:set_staging_app, :off, :push, :migrate, :on]#, :tag]
task :staging_rollback => [:set_staging_app, :off, :push_previous, :restart, :on]
desc 'Deploy app to production'
task :production => [:set_production_app, :off, :push, :migrate, :on, :tag]
task :production_rollback => [:set_production_app, :off, :push_previous, :restart, :on]
task :set_staging_app do
APP = STAGING_APP
end
task :set_production_app do
APP = PRODUCTION_APP
end
task :push do
puts 'Deploying site to Heroku ...'
sh "git push #{REMOTE}:#{APP}.git master"
end
task :restart do
puts 'Restarting app servers ...'
heroku_cmd "heroku restart --app #{APP}"
end
task :tag do
release_name = "#{APP}_release-#{Time.now.utc.strftime("%Y%m%d%H%M%S")}"
puts "Tagging release as '#{release_name}'"
sh "git tag -a #{release_name} -m 'Tagged release'"
sh "git push --tags #{REMOTE}:#{APP}.git"
end
task :migrate do
puts 'Running database migrations ...'
heroku_cmd "run rake db:migrate --app #{APP}"
end
task :off do
puts 'Putting the app into maintenance mode ...'
heroku_cmd "maintenance:on --app #{APP}"
end
task :on do
puts 'Taking the app out of maintenance mode ...'
heroku_cmd "maintenance:off --app #{APP}"
end
task :push_previous do
prefix = "#{APP}_release-"
releases = `git tag`.split("\n").select { |t| t[0..prefix.length-1] == prefix }.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 ..."
sh "git checkout #{previous_release}"
sh "git checkout -b #{previous_release}"
puts "Removing tagged version '#{previous_release}' (now transformed in branch) ..."
sh "git tag -d #{previous_release}"
sh "git push #{REMOTE}:#{APP}.git :refs/tags/#{previous_release}"
puts "Pushing '#{previous_release}' to Heroku master ..."
sh "git push #{REMOTE}:#{APP}.git +#{previous_release}:master --force"
puts "Deleting rollbacked release '#{current_release}' ..."
sh "git tag -d #{current_release}"
sh "git push #{REMOTE}:#{APP}.git :refs/tags/#{current_release}"
puts "Retagging release '#{previous_release}' in case to repeat this process (other rollbacks)..."
sh "git tag -a #{previous_release} -m 'Tagged release'"
sh "git push --tags #{REMOTE}:#{APP}.git"
puts "Turning local repo checked out on master ..."
sh "git checkout master"
puts 'All done!'
else
puts "No release tags found - can't roll back!"
puts releases
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment