【问题标题】:Deploying a Git subdirectory in Capistrano在 Capistrano 中部署 Git 子目录
【发布时间】:2010-09-06 22:46:05
【问题描述】:

我的主分支布局是这样的:

/

/client

/server

我想做的只是在我的deploy.rb 中拉下 /server 目录,但我似乎找不到任何方法来做到这一点。 /client 目录很大,所以设置一个 hook 将 /server 复制到 / 不会很好,它只需要拉下 Rails 应用程序。

【问题讨论】:

    标签: ruby-on-rails git deployment capistrano


    【解决方案1】:

    不知道是否还有人对此感兴趣。但如果有人在寻找答案,就让你们看看。 现在我们可以使用::repo_tree

    https://capistranorb.com/documentation/getting-started/configuration/

    【讨论】:

      【解决方案2】:

      对于 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'
      

      所有重要代码都在策略release 方法中,该方法使用git archive 仅归档repo 的子目录,然后使用tar--strip 参数在正确的级别提取归档。

      更新

      从 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 :git_strategy' 设置自定义策略,它一直使用 DefaultStrategy
      • 我还需要从原始文件中复制并粘贴“fetch_revision”方法。(github.com/capistrano/capistrano/blob/master/lib/capistrano/…)
      • @TsuneoYoshioka 是的,Capistrano 3.1 中添加了“fetch_revision”方法。但是,3.1 还添加了“repo_tree”配置变量,这(很高兴)使这个答案过时了。详情请见github.com/capistrano/capistrano#configuration
      • :repo_tree 实际上是在 3.3.3 而不是 3.1 中添加的。对于那些看到这一点但对他们不起作用的人。
      • 嗨,我正在使用 capistrano 3.4.0,但我仍然无法使用 :repo_tree 变量使其工作。我有一个名为 demo_app 的 git repo,它有两个子目录 serverclient。我想使用 server 子目录进行部署。如何使用 :repo_tree 进行设置?这些都不起作用:- set :repo_tree, 'demo_app/server' set :repo_tree, 'server'
      【解决方案3】:

      对于 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"
      

      【讨论】:

        【解决方案4】:

        我根据以前的答案和 github 中的其他信息创建了一个可与 Capistrano 3.x 配合使用的片段:

        # 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 获得。

        【讨论】:

        • 不小心一直向下滚动,发现了这个。为我工作,+1。
        • 它对我来说也很好用...谢谢 +1 我现在可以部署 api 版本 v1、v2、...
        【解决方案5】:

        我们也在 Capistrano 上通过克隆完整的存储库、删除未使用的文件和文件夹并将所需的文件夹向上移动到层次结构来执行此操作。

        部署.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 子模块组合在一起。

        【讨论】:

        • 不错!有点低效,但至少不是丑陋的黑客。
        • 并且不要忘记手动符号链接日志目录,因为 capistrano 不再自动执行此操作了..
        • 为了更有效的方法。有人创建了一个 gem,它添加了一个部署策略“copy_subdir”。只有 repo 中的子目录被归档并复制到远程服务器。 github.com/yyuu/capistrano-copy-subdir
        • 知道我们如何根据这个角色来做吗?
        【解决方案6】:

        您可以拥有两个 git 存储库(客户端和服务器)并将它们添加到“超级项目”(应用程序)。在这个“超级项目”中,您可以将两个存储库添加为子模块(检查this tutorial)。

        另一种可能的解决方案(有点脏)是为客户端和服务器设置单独的分支,然后您可以从“服务器”分支中拉取。

        【讨论】:

          【解决方案7】:

          这已经为我工作了几个小时。

          # 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)。

          让我们看看它有多强大。使用“之前”非常弱。

          【讨论】:

            【解决方案8】:

            没有任何肮脏的分叉动作,但更肮脏!

            在我的 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)
            

            【讨论】:

            • 哦,我多么希望我能给你送几品脱凉爽的啤酒。谢谢!!
            • 完美。正是我需要的。谢谢!
            • 注意。任何阅读的人,如果您已经使用 remote_cache 作为您的 :deploy_via 机制(这依赖于服务器端的 SCM 访问),这将有效。
            • 我不断收到加载错误:找不到需要“capistrano/recipes/deploy/strategy/remote_cache”文件。我正在使用 Capistrano 3
            【解决方案9】:

            看起来它也不适用于 codebasehq.com,所以我最终制作了清理混乱的 capistrano 任务 :-) 也许通过覆盖一些 capistrano 任务实际上有一种不那么老套的方法......

            【讨论】:

              【解决方案10】:

              有一个解决方案。从 github 获取 crdlo 的 patch for capistranocapistrano source。移除你现有的 capistrano gem,应用补丁,setup.rb 安装,然后你可以使用他非常简单的配置行set :project, "mysubdirectory" 设置一个子目录。

              唯一的问题是 github 显然不“支持归档命令”……至少在他写它的时候是这样。我在 svn 上使用我自己的私人 git 存储库,它工作正常,我没有在 github 上尝试过,但我想如果有足够多的人抱怨他们会添加该功能。

              还可以看看是否可以让 capistrano 作者将此功能添加到 cap at the relevant bug

              【讨论】:

              • 灯塔链接已损坏。我想知道 capistrano 是否同时实现了这一点。
              【解决方案11】:

              不幸的是,git 无法做到这一点。相反,“git 方式”是拥有两个存储库——客户端和服务器,然后克隆你需要的。

              【讨论】:

              • 提及“git方式”对任何人或任何人都没有帮助。
              猜你喜欢
              • 2011-09-05
              • 2013-09-23
              • 1970-01-01
              • 2014-12-06
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多