Deploying a Git subdirectory in Capistrano Deploying a Git subdirectory in Capistrano ruby-on-rails ruby-on-rails

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.