Aujourd’hui je vous propose de faire une revue des changements nécessaires pour migrer Capistrano de la version 2 vers la 3 dans une application Rails.
Tout d’abord il faut mettre à jour le Gemfile pour ajuster les gems et les versions à utiliser:
gem 'capistrano', '~> 2.0'
devient:
gem 'capistrano', '~> 3.0'
Il faut aussi rajouter ces 2 gems:
gem 'capistrano-rails', '~> 1.1', require: false
gem 'capistrano-bundler', '~> 1.1', require: false
puisque Capistrano 3 n’intègre plus Rails et Bundler par défaut. Si vous utilisez Passenger, vous voudrez aussi ajouter capistrano-passenger
.
Nous avons aussi les gems correpondantes au gestionnaire de versions de Ruby capistrano-rvm
, capistrano-rbenv
et capistrano-chruby
, qu’il peut être intéressant d’ajouter. Dans mon cas:
gem 'capistrano-rbenv', '~> 2.0', require: false
Il est ensuite conseillé de faire un backup de l’ancienne configuration de Capistrano 2, qui comprend au minimum un Capfile
, un config/deploy.rb
, et en cas de multi-instances les fichiers compris dans config/deploy/
:
mkdir old_cap
mv Capfile old_cap
mv config/deploy.rb old_cap
mv config/deploy/ old_cap
Après un bundle install
, nous pouvons utiliser la nouvelle commande d’installation de Capistrano 3:
bundle exec cap install
On retrouve le Capfile
à la racine du projet, ainsi que config/deploy.rb
et, puisque Capistrano 3 est multi-instances par défaut, config/deploy/staging.rb
et config/deploy/production.rb
.
Voici le Capfile généré:
# Load DSL and set up stages
require 'capistrano/setup'
# Include default deployment tasks
require 'capistrano/deploy'
# Include tasks from other gems included in your Gemfile
#
# For documentation on these, see for example:
#
# https://github.com/capistrano/rvm
# https://github.com/capistrano/rbenv
# https://github.com/capistrano/chruby
# https://github.com/capistrano/bundler
# https://github.com/capistrano/rails
# https://github.com/capistrano/passenger
#
# require 'capistrano/rvm'
# require 'capistrano/rbenv'
# require 'capistrano/chruby'
# require 'capistrano/bundler'
# require 'capistrano/rails/assets'
# require 'capistrano/rails/migrations'
# require 'capistrano/passenger'
# Load custom tasks from `lib/capistrano/tasks' if you have any defined
Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }
Nous pouvons décommenter les parties qui nous intéressent. Déjà capistrano/bundler
, capistrano/rails/assets
et capistrano/rails/migrations
, puis la gem en rapport avec Passenger si vous l’utilisez, ainsi que la gem correspondante à notre gestionnaire de versions de Ruby.
On peut maintenant remettre en place les anciens fichiers de multi-instances au même endroit dans config/deploy/
, et “merger” les nouveaux fichiers avec les anciens.
Notez que la tache deploy:restart
n’est plus exécutée automatiquement, il faut donc penser à l’appeler:
after 'deploy:publishing', 'deploy:restart'
# ou
namespace :deploy do
after :publishing, :restart
end
Pour les utilisateurs de Passenger ayant intégrés la gem capistrano-passenger
, cet ajout n’est pas nécessaire.
Quelques options ont changées, voici certains changements de définitions à noter:
set :linked_files, %w{ config/database.yml }
linked_dirs
est prévue à cet effetrepository
devient repo_url
set :deploy_via, :remote_cache
n’est plus nécessaire, car le mode :copy
n’est plus présent dans la version 3pty
se définie comme les autres: set :pty, true
verbose
du tableau d’options ssh_options
remplace l’option -v
de la ligne de commande. Elle peut être utile pour trouver les erreurs lors d’un déploiement.set :ssh_options, { verbose: :debug }
Voici quelques exemples de nouveautés apportées par SSHKit:
fetch(:var_name)
et non plus simplement par var_name
on
, qui défini donc cette tache pour un ou plusieurs roleswithin
sert à définir le dossier dans lequel exécuter les commandeswith
run
, mais avec execute
Exemple pour une tache seed
:
desc 'Runs rake db:seed'
task :seed => [:set_rails_env] do
on primary fetch(:migration_role) do
within release_path do
with rails_env: fetch(:rails_env) do
execute :rake, "db:seed"
end
end
end
end
On peut également voir dans le config/deploy.rb
généré:
after :restart, :clear_cache do
on roles(:web), in: :groups, limit: 3, wait: 10 do
# Here we can do anything such as:
# within release_path do
# execute :rake, 'cache:clear'
# end
end
end
Ici on observe les options in
, limit
et wait
qui servent respectivement à:
in
: pour définir la stratégie d’execution de la commande sur les différents serveurs (options: parallel
, groups
et sequence
)limit
: en cas d’utilisation de l’option groups
, définit la taille du groupewait
: définit le temps d’attente entre 2 envois d’ordres pour les options groups
et sequence
Le “flow” de déploiement de Capistrano 3 est quelque peu simplifié:
deploy:starting - start a deployment, make sure everything is ready
deploy:started - started hook (for custom tasks)
deploy:updating - update server(s) with a new release
deploy:updated - updated hook
deploy:publishing - publish the new release
deploy:published - published hook
deploy:finishing - finish the deployment, clean up everything
deploy:finished - finished hook
et voici celui d’un “rollback”:
deploy:starting
deploy:started
deploy:reverting - revert server(s) to previous release
deploy:reverted - reverted hook
deploy:publishing
deploy:published
deploy:finishing_rollback - finish the rollback, clean up everything
deploy:finished
Une fois le “merge” fini, tout devrait fonctionner comme avant mais avec Capistrano 3. Pour vérifier que tout est ok:
bundle exec cap staging deploy:check
Encore une chose, la tâche cap deploy:cold
destinée au premier déploiement d’une application, a été retiré de Capistrano version 3. Voici une page donnant quelques options pour ce cas.
Terminons par un petit nettoyage, désinstallons l’ancienne gem Capistrano 2:
gem uninstall capistrano --version '<3.0'
Voilà donc la base des changements à connaître et à apporter pour effectuer cette migration, sur laquelle vous devrez sans aucun doute faire quelques ajustements en fonction de votre projet.
L’équipe Synbioz.
Libres d’être ensemble.