Deploying a Git subdirectory in Capistrano
Without any dirty forking action but even dirtier !
In my config/deploy.rb :
set :deploy_subdir, "project/subdir"
Then I added this new strategy to my Capfile :
require 'capistrano/recipes/deploy/strategy/remote_cache'class RemoteCacheSubdir < Capistrano::Deploy::Strategy::RemoteCache private def repository_cache_subdir if configuration[:deploy_subdir] then File.join(repository_cache, configuration[:deploy_subdir]) else repository_cache end end def copy_repository_cache logger.trace "copying the cached version to #{configuration[:release_path]}" if copy_exclude.empty? run "cp -RPp #{repository_cache_subdir} #{configuration[:release_path]} && #{mark}" else exclusions = copy_exclude.map { |e| "--exclude=\"#{e}\"" }.join(' ') run "rsync -lrpt #{exclusions} #{repository_cache_subdir}/* #{configuration[:release_path]} && #{mark}" end endendset :strategy, RemoteCacheSubdir.new(self)
For Capistrano 3.0, I use the following:
In my Capfile
:
# Define a new SCM strategy, so we can deploy only a subdirectory of our repo.module RemoteCacheWithProjectRootStrategy def test test! " [ -f #{repo_path}/HEAD ] " end def check test! :git, :'ls-remote', repo_url end def clone git :clone, '--mirror', repo_url, repo_path end def update git :remote, :update end def release git :archive, fetch(:branch), fetch(:project_root), '| tar -x -C', release_path, "--strip=#{fetch(:project_root).count('/')+1}" endend
And in my deploy.rb
:
# Set up a strategy to deploy only a project directory (not the whole repo)set :git_strategy, RemoteCacheWithProjectRootStrategyset :project_root, 'relative/path/from/your/repo'
All the important code is in the strategy release
method, which uses git archive
to archive only a subdirectory of the repo, then uses the --strip
argument to tar
to extract the archive at the right level.
UPDATE
As of Capistrano 3.3.3, you can now use the :repo_tree
configuration variable, which makes this answer obsolete. For example:
set :repo_url, 'https://example.com/your_repo.git'set :repo_tree, 'relative/path/from/your/repo' # relative path to project root in repo
See http://capistranorb.com/documentation/getting-started/configuration.
We're also doing this with Capistrano by cloning down the full repository, deleting the unused files and folders and move the desired folder up the hierarchy.
deploy.rb
set :repository, "git@github.com:name/project.git"set :branch, "master"set :subdir, "server"after "deploy:update_code", "deploy:checkout_subdir"namespace :deploy do desc "Checkout subdirectory and delete all the other stuff" task :checkout_subdir do run "mv #{current_release}/#{subdir}/ /tmp && rm -rf #{current_release}/* && mv /tmp/#{subdir}/* #{current_release}" endend
As long as the project doesn't get too big this works pretty good for us, but if you can, create an own repository for each component and group them together with git submodules.