Go to Hackademy website

Migrer de Capistrano 2 vers 3 dans une application Rails

Numa Claudel

Posté par Numa Claudel dans les catégories outils

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.

Changements à apporter

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.

Au niveau des options

Quelques options ont changées, voici certains changements de définitions à noter:

  • il n’est plus nécessaire de définir de taches pour générer les liens symboliques des fichiers partagés entre les versions. Il suffit dorénavant de définir ceci:
set :linked_files, %w{ config/database.yml }
  • de même pour les dossiers partagés, une option linked_dirs est prévue à cet effet
  • l’option repository devient repo_url
  • l’option set :deploy_via, :remote_cache n’est plus nécessaire, car le mode :copy n’est plus présent dans la version 3
  • l’option pty se définie comme les autres: set :pty, true
  • l’option 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 }

Syntaxe des taches

Voici quelques exemples de nouveautés apportées par SSHKit:

  • la récupération de variable se fait via fetch(:var_name) et non plus simplement par var_name
  • les taches s’exécutent maintenant dans un block on, qui défini donc cette tache pour un ou plusieurs roles
  • within sert à définir le dossier dans lequel exécuter les commandes
  • pour définir des paramètres à une tache, il y a with
  • exécuter une commande ne se fait plus avec 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 groupe
  • wait: définit le temps d’attente entre 2 envois d’ordres pour les options groups et sequence

Flow de Capistrano 3

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

Pour finir

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.

Articles connexes

Un plugin Vim à la mimine

03/01/2019

Dans l’article précédent, intitulé une assez bonne intimité, je vous présentais GPG et le chiffrement de courriels. Nous avons alors remarqué que le contenu d’un courriel était encodé de sorte que le...

Une assez bonne intimité

20/12/2018

Si vous êtes utilisateur de MacOS, il y a de fortes chances que vous utilisiez Apple Mail pour échanger des courriels. Et comme vous êtes sensible à la confidentialité des informations que vous...

Tests end to end avec Jest et Puppeteer

05/07/2018

Dans cet article, on va partir sur des tests end to end. Pour planter le décor, un test end to end (e2e) est un test logiciel qui a pour but de valider que le système testé répond correctement à un...

Chasser les requêtes N+1 avec Bullet

05/04/2018

Aujourd’hui nous allons parler des requêtes N+1 dans une application Rails : vous savez ces lignes quasiment identiques, qui s’ajoutent de manière exponentielle aux logs, dès lors que l’on appelle...