A implantação de um Git subdiretório em Capistrano
-
09-06-2019 - |
Pergunta
Meu branch master esquema é assim:
/ <-- nível superior
/cliente <-- cliente da área de trabalho arquivos de origem
/server <-- Trilhos app
O que eu gostaria de fazer é só puxar para baixo o diretório /server na minha deploy.rb
, mas eu não consigo encontrar nenhuma maneira de fazer isso.O cliente /diretório é enorme, então a configuração de um gancho para cópia /servidor / não irá funcionar muito bem, ele precisa só puxar para baixo o app Rails.
Solução
Sem qualquer suja bifurcar-se de ação, mas ainda mais sujo !
Na minha config/deploy.rb :
set :deploy_subdir, "project/subdir"
Então eu adicionei essa nova estratégia, a meu 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)
Outras dicas
Para Capistrano 3.0, eu uso o seguinte:
No meu 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
E no meu 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'
Todo o código é importante na estratégia release
o método, que usa git archive
para arquivar apenas um subdiretório do acordo de recompra, em seguida, usa o --strip
argumento tar
para extrair o arquivo no nível certo.
ATUALIZAÇÃO
Como de Capistrano 3.3.3, agora você pode usar o :repo_tree
variável de configuração, o que torna esta resposta obsoletos.Por exemplo:
set :repo_url, 'https://example.com/your_repo.git'
set :repo_tree, 'relative/path/from/your/repo' # relative path to project root in repo
Ver http://capistranorb.com/documentation/getting-started/configuration.
Também estamos fazendo isso com Capistrano através da clonagem para baixo o repositório completo, apagando os arquivos e pastas não utilizados e mover a pasta desejada para cima na hierarquia.
implantar.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
Enquanto o projeto não é muito grande, isso funciona muito bem para nós, mas se você pode criar um repositório próprio para cada componente e agrupá-los em conjunto com o git submódulos.
Você pode ter dois repositórios git (cliente e servidor) e adicioná-los a um "super-projeto" (app).Nesta "super-projecto" você pode adicionar os dois repositórios como submódulos (seleção este tutorial).
Outra solução possível (um pouco mais suja) é separado ramos para o cliente e servidor e, em seguida, você pode usar o 'servidor' ramo.
Não é uma solução.Pegue crdlo do patch para capistrano e o capistrano de origem a partir do github.Remova o existente em seu capistrano gem, aplicar o patch, o programa de configuração.rb instalar e, em seguida, você pode usar a sua configuração muito simples de linha de set :project, "mysubdirectory"
para definir um subdiretório.
A única pegadinha é que, aparentemente, o github não "suporta o comando de arquivo" ...pelo menos quando ele a escreveu.Eu estou usando o meu próprio privado repositório git sobre o svn e ele funciona muito bem, eu ainda não tentei com o github, mas eu imagino que se um número suficiente de pessoas se queixam de que vai adicionar essa funcionalidade.
Também veja se você pode obter capistrano de autores para adicionar esse recurso no pac no respectivo erro.
Para Capistrano 3, com base no @Thomas Fankhauser resposta:
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"
Infelizmente, o git não fornece nenhuma maneira de fazer isso.Em vez disso, o 'git forma' é ter dois repositórios -- o cliente e o servidor, e o clone(s) que você precisa.
Eu criei um corte que funciona com Capistrano 3.x baseado no anterior anwers e outras informações encontradas no 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
Ele também está disponível como uma Essência em Github.
Parece que ele também não trabalho com codebasehq.com então eu acabei fazendo capistrano tarefas que limpa a bagunça :-) Talvez na verdade, há uma menor hacky maneira de fazer isso substituindo alguns capistrano tarefas...
Esta tem sido a trabalhar para mim por algumas horas.
# 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'
Você pode declarar uma variável para o diretório (aqui rails_app).
Vamos ver o quão robusta é.Usando o "antes" é muito fraco.