J’y pensais depuis que j’ai démarré mon activité de webdesigner, car j’utilise beaucoup Wordpress pour les sites de mes clients, j’ai enfin commencé à le faire. De quoi je parle ? D’un outil qui permette de synchroniser facilement deux installations Wordpress, une de développement et une de production.

Si vous avez la flemme de lire et voulez directement accéder au code, c’est par là.

Développer localement

En effet, il est déconseillé, car souvent dangereux, de procéder à des modifications directement sur un site en production, quel qu’il soit. Une pratique courante (par exemple avec un framework comme Django) est de développer localement (sur son ordinateur). Le site n’est alors visible que par le développeur, qui peut développer sans avoir peur de tout casser. Une fois sa session de développement terminé, il n’y a ensuite qu’a pousser (via une instruction en ligne de commande, par exemple) les modifications sur le serveur de production pour que le site public soit mis à jour instantanément et, normalement, sans casse.

Le cas Wordpress

Malheureusement, ce scénario idéal est beaucoup plus difficile à mettre en place avec Wordpress. Ce CMS a été développé avant tout pour être facile à utiliser, ce qui se fait au détriment de certaines bonnes pratiques. Notamment, l’URL d’un site Wordpress est stockée directement dans la base de données, plutôt que dans un fichier statique. Par conséquent, pour faire tourner une copie d’un site Wordpress en local, ce qui implique un changement d’URL, il faut passer par une étape systématique de rechercher-remplacer dans la base de données. Idem dans l’autre sens, pour transférer son site local en production, ou plus généralement, pour migrer son site d’une adresse à une autre.

D’autres étapes sont également indispensables (sans que l’on ait à blamer Wordpress):

  • Transférer les fichiers media d’un site à l’autre
  • Installer les mêmes thèmes
  • Installer les mêmes plugins

Développer localement avec Wordpress, en soi, n’est pas compliqué. C’est le workflow pour déployer son instance locale en production, ou pour répliquer une instance de production localement qui est désagréable, au mieux. Les procédures qui existent ici et impliquent souvent des outils payants, comme le plugin WP migrate DB pro. En plus de ça, je n’aime pas l’idée d’installer un plugin supplémentaire sur chacun de mes sites simplement pour pouvoir développer localement.

Un début de réponse : fabpress

Donc l’autre jour, j’ai pris mon courage à deux mains et j’ai commencé à coder mon propre outil, que j’ai appelé fabpress (contraction de Fabric et de Wordpress, voir plus bas). L’objectif étant d’avoir un prototype utilisable en ligne de commande, me permettant de copier en local un site en production, ou de déployer en production un site local.

J’ai terminé ce premier prototype hier, et j’ai pris du temps aujourd’hui pour rédiger la documentation et tester le machin. J’ai donc l’honneur de vous présenter la version 0.1 de fabpress, un utilitaire de migration d’instance Wordpress publié sous licence libre et écrit en Python. On est sur du prototype, donc partez du principe que ça peut pêter à tout moment.

En pratique, le bousin est basé sur deux outils assez différents mais étonemment complémentaires dans le cadre de ce projet :

  • WP-CLI : une interface en ligne de commande pour Wordpress. Si vous ne connaissez pas, allez jeter un oeil, c’est assez énorme et ça permet d’automatiser pas mal des tâches d’administration d’une installation Wordpress (installation de thèmes, de plugins, téléchargement des traductions, export/import de base de données, etc).
  • Fabric : une bibliothèque Python qui simplifie la connexion SSH et l’automatisation de nombreuses tâches d’administration système.

Dans le cadre de fabpress, Fabric prend en charge la partie ligne de commande et connexion au serveur de production. Ensuite, dans la grande majorité des cas, il transmet ses instructions à WP-CLI qui s’occupe de gérer ce qui est relatif à Wordpress (récupérer la liste des plugins installés, importer/exporter les bases de données, remplacer les permaliens, etc.).

Niveau conception, je suis assez content de moi, même s’il y a encore énormément de choses à améliorer. J’ai essayé d’écrire au maximum en orienté objet, ce qui m’a permis d’obtenir assez rapidement une structure modulaire, avec des tâches très spécifiques qui intéragissent entre elles.

Par exemple, la tache « fp.main.pull » qui sert à synchroniser complètement l’instance locale avec l’instance de production appelle la tache « fp.db.sync », chargée de synchroniser la base de données, ainsi que la tache « fp.media.sync », qui s’occupe des fichiers media. Ces tâches peuvent également en appeler d’autres, et tout ce petit monde peut être lancé de façon complétement indépendante si vous souhaitez ne synchroniser que les plugins, que les thèmes, que la base de données…

Autre point qui me semble intéressant : la possibilité d’enregistrer des hooks, c’est à dire des fonctions qui s’exécutent automatiquement lorsqu’une tâche est appelée. Typiquement, si vous développez votre propre plugin Wordpress et gérez le tout dans un dépôt git, vous pouvez rédiger en quelques lignes un hook qui serez appelé avec la tâche « plugin.sync » et s’occupera de récupérer la dernière version du plugin sur le dépôt Git.

Pour le moment, fabpress ne gère qu’un seul workflow de développement : une instance sur un serveur de développement local, et une installation sur un serveur de production. Cependant, j’aimerai rendre l’outil plus générique afin qu’il s’intègre sans douleur à d’autres workflows (un serveur de développement local, un serveur de test public et un serveur de production, par exemple).

J’ai choisi, à regret, d’héberger le dépôt sur GitHub (au lieu de mon GitLab habituel), afin de faciliter la remontée des bugs et l’intégration d’éventuelles pull-request. Si vous vous sentez d’attaque, vos contributions sont donc les bienvenues, de même que vos commentaires.

Happy coding !