2008-08-26 30 views
61

tôi bố trí chi nhánh tổng thể là như thế này:Triển khai một thư mục con Git trong Capistrano

/ < - cấp cao nhất

/client < - máy tính để bàn nguồn client file

/máy chủ < - Ứng dụng Rails

Điều tôi muốn làm là chỉ kéo xuống thư mục/server trong số deploy.rb của tôi, nhưng tôi dường như không tìm được cách nào để làm điều đó. Thư mục/client là rất lớn, do đó, thiết lập một hook để sao chép/server đến/sẽ không hoạt động tốt, nó chỉ cần kéo xuống ứng dụng Rails.

Trả lời

75

Nếu không có bất kỳ hành động làm bẩn bẩn thỉu nào nhưng thậm chí còn bẩn hơn!

Trong cấu hình của tôi/deploy.rb:

set :deploy_subdir, "project/subdir" 

Sau đó, tôi thêm vào chiến lược mới này để Capfile tôi:

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) 
+14

Ồ, tôi ước gì tôi có thể gửi cho bạn một vài lon bia cooold. Cảm ơn bạn!! – Nazar

+3

Hoàn hảo. Đúng thứ tôi cần. Cảm ơn! – Matt

+0

NB. bất cứ ai đọc, điều này hoạt động nếu bạn đã sử dụng remote_cache như cơ chế: deploy_via của bạn (dựa trên truy cập SCM ở cuối máy chủ.) – jrg

2

Thật không may, git không cung cấp cách nào để thực hiện việc này. Thay vào đó, 'git way' là có hai kho - máy khách và máy chủ, và sao chép (các) thứ bạn cần.

+0

mentioning các 'git way' does not help anything or anyone. –

4

Bạn có thể có hai kho lưu trữ git (máy khách và máy chủ) và thêm chúng vào "siêu dự án" (ứng dụng). Trong "siêu dự án" này, bạn có thể thêm hai kho lưu trữ dưới dạng mô-đun con (kiểm tra this tutorial).

Một giải pháp khả thi khác (hơi bẩn hơn) là có các nhánh riêng biệt cho máy khách và máy chủ, và sau đó bạn có thể kéo từ nhánh 'máy chủ'.

2

Có một giải pháp. Lấy patch for capistrano và số capistrano source của crdlo từ github. Hủy bỏ đá quý capistrano hiện tại của bạn, cài đặt bản vá, cài đặt setup.rb, và sau đó bạn có thể sử dụng dòng cấu hình rất đơn giản của mình set :project, "mysubdirectory" để đặt thư mục phụ.

Bí quyết duy nhất là dường như github không "hỗ trợ lệnh lưu trữ" ... ít nhất khi anh ấy viết nó. Tôi đang sử dụng riêng của tôi git repo trên svn và nó hoạt động tốt, tôi đã không thử nó với github nhưng tôi tưởng tượng nếu đủ người phàn nàn họ sẽ thêm tính năng đó.

Ngoài ra, hãy xem liệu bạn có thể tải các tác giả capistrano để thêm tính năng này vào nắp at the relevant bug hay không.

+0

Liên kết ngọn hải đăng bị hỏng. Tôi tự hỏi nếu capistrano thực hiện điều này trong khi chờ đợi. –

1

Hình như nó cũng không làm việc với codebasehq.com vì vậy tôi đã kết thúc làm nhiệm vụ capistrano sạch sẽ mớ hỗn độn :-) Có thể có thực sự là một cách ít hacky để làm điều này bằng cách ghi đè một số nhiệm vụ capistrano ...

0

này đã làm việc cho tôi trong một vài giờ.

# 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' 

Bạn có thể khai báo biến cho thư mục (tại đây rails_app).

Hãy xem mức độ mạnh mẽ của nó. Sử dụng "trước" khá yếu.

10

Chúng tôi cũng đang làm điều này với Capistrano bằng cách nhân bản xuống kho lưu trữ đầy đủ, xóa các tệp và thư mục không được sử dụng và di chuyển thư mục mong muốn lên phân cấp.

deploy.rb

set :repository, "[email protected]: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 

Chừng nào dự án không nhận được quá lớn này làm việc khá tốt cho chúng ta, nhưng nếu bạn có thể, tạo ra một kho lưu trữ riêng cho mỗi thành phần và nhóm chúng lại với nhau với git submodules.

+1

Rất tốt! Một chút không hiệu quả, nhưng không phải là một hack xấu xí ít nhất. –

+0

Và đừng quên liên kết bằng tay thư mục nhật ký với tư cách là capistrano không tự động làm điều đó nữa .. –

+2

Để có cách tiếp cận hiệu quả hơn. Có một viên ngọc được tạo ra để thêm một chiến lược triển khai "copy_subdir". Chỉ thư mục phụ trong repo mới được lưu trữ và sao chép vào máy chủ từ xa. https://github.com/yyuu/capistrano-copy-subdir – Kevin

40

Đối Capistrano 3.0, tôi sử dụng như sau:

Trong tôi 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 

Và trong tôi 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' 

Tất cả các mã quan trọng là trong phương pháp chiến lược release , sử dụng git archive để chỉ lưu trữ một thư mục con của repo, sau đó sử dụng --strip một rgument để tar để trích xuất lưu trữ ở cấp độ phù hợp.

CẬP NHẬT

Tính đến Capistrano 3.3.3, bây giờ bạn có thể sử dụng các biến :repo_tree cấu hình, mà làm cho câu trả lời này đã lỗi thời. Ví dụ:

set :repo_url, 'https://example.com/your_repo.git' 
set :repo_tree, 'relative/path/from/your/repo' # relative path to project root in repo 

Xem http://capistranorb.com/documentation/getting-started/configuration.

+0

Tôi không thể đặt chiến lược tùy chỉnh bằng cách sử dụng 'set: git_strategy', nó được lưu giữ bằng cách sử dụng DefaultStrategy – leojh

+7

Tôi cũng cần sao chép và dán phương thức "fetch_revision" từ gốc. (Https://github.com/capistrano/capistrano/blob/ master/lib/capistrano/git.rb) –

+1

@TsuneoYoshioka Có, phương thức "fetch_revision" đã được thêm vào trong Capistrano 3.1. Tuy nhiên, 3.1 cũng đã thêm biến cấu hình 'repo_tree', mà (vui vẻ) làm cho câu trả lời này lỗi thời. Xem https://github.com/capistrano/capistrano#configuration để biết chi tiết. –

1

Tôi tạo ra một Snipped làm việc với Capistrano 3.x có trụ sở tại anwers trước và các thông tin khác được tìm thấy trong 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 

Nó cũng có sẵn như là một Gist trên Github.

+0

Vô tình cuộn xuống tất cả các con đường xuống và tìm thấy điều này. Làm việc cho tôi, +1. –

+0

nó cũng hoạt động tốt cho tôi ... cảm ơn +1 Tôi hiện có thể triển khai phiên bản api v1, v2, ... – erwin

2

Đối Capistrano 3, based on @Thomas Fankhauser answer:

set :repository, "[email protected]: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" 
Các vấn đề liên quan