Déployez malin avec PHP

Quand on s'attaque à des projets d'une certaine envergure, déployer son travail sur les serveurs de production devient une corvée qu'on préfère naturellement éviter. D'un point de vue logistique, il devient alors nécessaire de pouvoir déployer le code en pressant un unique bouton et sans s'inquiéter des spécificités des serveurs.

Il existe bien des méthodes pour accomplir ce but; on peut en bricoler facilement à coup de script bash et rsync, ou alors en faisant appel à des outils testés comme capistrano, rake et bundler pour Ruby.

Le monde de PHP, avec ses bizarreries habituelles manque cruellement de structure du point de vue déploiement. Il y a bien sûr des recettes pour utiliser capistrano mais dans la plupart des cas elles assument que le paquet PHP est tout-en-un et n'a pas de dépendances insatisfaites; ou alors le script de déploiement contient plus d'instructions qu'il ne le devrait obligeant l'écriture de règles particulières pour les machines des développeurs.

Capistrano est un excellent outil pour le déploiement distant, mais il est préférable de pouvoir installer localement sans l'utiliser. Pour cela, le monde de ruby utilise bundler et rake, outils qui ont été portés dans le monde de PHP assez récemment sous la forme de composer et phake. Nombre de tutoriels sont disponibles en ligne au sujet de capistrano, donc je vais me concentrer sur la présentation de composer et phake.

Composer

Composer est un gestionnaire de dépendances, similaire au gestionnaire de paquets de votre distro favorite (ou de vos doigts potelés si vous utilisez Windows). C'est à dire qu'il lit un fichier décrivant les dépendances du logiciel, puis télécharge les dépendances insatisfaites et cherche leurs propres dépendances et ainsi de suite. Composer se charge aussi de générer un auto-loader pour vous de manière à ne pas avoir à inclure quoi que ce soit manuellement. Le tout s'exécute avec une seule commande, ce qui rend la chose pratique.

Pour les habitués de ruby ou python, contrairement à ces langages, Composer n'installe aucune dépendance globalement, tout est installé localement dans le dossier vendor. Ce n'est certes pas extrêmement propre, mais c'est tout de même un moindre mal.

Pour l'utiliser, il suffit donc de créer un fichier JSON qui déclare les dépendances. Voici un exemple de fichier:

{
    "name": "etenil/assegai",
    "description": "A full MVC framework for PHP.",
    "homepage": "http://pikacode.com/etenil/atlatl",
    "type": "library",
    "license": "GPL-3.0+",
    "authors": [
        {
            "name": "Guillaume 'Etenil' Pasquet",
            "email": "devnull@etenil.net",
            "homepage": "http://blog.etenil.net"
        }
    ],
    "repositories": [
        {
            "type": "vcs",
            "url": "http://pikacode.com/etenil/atlatl"
        }
    ],
    "require": {
        "etenil/atlatl": "0.1",
        "gabordemooij/redbean": "3.3.6"
    },
    "autoload": {
        "files": ["lib/loader.php"]
    }
}

Le format est assez descriptif, je vais m'arrêter sur les parties juteuses.

Le bloc require définit les dépendances du paquet. Ici nous avons deux dépendances, notez le format auteur/paquet utilisé. Les versions sont également spécifiées, Composer est assez intelligent pour comprendre de nombreux formats de numérotation et permet en outre l'utilisation d'étoiles pour être plus vague (comme "3.3.*").

Par défaut, Composer recherche les paquets dans son dépôt officiel, packagist. Si ça ne suffit pas, on peut spécifier ses propres sources, et là les possibilités sont assez vastes. Composer supporte de nombreux gestionnaires de version, téléchargement direct et d'autres méthodes. Le bloc repositories contient les addresses d'autres dépôts à utiliser pour trouver des dépendances, dans l'exemple il s'agit d'un dépôt Mercurial.

Pour trouver les versions spécifiées, Composer se réfère aux tags ou noms de branches pour les gestionnaires de versions, ou bien aux noms d'archives (comme truc-0.x.x.zip) pour les paquets tout prêts.

Il suffit alors d'inclure le fichier vendor/autoload.php quelque part dans le code du projet pour bénéficier des dépendances.

Phake

Phake est un outil similaire à Rake et donc Make. Il contient des règles interdépendantes qui peuvent être invoquées en ligne de commande. Qui plus est, Phake repose intégralement sur PHP et n'a donc pas de langage dédié, donc on dispose de toutes les fonctions internes de PHP pour achever l'objectif voulu.

Néanmoins, Phake a quelques inconvénients. Notemment le manque de fonctions plus pratiques pour les opérations courantes, comme par exemple copier, déplacer, faire des liens, le tout de manière indépendante de l'OS. Ça peut se régler assez facilement, mais ce serait tout de même pratique.

Les règles sont simples à utiliser et se basent sur des fonctions lambda. Voici un exemple plus parlant:

task('truc', function () {
    echo "Ceci est un truc.";
});

task('machin', 'truc', function() {
    echo "Ceci est un machin qui dépend d'un truc.";
});

group('bidules', function() {
    task('chose', function () {
        echo "Voici une chose qui fait partie des bidules.";
    });
});

Pour exécuter la règle truc, on lancera la commande suivante:

phake truc

Et pour chose, faisant partie du groupe bidules:

phake bidules:chose

La tâche nommée default est exécutée si aucune n'est spécifiée en ligne de commande.

On voit bien ici comment utiliser les deux outils afin d'installer l'application. D'abord exécuter composer pour attraper les dépendances, puis exécuter phake pour faire du nettoyage/réglage. Les deux outils sont en PHP pur et donc marchent partout où PHP est installé, et ils permettent au script de déploiement (capistrano ou autre) de rester très simple et générique.

Vous trouverez de plus amples informations dans la documentation assez bonne des deux outils sur leurs pages respectives. Composer est un outil développé par les gens de Symfony, la maintenance est donc bien assurée. Phake a moins de visibilité mais le code bouge pas mal, et l'utilitaire reste assez simple pour le corriger soi-même.

Vus : 528
Publié par Etenil : 58