Déploiement d’un sous-répertoire Git dans Capistrano

La disposition de ma twig principale est la suivante:

/ <- niveau supérieur

/ client <- fichiers source du bureau client

/ server <- Application Rails

Ce que je voudrais faire, c’est de ne supprimer que le répertoire / server dans deploy.rb , mais je n’arrive pas à trouver le moyen de le faire. Le répertoire / client est énorme, donc configurer un hook pour copier / serveur sur / ne fonctionnera pas très bien, il suffit de déployer l’application Rails.

Sans aucune action sale mais encore plus sale!

Dans mon config / deploy.rb:

 set :deploy_subdir, "project/subdir" 

Ensuite, j’ai ajouté cette nouvelle stratégie à mon fichier 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) 

Pour Capistrano 3.0, j’utilise les éléments suivants:

Dans mon 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, "--ssortingp=#{fetch(:project_root).count('/')+1}" end end 

Et dans mon 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' 

Tout le code important se trouve dans la méthode de release stratégie, qui utilise git archive pour archiver uniquement un sous-répertoire du repository, puis utilise l’argument --ssortingp pour tar pour extraire l’archive au bon niveau.

METTRE À JOUR

A partir de Capistrano 3.3.3, vous pouvez maintenant utiliser la variable de configuration :repo_tree , ce qui rend cette réponse obsolète. Par exemple:

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

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

Nous faisons également cela avec Capistrano en clonant le repository complet, en supprimant les fichiers et dossiers inutilisés et en déplaçant le dossier souhaité dans la hiérarchie.

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 

Tant que le projet n’est pas trop gros, cela fonctionne plutôt bien pour nous, mais si vous le pouvez, créez un propre référentiel pour chaque composant et regroupez-les avec des sous-modules git.

Vous pouvez avoir deux référentiels git (client et serveur) et les append à un “super-projet” (app). Dans ce “super-projet”, vous pouvez append les deux référentiels en tant que sous-modules (consultez ce tutoriel ).

Une autre solution possible (un peu plus sale) est d’avoir des twigs séparées pour le client et le serveur, et ensuite vous pouvez tirer de la twig «serveur».

Malheureusement, git ne fournit aucun moyen de le faire. Au lieu de cela, la méthode git consiste à avoir deux référentiels – client et serveur – et à cloner celui (s) dont vous avez besoin.

Il y a une solution. Prenez le patch de crdlo pour capistrano et la source capistrano de github. Supprimez votre gem capistrano existant, appy le patch, setup.rb install, puis vous pouvez utiliser son set :project, "mysubdirectory" lignes de configuration très simple set :project, "mysubdirectory" pour définir un sous-répertoire.

Le seul truc est qu’apparemment github ne “supporte pas la commande d’archive” … du moins quand il l’a écrit. J’utilise mon propre repository git privé sur svn et ça marche bien, je ne l’ai pas essayé avec github mais j’imagine que si suffisamment de personnes se plaignent, elles vont append cette fonctionnalité.

Voyez également si vous pouvez faire en sorte que les auteurs de capistrano ajoutent cette fonctionnalité au cap lors du bogue concerné .

Pour Capistrano 3, basé sur @Thomas Fankhauser, répondez:

 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" 

On dirait que ça ne fonctionne pas non plus avec codebasehq.com donc j’ai fini par faire des tâches de capistrano qui nettoient le désordre 🙂 Peut-être y a-t-il une façon moins risquée de le faire en remplaçant certaines tâches de capistrano …

J’ai créé un snipped qui fonctionne avec Capistrano 3.x basé sur les réponses précédentes et d’autres informations trouvées dans 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, "--ssortingp=#{fetch(:project_root).count('/')+1}" end end 

Il est également disponible en tant que Gist sur Github .

Cela a fonctionné pour moi pendant quelques heures.

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

Vous pourriez déclarer une variable pour le répertoire (ici rails_app).

Voyons comment il est robuste. Utiliser “avant” est assez faible.