Created
September 28, 2012 22:18
-
-
Save ndbroadbent/3802355 to your computer and use it in GitHub Desktop.
Rake task for precompiling assets locally before deploying to 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
require 'fileutils' | |
# Warning: The following deploy task will completely overwrite whatever is currently deployed to Heroku. | |
# The deploy branch is rebased onto master, so the push needs to be forced. | |
desc "Deploy app to Heroku after precompiling assets" | |
task :deploy do | |
deploy_branch = 'heroku' | |
remote = 'heroku' | |
deploy_repo_dir = "tmp/heroku_deploy" | |
begin | |
# Check branch and working directory. Fail if not on clean master branch. | |
branch = `branch_name=$(git symbolic-ref HEAD 2>/dev/null); branch_name=${branch_name##refs/heads/}; echo ${branch_name:-HEAD}`.strip | |
if branch != 'master' | |
raise "You have checked out the #{branch} branch, please only deploy from the master branch!" | |
end | |
if `git status --porcelain`.present? | |
raise "You have unstaged or uncommitted changes! Please only deploy from a clean working directory!" | |
end | |
unless File.exists? deploy_repo_dir | |
# Copy repo to tmp dir so we can continue working while it deploys | |
@new_repo = true | |
puts "Copying repo to #{deploy_repo_dir}..." | |
# Can't copy into self, so copy to /tmp first | |
FileUtils.cp_r Rails.root.to_s, "/tmp/heroku_deploy" | |
FileUtils.mv "/tmp/heroku_deploy", Rails.root.join('tmp') | |
end | |
# Change working directory to copied repo | |
Dir.chdir(deploy_repo_dir) | |
# Create new deploy branch if starting with a fresh repo | |
if @new_repo | |
# Set remote to parent git dir, so we can fetch updates on future deploys | |
system "git remote set-url origin ../.." | |
system "git checkout -b #{deploy_branch}" | |
# Allow git to see public/assets | |
puts "Removing public/assets from .gitignore..." | |
system 'sed -i '' "/^[\/?]public\/assets/d" .gitignore' | |
system 'git add .gitignore; git commit -m "Allow git to commit public/assets"' | |
else | |
# Otherwise, we're already on the deploy branch, so fetch any new changes from original repo | |
system "git fetch origin" | |
# Rebase onto origin/master. | |
# This step should never fail, because we are rebasing commits for files | |
# that should be ignored by the master repo. | |
unless system "git rebase origin/master" | |
raise "Rebase Failed! Please delete tmp/heroku_deploy and start again." | |
end | |
end | |
# Precompile assets | |
Rake::Task['assets:precompile'].invoke | |
# Add any extra tasks you want to run here, such as compiling static pages, etc. | |
# Add all changes and new files | |
system 'git add -A' | |
commit_message = "Added precompiled assets" | |
if @new_repo | |
# Create new commit for new repo | |
system "git commit -m '#{commit_message}'", :out => "/dev/null" | |
else | |
# If existing repo, amend previous assets commit | |
system "git commit --amend -m '#{commit_message}'", :out => "/dev/null" | |
end | |
puts "Commit: #{commit_message}" | |
# Force push deploy branch to Heroku | |
puts "Pushing #{deploy_branch} branch to master on #{remote}..." | |
IO.popen("git push #{remote} #{deploy_branch}:master -f") do |io| | |
while (line = io.gets) do | |
puts line | |
end | |
end | |
end | |
end |
bash and sh will both use their built-in echo. bash's echo supports the -n flag, but sh does not
➔ sh
sh-3.2$ type cho
sh: type: cho: not found
sh-3.2$ type echo
echo is a shell builtin
sh-3.2$ /bin/echo foo
foo
sh-3.2$ echo foo
foo
sh-3.2$ /bin/echo -n foo
foosh-3.echo -n foo
-n foo
(ignore type cho
)
@ndbroadbent why not make this rake task a part of the turbo-sprockets-rails3 gem?
great work man! I've a bad case of premature heroku deploying without the assets:precompile - this works great. Love the gem also, well done.
Thanks for this! One suggestion, change the FileUtils.cp_r on line 27 to using the system command:
system "cp -r #{Rails.root} /tmp/heroku_deploy"
I had a socket file in my tmp/ and FileUtils.cp_r() failed with the following error. Only cp -r
told me which file.
$ rake deploy
Copying repo to tmp/heroku_deploy...
rake aborted!
cannot handle socket
/Users/turadg/.rbenv/versions/1.9.3-p327-perf/lib/ruby/1.9.1/fileutils.rb:1357:in `copy'
/Users/turadg/.rbenv/versions/1.9.3-p327-perf/lib/ruby/1.9.1/fileutils.rb:465:in `block in copy_entry'
/Users/turadg/.rbenv/versions/1.9.3-p327-perf/lib/ruby/1.9.1/fileutils.rb:1433:in `preorder_traverse'
/Users/turadg/.rbenv/versions/1.9.3-p327-perf/lib/ruby/1.9.1/fileutils.rb:462:in `copy_entry'
/Users/turadg/.rbenv/versions/1.9.3-p327-perf/lib/ruby/1.9.1/fileutils.rb:437:in `block in cp_r'
/Users/turadg/.rbenv/versions/1.9.3-p327-perf/lib/ruby/1.9.1/fileutils.rb:1515:in `block in fu_each_src_dest'
/Users/turadg/.rbenv/versions/1.9.3-p327-perf/lib/ruby/1.9.1/fileutils.rb:1531:in `fu_each_src_dest0'
/Users/turadg/.rbenv/versions/1.9.3-p327-perf/lib/ruby/1.9.1/fileutils.rb:1513:in `fu_each_src_dest'
/Users/turadg/.rbenv/versions/1.9.3-p327-perf/lib/ruby/1.9.1/fileutils.rb:436:in `cp_r'
👍 @turadg I also had a socket this barfed on.
The sed command didn't work for me, probably because I'm on zsh. Removing the brackets helped: sed -i "" "/^public\/assets/d" .gitignore
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I used it with a small change. Rather than origin, I used
#{remote}
in shell commands because I don't use a separate origin repo, just the Heroku repo.