-
-
Save njvitto/362873 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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#Deploy and rollback on Heroku in staging and production | |
task :deploy_staging => ['deploy:set_staging_app', 'deploy:push', 'deploy:restart', 'deploy:tag'] | |
task :deploy_production => ['deploy:set_production_app', 'deploy:push', 'deploy:restart', 'deploy:tag'] | |
namespace :deploy do | |
PRODUCTION_APP = 'YOUR_PRODUCTION_APP_NAME_ON_HEROKU' | |
STAGING_APP = 'YOUR_STAGING_APP_NAME_ON_HEROKU' | |
task :staging_migrations => [:set_staging_app, :push, :off, :migrate, :restart, :on, :tag] | |
task :staging_rollback => [:set_staging_app, :off, :push_previous, :restart, :on] | |
task :production_migrations => [:set_production_app, :push, :off, :migrate, :restart, :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 ...' | |
puts `git push -f [email protected]:#{APP}.git` | |
end | |
task :restart do | |
puts 'Restarting app servers ...' | |
puts `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}'" | |
puts `git tag -a #{release_name} -m 'Tagged release'` | |
puts `git push --tags [email protected]:#{APP}.git` | |
end | |
task :migrate do | |
puts 'Running database migrations ...' | |
puts `heroku rake db:migrate --app #{APP}` | |
end | |
task :off do | |
puts 'Putting the app into maintenance mode ...' | |
puts `heroku maintenance:on --app #{APP}` | |
end | |
task :on do | |
puts 'Taking the app out of maintenance mode ...' | |
puts `heroku 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 ..." | |
puts `git checkout #{previous_release}` | |
puts `git checkout -b #{previous_release}` | |
puts "Removing tagged version '#{previous_release}' (now transformed in branch) ..." | |
puts `git tag -d #{previous_release}` | |
puts `git push [email protected]:#{APP}.git :refs/tags/#{previous_release}` | |
puts "Pushing '#{previous_release}' to Heroku master ..." | |
puts `git push [email protected]:#{APP}.git +#{previous_release}:master --force` | |
puts "Deleting rollbacked release '#{current_release}' ..." | |
puts `git tag -d #{current_release}` | |
puts `git push [email protected]:#{APP}.git :refs/tags/#{current_release}` | |
puts "Retagging release '#{previous_release}' in case to repeat this process (other rollbacks)..." | |
puts `git tag -a #{previous_release} -m 'Tagged release'` | |
puts `git push --tags [email protected]:#{APP}.git` | |
puts "Turning local repo checked out on master ..." | |
puts `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
Great task! :)
A interesting thing happened the other day while I was using it to deploy code and run migrations.
Heroku Toolbelt detected that there is an update available and started updating itself in the middle of a running task. This resulted in maintenance mode being turned on, code being deployed and all other tasks cancelled because of the "update in progress" status. This left the environment down and its DB "unmigrated".
I recommend adding another task that is run first:
And you probably want to run it first when deploying to production. For example:
Hope this helps!
EDIT: Added the plugin update check.