Deploy laravel avec capistrano 3

Le déploiement d'une application est souvent compliqué. Entre les releases foireuses, les migrations ratées et les downtimes qui n'en finissent pas...Bref vous voyez le genre.

Capistrano permet de résoudre tout ça et sans écrire un putain de script bash de merde qui prendra des dizaines de lignes, devra être exécuté directement sur le serveur etc.

Avec Capistrano vous allez pouvoir:

  • Déployer votre app en une ligne
  • Lancer un déploiement via un CI
  • Utiliser les clés ssh pour les autorisations server
  • Définir des tasks pendant le deploy

Installer Capistrano

Capistrano étant fait en ruby, vous comprendrez bien qu'il faut ruby d'installer! Je ne vais pas décrire la procédure pour installer ruby ici.

Pour installer Capistrano 3:

# gem install capistrano

Une fois la gem installée il faut mettre en place la config sur notre projet laravel.

Pour cela placez-vous à la racine de votre projet et faite un:

# cap install

Cette commande génère plusieurs fichiers pour nous.

Notamment un dossier/fichier config/deploy.rb qui contient notre future configuration.

Préparer le terrain

Pour commencer nous allons définir deux serveurs de déploiements.

Un serveur de préproduction et un de production. Vous allez donc devoir mettre en place une connexion ssh via clés privée/publique sur ces deux serveurs.

Dans le dossier config/deploy/ vous trouverez deux fichiers. Il représente vos stage qui vous permettrons de deploy votre application de differentes façons.

Créer un fichier preprod.rb dans config/deploy/:

set :stage, :preprod

# Définit un serveur pour le déploiement préprod
# Vous pouvez en définir plusieurs si vous souhaitez 
# déployer sur plusieurs serveurs en meme temps
server 'example.com', user: 'deploy', roles: %w{web app}  

Nos tasks

Maintenant que nous avons défini notre serveur nous allons configurer les différentes tasks.

Nous allons maintenant éditer le fichier config/deploy.rb.

Il se présente comme ceci:

# config valid only for Capistrano 3.1
lock '3.1.0'

set :application, "TestApp"  # Le nom de votre app

set :scm, :git  
# L'url git de votre projet
set :repo_url, "git@github.com:test/test.git"

set :use_sudo, false # On est pas fou quand même  
set :ssh_options, {  
   :forward_agent => true
}

# On demande au serveur de garder 5 releases
# Pour une plus grande flexibilité lors des rollbacks
set :keep_releases, 5

# Lorsqu'on utilise le namespace deploy
namespace :deploy do

    after :finishing, "deploy:cleanup"

end  

On a déjà un bon squelette, on va définir des tasks pour notre projet laravel:

  • Lancer un composer install
  • Définition des permissions
  • Lancement des migrations
  • Lancement des optimisations

On va donc définir des tasks pour tout ceci. Nous allons créer un namespace pour laravel et composer.

Je vais placer tout le code suivant dans le fichier config/deploy.rb, après la définition du ssh forward_agent.

Nous allons définir la task lançant le composer install.

namespace :composer do

    desc "Run composer install in release_path."
    task :install do
        on roles(:all) do
            within release_path do
                execute "composer", "install", "-o"
            end
        end
    end
end  

Le code ruby est plutôt clair et parlant. Je ne pense pas avoir besoin de l'expliquer ligne par ligne.

Création des tasks laravel:

namespace :laravel do

    desc "Setup Laravel folder permissions."
    task :permissions do
        on roles(:all) do
            within release_path do
                execute "chmod", "u+x", "artisan"
                execute "chmod", "-R", "w", "app/storage"
            end
        end
    end

    desc "Run Laravel Artisan migrate."
    task :migrate do
        on roles(:all) do
            wihtin release_path do
                execute "php", "artisan", "migrate"
            end
        end
    end

    desc "Optimize Laravel Class Loader"
    task :optimize do
        on roles(:all) do
            within release_path do
                execute "php", "artisan", "clear-compiled"
                execute "php", "artisan", "optimize"
            end
        end
    end
end  

Vos tasks sont maintenant créés mais vous devez définir où les placer dans le processus.

Dans le namespace :deploy:

namespace :deploy do

    after :publishing, "composer:install"
    after :publishing, "laravel:permissions"
    after :publishing, "laravel:migrate"
    after :publishing, "laravel:optimize"
end  

Il ne vous reste plus qu'a tester tout ceci!

# cap preprod deploy

Voila vous pouvez maintenant créer vos tasks et déployer vos releases!

Prochaine étape le rollback!

ps: Si vous avez des améliorations/suggestions n'hésitez pas à me contacter!