web-dev-qa-db-fra.com

Capistrano 3 s'exécute dans un répertoire

J'essaie d'écrire une tâche pour Capistrano 3 qui implique d'exécuter une "installation du compositeur" dans le répertoire de la version actuelle. Cela ressemble à ceci:

namespace :composer do
  desc 'Install dependencies with Composer'
  task :install do
    on roles(:web) do
      within release_path do
        execute "#{fetch(:composer_command)} install"
      end
    end
  end
end

composer_command est défini dans les fichiers de transfert et de production - dans mon cas particulier sur php /home/user/composer.phar

Pour une raison quelconque, cette commande ne s'exécute pas réellement dans le répertoire de la version actuelle, mais s'exécute à la place dans le répertoire parent (contenant les versions actuelles, partagées, etc.)

J'ai approfondi un peu plus loin et j'ai constaté que lorsque j'exécutais une seule commande Word, comme:

within release_path do
    execute "pwd"
end

Cela fonctionne très bien et exécute la commande dans le répertoire de version actuel. Mais ... lorsque j'exécute une commande avec des espaces, comme:

within release_path do
    execute "pwd && ls"
end

Il s'exécute dans le répertoire parent et non dans le répertoire défini par le bloc within.

Quelqu'un peut-il nous éclairer à ce sujet? Merci!

29
Rahul Sekhar

Ça sent comme un bogue de Cap 3.

Je suggère simplement de garantir que vous êtes là où vous voulez être du point de vue de Shell:

execute "cd '#{release_path}'; #{fetch(:composer_command)} install"
31
Electrawn

Vous pouvez conserver toutes les subtilités de within(), with(), default_env, etc., tout en conservant la syntaxe de chaîne naturelle:

within release_path do
  execute *%w[ pip install -r requirements.txt ]
end
9
bricker

Quelques conseils:

1) Capistrano utilise SSHKit pour beaucoup de choses, parmi lesquelles l'exécution de commandes. Afin de simplifier l'utilisation de Composer, vous pouvez configurer la mappe de commande (dans deploy.rb ou production.rb, etc.), voici 2 exemples:

SSHKit.config.command_map[:composer] = "#{shared_path.join('composer.phar')}"
SSHKit.config.command_map[:composer] = '/usr/bin/env composer.phar'

Ensuite, vous pouvez l'exécuter comme suit:

execute :composer, :install

2) Du point de vue de la sécurité, il est sage de désactiver le paramètre php allow_url_fopen, mais malheureusement Composer a besoin qu'il soit activé pour fonctionner. Vous pouvez utiliser cette astuce pour le désactiver globalement:

SSHKit.config.command_map[:composer] = "/usr/bin/env php -d allow_url_fopen=On #{shared_path.join('composer.phar')}"

Consultez iniscan pour plus de conseils de sécurité sur les paramètres php.

3) Composer a une option -d, --working-dir, que vous pouvez pointer vers le répertoire contenant le composer.json fichier pour exécuter Composer à partir de tout autre répertoire. Cela devrait résoudre votre problème:

execute :composer, '-d', release_path, :install

4) Vous voudrez peut-être jeter un œil au projet capistrano-composer :)

7
Jasper N. Brouwer

En fait, votre utilisation de la fonction within est presque correcte. Vous lui avez fourni une chaîne entière en tant que commande, mais le doc souligne que cela se traduit par un comportement peu fiable (que j'ai moi-même expérimenté).

Soit le premier argument de execute un symbole au lieu d'une chaîne (qui contient des espaces):

within release_path do
    execute fetch(:composer_command).to_sym, "install"
    execute :pwd
    execute :ls
end
4
JellicleCat

juste pour référence ici est le Capistrano Doc expliquant pourquoi within {} ne fonctionne pas avec les arguments avec des espaces. J'espère que ça aide.

3
cdog