我的主分支布局是这样的:
/ <-顶层
/ client <-桌面客户端源文件
/ server <-Rails应用
我想做的只是在我的目录中拉/ server目录deploy.rb
,但是我似乎找不到任何方法。/ client目录很大,因此设置一个将/ server复制到/的钩子将无法很好地工作,它只需要拉下Rails应用程序即可。
我的主分支布局是这样的:
/ <-顶层
/ client <-桌面客户端源文件
/ server <-Rails应用
我想做的只是在我的目录中拉/ server目录deploy.rb
,但是我似乎找不到任何方法。/ client目录很大,因此设置一个将/ server复制到/的钩子将无法很好地工作,它只需要拉下Rails应用程序即可。
Answers:
没有任何肮脏的分叉动作,甚至更脏!
在我的config / deploy.rb中:
set :deploy_subdir, "project/subdir"
然后,我将此新策略添加到我的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
end
end
set :strategy, RemoteCacheSubdir.new(self)
对于Capistrano 3.0,我使用以下命令:
在我的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}"
end
end
在我的deploy.rb
:
# Set up a strategy to deploy only a project directory (not the whole repo)
set :git_strategy, RemoteCacheWithProjectRootStrategy
set :project_root, 'relative/path/from/your/repo'
所有重要的代码都在strategyrelease
方法中,该方法git archive
仅用于存档存储库的子目录,然后使用--strip
参数tar
在正确的级别提取存档。
更新
从Capistrano 3.3.3开始,您现在可以使用:repo_tree
配置变量,这使此答案已过时。例如:
set :repo_url, 'https://example.com/your_repo.git'
set :repo_tree, 'relative/path/from/your/repo' # relative path to project root in repo
请参阅http://capistranorb.com/documentation/getting-started/configuration。
set :repo_tree, 'demo_app/server'
set :repo_tree, 'server'
我们还通过关闭整个存储库,删除未使用的文件和文件夹,并将所需的文件夹移到层次结构中,来使用Capistrano。
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}"
end
end
只要项目规模不大,这对我们来说就很好了,但如果可以的话,请为每个组件创建一个自己的存储库,并将它们与git子模块组合在一起。
您可以有两个git存储库(客户端和服务器),并将它们添加到“超级项目”(应用程序)中。在这个“超级项目”中,您可以将两个存储库添加为子模块(请检查本教程)。)。
另一个可能的解决方案(更加肮脏)是为客户端和服务器分别设置分支,然后您可以从“服务器”分支中拉出。
有一个解决方案。抓取针对capistrano的crdlo补丁和来自github的capistrano源代码。删除您现有的capistrano gem,应用补丁,安装setup.rb,然后您可以使用他的非常简单的配置行set :project, "mysubdirectory"
来设置子目录。
唯一的问题是,显然github至少在写时不“支持archive命令”。我在svn上使用了自己的私有git repo,它工作正常,我还没有在github上尝试过,但是我想如果有足够多的人抱怨他们会添加该功能。
对于Capistrano 3,基于@Thomas Fankhauser的答案:
set :repository, "git@github.com:name/project.git"
set :branch, "master"
set :subdir, "relative_path_to_my/subdir"
namespace :deploy do
desc "Checkout subdirectory and delete all the other stuff"
task :checkout_subdir do
subdir = fetch(:subdir)
subdir_last_folder = File.basename(subdir)
release_subdir_path = File.join(release_path, subdir)
tmp_base_folder = File.join("/tmp", "capistrano_subdir_hack")
tmp_destination = File.join(tmp_base_folder, subdir_last_folder)
cmd = []
# Settings for my-zsh
# cmd << "unsetopt nomatch && setopt rmstarsilent"
# create temporary folder
cmd << "mkdir -p #{tmp_base_folder}"
# delete previous temporary files
cmd << "rm -rf #{tmp_base_folder}/*"
# move subdir contents to tmp
cmd << "mv #{release_subdir_path}/ #{tmp_destination}"
# delete contents inside release
cmd << "rm -rf #{release_path}/*"
# move subdir contents to release
cmd << "mv #{tmp_destination}/* #{release_path}"
cmd = cmd.join(" && ")
on roles(:app) do
within release_path do
execute cmd
end
end
end
end
after "deploy:updating", "deploy:checkout_subdir"
我创建了一个片段,该片段与Capistrano 3.x一起使用,基于以前的答案以及在github中找到的其他信息:
# Usage:
# 1. Drop this file into lib/capistrano/remote_cache_with_project_root_strategy.rb
# 2. Add the following to your Capfile:
# require 'capistrano/git'
# require './lib/capistrano/remote_cache_with_project_root_strategy'
# 3. Add the following to your config/deploy.rb
# set :git_strategy, RemoteCacheWithProjectRootStrategy
# set :project_root, 'subdir/path'
# Define a new SCM strategy, so we can deploy only a subdirectory of our repo.
module RemoteCacheWithProjectRootStrategy
include Capistrano::Git::DefaultStrategy
def test
test! " [ -f #{repo_path}/HEAD ] "
end
def check
test! :git, :'ls-remote -h', 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}"
end
end
也可以在Github上作为Gist使用。
这已经为我工作了几个小时。
# Capistrano assumes that the repository root is Rails.root
namespace :uploads do
# We have the Rails application in a subdirectory rails_app
# Capistrano doesn't provide an elegant way to deal with that
# for the git case. (For subversion it is straightforward.)
task :mv_rails_app_dir, :roles => :app do
run "mv #{release_path}/rails_app/* #{release_path}/ "
end
end
before 'deploy:finalize_update', 'uploads:mv_rails_app_dir'
您可以为目录声明一个变量(此处为rails_app)。
让我们看看它有多健壮。使用“之前”是相当弱的。
不知道是否有人对此感兴趣。但是如果有人正在寻找答案,就让你们。现在我们可以使用::repo_tree
https://capistranorb.com/documentation/getting-started/configuration/