Forked from rafaelp/heroku_migrate_from_bamboo_to_cedar.rake
Created
January 26, 2012 21:58
-
-
Save a-bash/1685367 to your computer and use it in GitHub Desktop.
Rake task to migrate an application from bamboo stack do cedar stack on Heroku
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
# -*- encoding : utf-8 -*- | |
# Rafael Lima (http://rafael.adm.br) | |
# License: http://creativecommons.org/licenses/by/2.5/ | |
# | |
# ATTENTION: This is a initial work, use it at your own risk! | |
# | |
# Usage: | |
# $ APP_NAME=myappname rake heroku:migrate_from_bamboo_to_cedar | |
namespace :heroku do | |
def run(*cmd) | |
system(*cmd) | |
raise "Command #{cmd.inspect} failed!" unless $?.success? | |
end | |
def confirm(message) | |
print "\n#{message}\nAre you sure? [Yn] " | |
raise 'Aborted' unless STDIN.gets.chomp.downcase == 'y' | |
end | |
def step(message) | |
confirm(message) | |
print "-----> #{message}…" | |
yield | |
puts " OK" | |
end | |
task :migrate_from_bamboo_to_cedar => :environment do | |
current_app = ENV['APP_NAME'] | |
raise "You must set environment variable APP_NAME. Try running: APP_NAME=myappname rake heroku:migrate_from_bamboo_to_cedar" if ENV['APP_NAME'].nil? | |
new_app = "#{current_app}-new" | |
old_app = "#{current_app}-old" | |
step "Checking current stack" do | |
ret = `heroku stack --app #{current_app} |grep '*'` | |
stack = ret.strip.gsub("* ", "") | |
raise "Current application should be running on bamboo-mri-1.9.2 to be migrated but it ir running on #{stack}. More info at: http://devcenter.heroku.com/articles/cedar#migrating_from_bamboo_to_cedar" if stack != "bamboo-mri-1.9.2" | |
end | |
step "Checking log configuration" do | |
ret = `heroku config -s --app #{current_app} |grep RACK_ENV` | |
env = ret.strip.split("=")[1] | |
file_name = Rails.root.join('config','environments',"#{env}.rb") | |
raise "Environment file (#{file_name}) not found" unless File.exists?(file_name) | |
ret = `cat #{file_name} |grep config.logger` | |
lines = ret.split("\n") | |
ocurrences = lines.map do |line| | |
line.strip[0] != "#" | |
end | |
raise "Environment file (#{file_name}) should not have config.logger directive. More info at: https://github.com/ddollar/rails_log_stdout/issues/4#issuecomment-2512778" if ocurrences.include?(true) | |
end | |
step "Checking mailer configuration" do | |
ret = `heroku addons --app #{current_app} |grep sendgrid` | |
if !ret.strip.blank? | |
ret = `heroku config -s --app #{current_app} |grep RACK_ENV` | |
env = ret.strip.split("=")[1] | |
file_name = Rails.root.join('config','environments',"#{env}.rb") | |
raise "Environment file (#{file_name}) not found" unless File.exists?(file_name) | |
ret = `cat #{file_name} |grep config.action_mailer.smtp_settings` | |
lines = ret.split("\n") | |
ocurrences = lines.map do |line| | |
line.strip[0] != "#" | |
end | |
raise "You have sendgrid addon and the environment file (#{file_name}) don't have the configuration of action_mailer. More info at: http://devcenter.heroku.com/articles/sendgrid#usage" if ocurrences.empty? or !ocurrences.include?(true) | |
end | |
end | |
step "Checking SSL" do | |
ret = `heroku ssl --app #{current_app} |grep 'SSL certificate registered'` | |
if ret.strip != "" | |
domain = /(.*)\shas a SSL certificate registered/.match(ret.strip)[1] | |
confirm("As you have SSL, you will have to change the CNAME value for the domain #{domain} and your application will be offline for a while until DNS propagate.") | |
pem_file_name = Rails.root.join("config/certs/#{domain}.pem") | |
key_file_name = Rails.root.join("config/certs/#{domain}.key") | |
raise "Current application has SSL certificate, you will need the PEM file at #{pem_file_name} to finish the upgrade." unless File.exists?(pem_file_name) | |
raise "Current application has SSL certificate, you will need the KEY file at #{key_file_name} to finish the upgrade." unless File.exists?(key_file_name) | |
end | |
end | |
step "Looking for Procfile" do | |
raise "This project doesn't have Procfile. Read more at: http://devcenter.heroku.com/articles/rails3#webserver" unless File.exists?(Rails.root.join("Procfile")) | |
ret = `git blame Procfile` | |
raise "Procfile is not commited" unless ret.strip != "fatal: cannot stat path 'Procfile': No such file or directory" | |
end | |
step "Creating #{new_app}" do | |
ret = `heroku apps |grep #{new_app}` | |
if ret.strip != "#{new_app}" | |
run("heroku create #{new_app} --stack cedar") | |
end | |
end | |
step "Installing addons" do | |
ret = `heroku addons --app #{current_app}` | |
current_addons = ret.split("\n") | |
ret = `heroku addons --app #{new_app}` | |
new_addons = ret.split("\n") | |
addons_to_install = current_addons - new_addons | |
print " #{addons_to_install.inspect}" | |
addons_to_install.each do |addon| | |
if ["logging:expanded"].include?(addon) | |
`heroku addons:upgrade #{addon} --app #{new_app}` | |
else | |
`heroku addons:add #{addon} --app #{new_app}` | |
end | |
end | |
end | |
# Only copy variables wich does not exists in new app | |
step "Copying environment variables" do | |
ret = `heroku config -s --app #{current_app}` | |
current_vars = ret.split("\n") | |
current_pairs = {} | |
current_keys = [] | |
current_vars.each do |var| | |
key = var.split("=")[0] | |
value = var.split("=")[1] | |
current_pairs[key] = value | |
current_keys << key | |
end | |
ret = `heroku config -s --app #{new_app}` | |
new_vars = ret.split("\n") | |
new_pairs = {} | |
new_keys = [] | |
new_vars.each do |var| | |
key = var.split("=")[0] | |
value = var.split("=")[1] | |
new_pairs[key] = value | |
new_keys << key | |
end | |
configs_to_add = current_keys - new_keys | |
print " #{configs_to_add.inspect}" | |
configs = [] | |
configs_to_add.each do |config| | |
configs << %{#{config}="#{current_pairs[config]}"} | |
end | |
if !configs.empty? | |
`heroku config:add #{configs.join(' ')} --app #{new_app}` | |
end | |
end | |
step "Pushing application to the new stack" do | |
run "git push [email protected]:#{new_app}.git HEAD:master -f" | |
end | |
step "Putting current application in maintenance mode" do | |
run "heroku maintenance:on --app #{current_app}" | |
end | |
step "Copying database between applications" do | |
run("heroku pgbackups:capture --app #{current_app} --expire") | |
run("heroku pgbackups:restore DATABASE `heroku pgbackups:url --app #{current_app}` --app #{new_app} --confirm #{new_app}") | |
run("heroku run rake db:migrate --app #{new_app}") | |
run("heroku restart --app #{new_app}") | |
end | |
step "Set RACK_ENV and RAILS_ENV config vars" do | |
ret = `heroku config -s --app #{current_app} |grep RACK_ENV` | |
env = ret.strip.split("=")[1] | |
run("heroku config:add RACK_ENV=#{env} RAILS_ENV=#{env} --app #{new_app}") | |
end | |
step "Copying domains between applications" do | |
ret = `heroku ssl --app #{current_app} |grep 'SSL certificate registered'` | |
if ret.strip != "" | |
ssl_domain = /(.*)\shas a SSL certificate registered/.match(ret.strip)[1] | |
else | |
ssl_domain = nil | |
end | |
ret = `heroku domains --app #{current_app}` | |
domains = ret.split("\n") | |
domains.shift | |
run("heroku config:add DOMAINS=#{domains.to_json} --app #{new_app}") # just to backup | |
domains.each do |domain| | |
run("heroku domains:remove #{domain} --app #{current_app}") | |
run("heroku domains:add #{domain} --app #{new_app}") | |
end | |
if ssl_domain | |
pem_file_name = Rails.root.join("config/certs/#{ssl_domain}.pem") | |
key_file_name = Rails.root.join("config/certs/#{ssl_domain}.key") | |
run("heroku ssl:add #{pem_file_name} #{key_file_name} --app #{new_app}") | |
end | |
end | |
step "Rename applications" do | |
run("heroku rename #{old_app} --app #{current_app}") | |
run("heroku rename #{current_app} --app #{new_app}") | |
end | |
step "Setting Dynos" do | |
ret = `heroku dynos --app #{current_app}` | |
dynos = /.* is running (\d*) dyno/.match(ret.strip)[1].to_i | |
if dynos > 1 | |
run("heroku scale web=#{dynos} --app #{new_app}") | |
end | |
end | |
step "Setting Workers" do | |
ret = `heroku workers --app #{current_app}` | |
workers = /.* is running (\d*) worker/.match(ret.strip)[1].to_i | |
if workers > 0 | |
run("heroku scale worker=#{workers} --app #{new_app}") | |
end | |
end | |
puts "Adjust repositories in your .git/config" | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment