Skip to content

Instantly share code, notes, and snippets.

@semipermeable
Last active October 4, 2015 12:48
Show Gist options
  • Save semipermeable/2639790 to your computer and use it in GitHub Desktop.
Save semipermeable/2639790 to your computer and use it in GitHub Desktop.
Tddium post-build task to deploy into Heroku
def cmd(c)
system c
end
namespace :tddium do
desc "post_build_hook"
task :post_build_hook do
# This build hook should only run after CI builds.
#
# There are other cases where we'd want to run something after every build,
# or only after manual builds.
return unless ENV["TDDIUM_MODE"] == "ci"
return unless ENV["TDDIUM_BUILD_STATUS"] == "passed"
dir = File.expand_path("~/.heroku/")
heroku_email = ENV["HEROKU_EMAIL"]
heroku_api_key = ENV["HEROKU_API_KEY"]
current_branch = `git symbolic-ref HEAD 2>/dev/null | cut -d"/" -f 3-`.strip
app_name = ENV["HEROKU_APP_NAME"]
push_target = "git@heroku.com:#{app_name}.git"
abort "invalid current branch" unless current_branch
FileUtils.mkdir_p(dir) or abort "Could not create #{dir}"
puts "Writing Heroku Credentials"
File.open(File.join(dir, "credentials"), "w") do |f|
f.write([heroku_email, heroku_api_key].join("\n"))
f.write("\n")
end
File.open(File.expand_path("~/.netrc"), "a+") do |f|
['api', 'code'].each do |host|
f.puts "machine #{host}.heroku.com"
f.puts " login #{heroku_email}"
f.puts " password #{heroku_api_key}"
end
end
puts "Pushing to Heroku: #{push_target}..."
cmd "git push #{push_target} HEAD:master --force" or abort "could not push to #{push_target}"
Bundler.with_clean_env do
puts "Running Heroku Migrations..."
cmd "heroku run rake db:migrate --app #{app_name}" or abort "aborted migrations"
puts "Restarting Heroku..."
cmd "bundle exec heroku restart --app #{app_name}" or abort "aborted heroku restart"
end
end
end
@jacortinas
Copy link

@semipermeable is this still accurate, or is there a better solution at this point?

@wkj
Copy link

wkj commented Jun 21, 2013

You can now use the Heroku toolbelt instead of the gem. We'll update the example to match.

@javierjulio
Copy link

For this to work on Tddium you need to wrap the heroku command calls with a Bundler.with_clean_env so you should have the following:

...
Bundler.with_clean_env do
  puts "Running Heroku Migrations..."
  cmd "heroku run rake db:migrate --app #{app_name}" or abort "aborted migrations"

  puts "Restarting Heroku..."
  cmd "bundle exec heroku restart --app #{app_name}" or abort "aborted heroku restart"
end
...

Also if you have any other rake tasks that use the heroku command you'll need to use Bundler.with_clean_env otherwise you might get Ruby version mismatch errors. I have a db rake task that restores dev db from staging which staging is hosted on heroku.

@semipermeable
Copy link
Author

@javierjulio We've updated the gist to use Bundler.with_clean_env. Thanks for the information!

@kavinderd
Copy link

Tddium often returns BUILD FAILED while running the post_build_hook. However the logs of show a successful deploy and the output of 'running Migrations' but no error afterwards. Is this related to the timeout on hooks?

@mattgibson
Copy link

I just found that I started getting a segfault from the JSON gem on restarting the dynos out of nowhere. Had to remove 'bundle exec' from the restart command to get it to work.

@sdhull
Copy link

sdhull commented May 8, 2014

Why wrap the call to system in this cmd method? Just curious...

@kbaum
Copy link

kbaum commented Jul 23, 2014

I tried this out with heroku_san and i think it's a lot cleaner:

https://gist.github.com/kbaum/068ac0317838b6f123d2

Let me know what you think.

thx!

@wvengen
Copy link

wvengen commented Nov 12, 2014

You don't need to write these files when using HEROKU_API_KEY (that might depend on the heroku cli version) - https://gist.github.com/wvengen/895c45d4f03e1b3ae46f

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment