Développement web collaboratif

On me demande souvent comment j’organise le développement web dans mon entreprise : comment on arrive à coder à plusieurs sur le même fichier sans se marcher sur les pieds, comment on archive les versions, comment on effectue les livraisons en production, etc. Il est vrai que le développement web collaboratif est souvent mal organisé, et il est courant d’avoir comme seul outil un simple dossier partagé…

Contraintes liées au développement web collaboratif

Contrairement à un projet classique qui ne nécessite “que” un compilateur et des bibliothèques, une application web est une association complexe de plusieurs composants logiciels dont les versions et les configurations très variables peuvent influer sur le bon fonctionnement de l’application :

  • un serveur web (vhost, htaccess, mod_rewrite, etc.),
  • l’interpréteur php (options de php.ini, modules supplémentaires comme pdo, gettext, etc.),
  • le sgbd (configuration des users, etc.).

Donc la solution “classique” d’avoir un poste de développement par développeur est ici difficile à maintenir : il faudrait installer tous ces logiciels sur chaque poste et surtout veiller à avoir une configuration identique partout. Et ça se complique dès qu’il faut faire une mise à jour de la config…

Une autre solution serait d’avoir un serveur de dev unique (pour éviter les problèmes de maintenance évoqués ci-avant), et de travailler directement dessus via des partages de fichiers (Samba, NFS, etc.). Or cette solution pose plusieurs problèmes :

  • en cas d’accès concurrents à un fichier : le risque est grand de voir ses modifications écrasées par un autre développeur ;
  • en cas de modifications lourdes (exemple : un refactoring de la base) : les autres développeurs sont bloqués ;
  • impossible d’utiliser correctement le svn : il n’y a qu’une seule version des fichiers et on ne sait pas qui l’a modifiée.

Nous avons donc créée une solution intermédiaire : un serveur de dev unique (pour une maintenance facile), qui fournit des serveurs virtuels pour chaque développeur (pour une bonne séparation des données et une utilisation optimale de svn).

Le serveur de dev fonctionne avec Debian GNU/Linux, les postes clients avec Windows XP.

Plateforme technique

Compte sur le serveur

Chaque développeur dispose d’un compte uniquement sur le serveur de dev, qui lui permet de se connecter dessus en SSH (bien utile pour tester des tâches en ligne de commande tel que des scripts de maintenance). De plus, tous les développeurs appartiennent au même groupe (www) et les permissions sont par défaut en rw pour le groupe.

Partage Windows : Samba

Grace à Samba, chaque développeur dispose d’un partage windows identifié par son login. Le partage est également accessible en local sur la machine, dans son home.

Vhost Apache

Pour chaque dossier créé dans le partage, il existe un vhost permettant d’y accéder, sous la forme http://login.dossier.dev.bso.

Exemple, je crée le dossier monboprojet dans mon partage monbologin. L’URL est : http://monbologin.monboprojet.dev.bso

Pour les projets dont le documentRoot n’est pas à la racine (c’est à dire à peut près tous les projets sur svn, puisque la racine contient seulement trunk/, branches/ et tags/), il vaut mieux les mettre dans un répertoire suffixé par “-src” et faire un lien symbolique. Par exemple :

$ svn checkout http://mon.beau.svn/monboprojet monboprojet-src
$ ln -s monboprojet-src/trunk/htdocs monboprojet

BDD Mysql

Il n’y a qu’un seul serveur MySQL. Chaque développeur peut disposer de son propre compte et de ses propres bases. Cependant, pour des raisons pratiques, on utilise la plupart du temps les mêmes bases. Un développeur ne va utiliser des bases à part que s’il a besoin de faire des opérations lourdes (genre modifier la structure d’un ensemble de tables) qui bloqueraient tout le monde le temps que le code mis à jour soit commit.

Coordination du développement

SVN

Un serveur Subversion (SVN) est utilisé pour gérer les sources. Le serveur svn est sur une machine différente du serveur de dev ce qui permet de sécuriser les données (en cas de crash de la machine de dev, on peut récupérer les dépots ; en cas de crash de la machine svn, on a toujours les versions locales).

Les dépots sont organisés de la manière classique avec 3 repertoires :

  • branches/
  • trunk/
  • tags/

Un commit ne doit pas casser le dépôt. C’est à dire qu’un développeur qui ferait un update doit pouvoir continuer à utiliser l’application sans être bloqué par un bug, une fonctionnalité manquante, ou autre. Il est tout à fait possible de faire un commit d’une feature non terminée, à partir du moment où le reste de l’application n’est pas impacté.

Fichiers de config

On ne commit jamais un fichier de config. En effet, d’une part un fichier de configuration est spécifique à un environnement (options de mise en cache, url, etc.) et d’autre part un fichier de configuration contient des logins et des mots de passes spécifiques.

On commit donc des modèles de fichiers de configuration, dont le nom se termine par .orig. Chaque développeur doit créer ses propres fichiers à partir des modèles. Quand on voit passer un “.orig” dans les logs d’update, on sait qu’il faut mettre à jour ce fichier. Cela est valable également pour les livraisons.

SQL

Pour permettre les livraisons (en préprod et en prod), à chaque modification de la base un fichier sql contenant les requêtes de mise à jour (alter, etc.) doit être écrit par le développeur. Pour éviter d’en avoir trop à gérer, il est intéressant de créer un fichier de mise à jour sql par version que l’on a prévu de livrer (upgrade_1.0.sql, upgrade_1.1.sql, etc.)

Livraison

Pour livrer, un développeur (en général le responsable du projet) utilise rsync depuis sa copie locale sur la machine de dev pour synchroniser les sources avec la préprod ou la prod. Puis il se connecte en SSH pour executer les scripts d’upgrade sql (d’où l’interet de les avoir écrit au fur et à mesure) et mettre à jour les fichiers de config.

Une option interessante de rsync est --exclude-from=nom_de_fichier, qui permet d’exclure du rsync tous les fichiers ou les répertoires qui matchent les noms présents dans nom_de_fichier. Très pratique pour éviter de livrer les fichiers inutiles (.svn, .mo, …) et éviter d’écraser les fichiers de config… Exemple de fichier d’exclusion :

.svn
rsync*
doc*
config/*
Thumbs.db
*.mo

Post a comment.