2008-08-26 39 views
61

Mi diseño rama principal es la siguiente:desplegar un subdirectorio Git en Capistrano

/ < - nivel superior

/cliente < - archivos de origen del cliente de escritorio

/servidor < - Aplicación Rails

Lo que me gustaría do es solo desplegar el directorio/server en mi deploy.rb, pero parece que no puedo encontrar ninguna manera de hacerlo. El directorio/client es enorme, por lo que configurar un hook para copiar/server a/will not work very well, necesita solo desplegar la aplicación Rails.

Respuesta

75

¡Sin ninguna acción de bifurcación sucia, pero aún más sucio!

En mi config/deploy.rb:

set :deploy_subdir, "project/subdir" 

Luego añade esta nueva estrategia para mi 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) 
+14

¡Oh, cómo me gustaría poder enviarte unas pintas de cerveza fresca! ¡¡Gracias!! – Nazar

+3

Perfecto. Justo lo que necesitaba. ¡Gracias! – Matt

+0

NB. Alguien leyendo, esto funciona si ya está utilizando remote_cache como su mecanismo: deploy_via (que se basa en el acceso SCM en el extremo del servidor). – jrg

2

Desafortunadamente, git no ofrece ninguna manera de hacerlo. En cambio, la 'manera Git' es tener dos repositorios, cliente y servidor, y clonar uno (s) que necesita.

+0

mencionar la 'vía Git' no ayuda a nada ni a nadie. –

4

Puede tener dos repositorios git (cliente y servidor) y agregarlos a un "superproyecto" (aplicación). En este "superproyecto" puede agregar los dos repositorios como submódulos (marque this tutorial).

Otra posible solución (un poco más sucia) es tener ramas separadas para el cliente y el servidor, y luego se puede extraer de la rama 'servidor'.

2

Hay una solución. Toma el patch for capistrano de crdlo y el capistrano source de github. Quite su gema capistrano existente, aplique el parche, instale setup.rb, y luego puede usar su línea de configuración muy simple set :project, "mysubdirectory" para establecer un subdirectorio.

El único problema es que aparentemente github no "admite el comando de archivo" ... al menos cuando lo escribió. Estoy usando mi propio git repo privado sobre svn y funciona bien, no lo he probado con github, pero me imagino que si hay suficientes personas se quejan de que agregarán esa característica.

También vea si puede lograr que los autores de capistrano añadan esta característica al casillero at the relevant bug.

+0

El enlace del faro está roto. Me pregunto si Capistrano implementó esto mientras tanto. –

1

parece que es también no trabajar con codebasehq.com así que terminé haciendo tareas Capistrano que limpia el lío :-) Tal vez hay en realidad es una forma menos hacky de hacer esto reemplazando algunas tareas Capistrano ...

0

Esto ha estado trabajando para mí durante unas 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' 

Puede declarar una variable para el directorio (aquí rails_app).

Veamos qué tan robusto es. Usar "antes" es bastante débil.

10

También estamos haciendo esto con Capistrano clonando por el depósito completo, eliminar los archivos y carpetas no utilizados y mover la carpeta deseada en la jerarquía.

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 

Mientras que el proyecto no sea demasiado grande esto funciona bastante bien para nosotros, pero si se puede, crear un repositorio propio de cada componente y agruparlos con git submódulos.

+1

¡Agradable! Un poco ineficiente, pero no un hack feo al menos. –

+0

Y no te olvides de vincular simbólicamente manualmente el directorio de registro ya que capistrano ya no lo hace automáticamente .. –

+2

Para un enfoque más eficiente. Hay una gema que alguien creó que agrega una estrategia de implementación "copy_subdir". Solo el subdirectorio en el repositorio se archiva y copia en el servidor remoto. https://github.com/yyuu/capistrano-copy-subdir – Kevin

40

Para Capistrano 3.0, utilizo el siguiente:

En mi 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 

Y en mi 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 el código importante está en el método de la estrategia release , que usa git archive para archivar solo un subdirectorio del repositorio, luego usa el --strip a rgument al tar para extraer el archivo en el nivel correcto.

ACTUALIZACIÓN

A partir de Capistrano 3.3.3, ahora se puede utilizar la variable de configuración :repo_tree, lo que hace que esta respuesta obsoleta. Por ejemplo:

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.

+0

No pude establecer la estrategia personalizada usando 'set: git_strategy', mantenía usando DefaultStrategy – leojh

+7

También necesitaba copiar y pegar el método "fetch_revision" desde el original. (Https://github.com/capistrano/capistrano/blob/ master/lib/capistrano/git.rb) –

+1

@TsuneoYoshioka Sí, se agregó el método "fetch_revision" en Capistrano 3.1. Sin embargo, 3.1 también agregó la variable de configuración 'repo_tree', que (afortunadamente) hace que esta respuesta sea obsoleta. Ver https://github.com/capistrano/capistrano#configuration para más detalles. –

1

he creado un cortado con tijeras que funciona con 3.x Capistrano basado en anwers anteriores y otras informaciones que se encuentran en 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 

También está disponible como una Gist en Github.

+0

Desplazado accidentalmente hasta el fondo y encontrado esto. Funciona para mí, +1. –

+0

funciona bien para mí también ... gracias +1 Ahora puedo implementar las versiones de api v1, v2, ... – erwin

2

Para Capistrano 3, basado en @Thomas Fankhauser respuesta:

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" 
Cuestiones relacionadas