images folder concern when deploying with Capistrano and git

Hi guys,

So I finally got around to setting up a staging server (ubuntu + apache + passenger) and after some headaches got Capistrano (using git as the scm) to deploy the app to my staging server using a basic deploy.rb file. Everything seems to be working well, any changes I commit and deploy take effect.

HOWEVER, I am storing user pictures using the paperclip plugin to the staging server filesystem (rails_root/public/images/users/). After creating some users and uploading their pictures (on the staging server), I decided to deploy some changes I made to the app only to find out that my user pictures we're overwritten with my local (development) user image folder.

I rolled back the deployment and all the pictures were displayed like they were previously (on the staging server)

So I added the following line to the .gitignore file to my local (development) machine:

[code] public/images/users/* [/code]

I committed the change and deployed but again, the local development machine's user image folder replaces the staging server user image folder contents.

Below is my deploy.rb file contents (edited):

[code]

set :application, "staging.domain.com" set :repository, "."

set :rails_env, "staging" set :user, "user" set :deploy_to, "/home/#{user}/public/#{application}" set :use_sudo, true

set :scm, :git set :deploy_via, :copy set :copy_remote_dir, "/home/#{user}"

role :app, application role :web, application role :db, application, :primary => true

namespace :deploy do   desc "Restarting mod_rails with restart.txt"   task :restart, :roles => :app, :except => { :no_release => true } do     run "touch #{current_path}/tmp/restart.txt"   end   [:start, :stop].each do |t|     desc "#{t} task is a no-op with mod_rails"     task t, :roles => :app do ; end   end end

[/code]

I'm pretty much stumped on this. Also, I realize doing a full copy every time to the server isn't the best thing to do, but it's the only way I can (currently) get it to work. I'm still pretty new at this rails/scm/terminal world. :wink:

Let me know if you need any more info or code from my end that may help.

Thanks for any advice or suggestions!

-Tony

I think, if I'm understanding your situation correctly, you want to symlink your user image directories into somewhere under your "/home/ #{user}/public/#{application}/shared" directory.

The "shared" directory created by capistrano on your staging server does not change from release to release. Create that directory on your local dev box and make sure that path is the same as on the staging serve. Then on both your dev and staging boxes create subdirectories under that perhaps "shared/images/users". Remove the existing "/public/images/users" then symlink to the shared directory (from your public/images directory just do: "ln -s /home/#{user}/ public/#{application}/shared/images/users users" in case your not familiar).

I haven't used git but I would assume that it can version symlinks.

Hope that helps! Tim

That is how Capistrano is supposed to work. You checkout new code from your repo and the current link is replaced with the latest checkout in releases/datestamp.

Just like Tim said when you have content that needs to be shared between releases you need to put that somewhere else LIKE the shared directory. You should do this with a task and a after filter in your deploy.rb file:

after "deploy:update_code", "deploy:symlink"

  task :symlink, :roles => :app do     run <<-CMD       rm -rf #{release_path}/public/images/users &&       ln -nfs #{shared_path}/users #{release_path}/public/images/users &&     CMD   end

Hi Tim & Freddy,

Thanks for the prompt and insightful replies. I'm glad I got it clear that this IS how Capistrano is supposed to work and that I shouldn't try to fight it much.

I wouldn't have even imagined I should have to symlink to get this to work. I'll give it a try and come back if I have any questions.

Thanks for the help!!!

-Tony

I'd watch out for the "rm -rf #{release_path}/public/images/users" line. I think that would remove all your images.

Tim McIntyre wrote:

I'd watch out for the "rm -rf #{release_path}/public/images/users" line. I think that would remove all your images.

Hi Tim,

Thanks for the tip. I've been busy so I haven't tried to do this just yet but I'm sure it would remove the images. The idea is to move the directory/contents to the shared folder prior to deploying with the "deploy:symlink" task.

Thanks again for the tip, I'm sure a lot of people will be grateful for that instead of finding their images gone (though nothing a simple, rollback couldn't fix) :slight_smile:

-Tony

Hi Tony... the rm line is only there for the release_path directory which either will have the symlink OR an empty directory that was checked-out from git. If the developers wants a few "test" images in git for testing you can do that but need to remove that when it is deployed to prod before you create the symlink...

#{release_path} is the /releases/datestamp/ directory...

But "#{release_path}/public/images/users" will still be symlinked to "#{shared_path}/users #{release_path}/public/images/users" and the "r" option will remove all files in that directory so I would just remove the "r" option and you should be OK. No???

Tim McIntyre wrote:

But "#{release_path}/public/images/users" will still be symlinked to "#{shared_path}/users #{release_path}/public/images/users" and the "r" option will remove all files in that directory so I would just remove the "r" option and you should be OK. No???

Maybe this makes some more sense:

In the deploy:symlink task (please notice that I just separated the run commands):

[code] # This deletes the users folder and contents that has been uploaded to the server when deployed (this will happen every deploy). run "rm -rf #{release_path}/public/images/users" #This reestablishes the users folder but as a symlink to the users folder in the shared directory run "ln -nfs #{shared_path}/images #{release_path}/public/images" [/code]

So every time you deploy, you delete the users folder (that's what the rm -rf command does) that was uploaded to the latest release and then you reestablish the symlink (this is what the ln -nfs command does). Hope that makes sense.

-Tony

Hi Tony,

Look into Ryan Bates Railscasts... there is one talking about Capistrano (and his tricks when dealing with images and other "site specific" data).

Jean-Marc http://m2i3.com/blog/jean-marc

Jean-Marc (M2i3.com) wrote:

Hi Tony,

Look into Ryan Bates Railscasts... there is one talking about Capistrano (and his tricks when dealing with images and other "site specific" data).

#133 Capistrano Tasks - RailsCasts

Jean-Marc http://m2i3.com/blog/jean-marc

Hi Jean-Marc,

Thanks for the link. Coincidentally, I also linked to the same screencast. I'm up and running just fine now but I'm sure others could use it.

-Tony