handling folders not under version control

11 views
Skip to first unread message

François Montel

unread,
Mar 19, 2009, 9:53:02 AM3/19/09
to Capistrano
I'm setting up capistrano with an existing project that has folders
under /public, where files uploaded from users are stored (ie, /public/
photos) that is not under version control. It's not part of the code
and it's continually being updated, so I don't want it in my git repo
(it's marked with git ignore so it isn't included).

The way capistrano seems to work is by checking out a new copy of the
git repo every time deploy:update is run. So even if I copy the user
data into the folder structure created by capistrano the first time I
deploy, the next time I update, a new version will be checked out of
the repo and that user data won't be there.

What's the preferred way to handle this? I could think of a couple of
options:

1. Store the files (ie, photos) in a folder outside of my app
structure, and symlink it to public/photos. That symlink would be in
my git repo so every fresh checkout would still point to the same user
file folder.

2. Maybe after my initial deploy, I shouldn't be using deploy:update
more, but my own recipe that just performs git pull and restarts
passenger. After all, I don't really want capistrano to perform a
whole new checkout every time I update the code (that's time
consuming). I just want it to update it with git pull. (Capistrano has
nice rollback features, but I can roll back with git if I need to.)

Perhaps there are other or better ways to handle this.

Thanks for the help!

PS. Capistrano 2.3 has a scm: none option, but that seems to be for
when the whole app is not under version control; not in the case of
subfolders as mentioned above.

Jean-Philippe Moal

unread,
Mar 19, 2009, 10:23:16 AM3/19/09
to capis...@googlegroups.com
Hello,

I didn't know that git could store symlinks ?
Depending on the deployment recipe I guess there could be problems with relative
symlinks due to the fact that the 'current' deployed directory in default
capistrano structure is a symlink to a folder located in the releases dir.

The most common (at least I think so) is to create a task (with a callback after
the code deployment; I personally use «after "deploy:symlink"») that will add
the required symlinks in the public dir that links to real folders located in
the 'shared' dir, which is already used for pids and logs.

François Montel a écrit :

Ian Sheridan

unread,
Mar 19, 2009, 10:52:42 AM3/19/09
to capis...@googlegroups.com
Jean-Philippe is correct. You do NOT place static folders in your
release directories. You need to place the UPLOADS folder (or any
other folder like it that has static non-versioned files in it) in the
"shared" directory. You then create a task that makes a new symlink to
the UPLOADS directory.

This flexibility is the heart and soul of Capistrano. You can get it
to do anything that you would need at any stage in your deployment
process. here is a sample task that creates a symlink:

desc "create symlink"
task :db, :roles => [:app] do
send(run_method, "ln -nfs #{shared_path}/UPLOADS
#{current_path}/public/UPLOADS")
end

Hope that puts you on the path to creating your own tasks.

- Ian
--
----------------------
Ian Sheridan
http://iansheridan.dyndns.org
----------------------

François Montel

unread,
Mar 19, 2009, 12:04:02 PM3/19/09
to Capistrano
Thanks, Ian and Jean-Philippe, very helpful input that sets me on
track.

Is there any advantage to using deploy:update (other than the rollback
option) as compared to just running a recipe that performs a git pull
(and whatever else I want to do when updating my code)?

For example, running deploy:update when there's a major version
release, but then a different custom recipe to only perform git pull
(etc.) when making minor changes/bug fixes.

Thanks. I'm just trying to understand how to make the best use of
capistrano.

François Montel

unread,
Mar 19, 2009, 12:10:19 PM3/19/09
to Capistrano


On Mar 19, 8:23 am, Jean-Philippe Moal <skateinm...@skateinmars.net>
wrote:
> I didn't know that git could store symlinks ?

Yes, it seems to store the symlink rather than follow the symlink and
store the files.

Jean-Philippe Moal

unread,
Mar 19, 2009, 12:23:34 PM3/19/09
to capis...@googlegroups.com
François Montel a écrit :

> Thanks, Ian and Jean-Philippe, very helpful input that sets me on
> track.
>
> Is there any advantage to using deploy:update (other than the rollback
> option) as compared to just running a recipe that performs a git pull
> (and whatever else I want to do when updating my code)?
>
> For example, running deploy:update when there's a major version
> release, but then a different custom recipe to only perform git pull
> (etc.) when making minor changes/bug fixes.
>
> Thanks. I'm just trying to understand how to make the best use of
> capistrano.

My main reason for always using the standard deploy recipe (with an entire
clone/checkout/export/whatever) is that I want to be able to rollback any
deployment, but your way is totally doable.
If you write this kind of task you certainly will have to set the needed
callbacks associated with the update_code task (see
http://wiki.capify.org/index.php/Default_Execution_Path).
As I use svn I also don't want to clutter my deployed directories with multiple
useless .svn folders.

If speed is your concern you could use remote_cache or fast_remote_cache which
keeps a directory with a git clone which is updated when needed (not sure about
the exact strategy).
If storage space is your concern against the standard deploy task know that you
can use deploy:cleanup. For instance we use it within a callback after:deploy in
staging envs to avoid useless outdated deployed versions.

>
> On Mar 19, 8:52 am, Ian Sheridan <ian.sheri...@gmail.com> wrote:
>> Jean-Philippe is correct. You do NOT place static folders in your
>> release directories. You need to place the UPLOADS folder (or any
>> other folder like it that has static non-versioned files in it) in the
>> "shared" directory. You then create a task that makes a new symlink to
>> the UPLOADS directory.
>>
>> This flexibility is the heart and soul of Capistrano. You can get it
>> to do anything that you would need at any stage in your deployment
>> process. here is a sample task that creates a symlink:
>>
>> desc "create symlink"
>> task :db, :roles => [:app] do
>> send(run_method, "ln -nfs #{shared_path}/UPLOADS
>> #{current_path}/public/UPLOADS")
>> end

Not sure why you are using a run_method var here, run "ln ..." also works fine :)

Additionally you can have a :created_shared_directory(ies) with a callback on
deploy:setup that creates the needed folders in the shared/ directory.

François Montel

unread,
Mar 19, 2009, 2:43:27 PM3/19/09
to Capistrano
Thanks, very helpful.

On Mar 19, 10:23 am, Jean-Philippe Moal <skateinm...@skateinmars.net>
wrote:
> François Montel a écrit :
>
> > Thanks, Ian and Jean-Philippe, very helpful input that sets me on
> > track.
>
> > Is there any advantage to using deploy:update (other than the rollback
> > option) as compared to just running a recipe that performs a git pull
> > (and whatever else I want to do when updating my code)?
>
> > For example, running deploy:update when there's a major version
> > release, but then a different custom recipe to only perform git pull
> > (etc.) when making minor changes/bug fixes.
>
> > Thanks. I'm just trying to understand how to make the best use of
> > capistrano.
>
> My main reason for always using the standard deploy recipe (with an entire
> clone/checkout/export/whatever) is that I want to be able to rollback any
> deployment, but your way is totally doable.
> If you write this kind of task you certainly will have to set the needed
> callbacks associated with the update_code task (seehttp://wiki.capify.org/index.php/Default_Execution_Path).

Ian Sheridan

unread,
Mar 19, 2009, 3:55:02 PM3/19/09
to capis...@googlegroups.com
Ah yes this is true "send(run_method" is an artifice of older versions
of Cap. You could change it to:

run "ln -nfs #{shared_path}/UPLOADS #{current_path}/public/UPLOADS")

François, You will need to use the "Before" and "After" methods to
make sure that this new task that you will make gets executed at the
right time. As Jean-Philippe said you should have it run "After"
"deploy:symlink".

Good Luck

- ian


On Thu, Mar 19, 2009 at 12:23 PM, Jean-Philippe Moal
<skate...@skateinmars.net> wrote:
>> On Mar 19, 8:52 am, Ian Sheridan <ian.sheri...@gmail.com> wrote:
>>>     desc "create symlink"
>>>     task :db, :roles => [:app] do
>>>       send(run_method, "ln -nfs #{shared_path}/UPLOADS
>>> #{current_path}/public/UPLOADS")
>>>     end
>
> Not sure why you are using a run_method var here, run "ln ..." also works fine :)
>
> Additionally you can have a :created_shared_directory(ies) with a callback on
> deploy:setup that creates the needed folders in the shared/ directory.

--

Reply all
Reply to author
Forward
0 new messages