Not to confuse you further, but it’s really up to you. There’s benefits to each method and it mostly comes down to whether or not you want to installed Node and Grunt on your remote servers. I’d lean towards compiling locally since you already have Grunt setup but unfortunately Capistrano isn’t set up by default to do things locally then copy.
I’ve gone with the build locally and copy approach.
This is how I’m achieving it – any improvements most welcome:
set :rel_path_to_theme, "web/app/themes/mytheme"
set :local_path_to_app, "/Applications/MAMP/htdocs/mysite/"
set :local_path_to_theme, "#{fetch(:local_path_to_app) + fetch(:rel_path_to_theme)}"
namespace :deploy do
task :copy_compiled_assets do
system("grunt --base #{fetch(:rel_path_to_theme)} --gruntfile #{fetch(:rel_path_to_theme)}/GruntFile.js build")
on roles(:web) do
%w{/assets/css/main.min.css /assets/js/scripts.min.js /assets/js/vendor/modernizr.min.js}.each do |asset|
upload! "#{fetch(:local_path_to_theme) + asset}", "#{release_path.to_s + '/' + fetch(:rel_path_to_theme) + asset}"
end
end
end
end
I’ve modified this to be a bit cleaner and more Ruby/Cap idiomatic. The one major difference is ideally you should modify your Grunt production task to output the files you want to some separate dir like dist/ then you can just upload that whole file instead of individually listing files. It’s just easier not to duplicate some logic from Grunt in here.
Note: I haven’t actually tested this.
set :theme_path, Pathname.new('web/app/themes/mytheme')
set :local_app_path, Pathname.new('/Applications/MAMP/htdocs/mysite')
set :local_theme_path, fetch(:local_app_path).join(fetch(:theme_path))
namespace :deploy do
task :compile_assets do
run_locally do
within fetch(:local_theme_path) do
execute :grunt, :build
end
end
end
task :copy_assets do
invoke 'deploy:compile_assets'
on roles(:web) do
upload! fetch(:local_theme_path).join('dist'), release_path.join(fetch(:theme_path)), recursive: true
end
end
end
Having a slight issue though – whenever I deploy I keep getting an SSHKit::ExecuteError.
It tells me that my local dist directory is a directory. Well, duh. It’s meant to be a directory.
Anyway, error as follows:
The deploy has failed with an error: #<SSHKit::Runner::ExecuteError: Exception while executing on host 11.22.33.44: Is a directory - /Applications/MAMP/htdocs/myapp/web/app/themes/mytheme/dist
I’ve tried adding the folder to the repo (with .gitkeep) and subsequently removing it to see if that helped. But no dice.
Also, this:
suggests adding recursive: true, but that doesn’t work for me either.
Okay, so the fix I’ve found is to ensure the first pathname is a string.
The issue here – I think – is the local path fetch(:local_theme_path).join('dist') is still a Pathname object, whereas the upload! command expects the path as a string.
I created a Gist inspired by christhesoul’s that doesn’t require setting up a dist directory. It just keeps a list of the generated assets in deploy.rb and uploads them.
It’s slightly less clean than just copying a single directory, but it doesn’t require mucking about updating paths in the theme, so it’s easier to get up and running.
I had to comment the invoke deploy:compile_assets line - can someone explain what it’s supposed to do?
it took a bit of time to understand the ‘assets to remote’ process - I know it’s up to the user to choose his/her method but would not a basic default method help new users? like having the upload method task in the deploy.rb file by default (like there are other optional tasks)