ruby on rails - deploy - Capistrano 3 se ejecuta dentro de un directorio
capistrano rails (5)
Estoy tratando de escribir una tarea para Capistrano 3 que implique ejecutar la "instalación del compositor" dentro del directorio de la versión actual. Se ve algo como esto:
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
se configura en los archivos de ensayo y producción, en mi caso particular a php /home/user/composer.phar
Por alguna razón, este comando no se ejecuta en el directorio de la versión actual, sino que se ejecuta en el directorio principal (que contiene versiones actuales, compartidas, etc.)
Profundicé un poco más en esto y descubrí que cuando ejecutaba un comando de una sola palabra, como:
within release_path do
execute "pwd"
end
Funciona bien y ejecuta el comando en el directorio de la versión actual. Pero ... cuando ejecuto un comando con espacios, como:
within release_path do
execute "pwd && ls"
end
Se ejecuta en el directorio principal, y no en el directorio establecido por el bloque within
.
¿Alguien puede arrojar algo de luz sobre esto? ¡Gracias!
En realidad, su uso de la función within
es casi correcto. Le ha suministrado una cadena completa como un comando, pero el documento señala que esto resulta en un comportamiento poco confiable (que yo mismo he experimentado).
Deje que el primer argumento que se execute
sea un símbolo en lugar de una cadena (que contiene espacios en blanco):
within release_path do
execute fetch(:composer_command).to_sym, "install"
execute :pwd
execute :ls
end
Huele como un error de Cap 3.
Sugiero que solo garantice que está donde quiere estar desde la perspectiva de shell:
execute "cd ''#{release_path}''; #{fetch(:composer_command)} install"
Puede conservar todas las sutilezas de within()
, with()
, default_env
, etc., manteniendo la sintaxis de cadena natural:
within release_path do
execute *%w[ pip install -r requirements.txt ]
end
Un par de consejos:
1) Capistrano usa SSHKit para muchas cosas, entre las que se encuentra la ejecución de comandos. Para simplificar el uso de Composer, puede configurar el mapa de comandos (en deploy.rb
o production.rb
, etc.), aquí hay 2 ejemplos:
SSHKit.config.command_map[:composer] = "#{shared_path.join(''composer.phar'')}"
SSHKit.config.command_map[:composer] = ''/usr/bin/env composer.phar''
A continuación puedes ejecutarlo así:
execute :composer, :install
2) Desde una perspectiva de seguridad, es aconsejable desactivar la configuración de php allow_url_fopen
, pero desafortunadamente Composer necesita que esté habilitado para funcionar. Puedes usar este truco para dejarlo deshabilitado globalmente:
SSHKit.config.command_map[:composer] = "/usr/bin/env php -d allow_url_fopen=On #{shared_path.join(''composer.phar'')}"
Echa un vistazo a iniscan para obtener más consejos de seguridad sobre la configuración de php.
3) Composer tiene una opción -d, --working-dir
, que puede apuntar al directorio que contiene el archivo composer.json
para ejecutar Composer desde cualquier otro directorio. Esto debería solucionar tu problema:
execute :composer, ''-d'', release_path, :install
4) Es posible que desee echar un vistazo al proyecto de capistrano-composer :)
solo para referencia aquí está el Doc Capistrano que explica por qué within {}
no funciona con argumentos con espacios en blanco. Espero que esto ayude.