Objectif(s) :
Installer une solution permettant le développement collaboratif en privilégiant le développement lui-même et non la maintenance de la solution collaborative. En d'autres termes, il s'agit de trouver et d'utiliser un système simple, efficace et souple où l'énergie reste dans le développement et non l'administration. Il faudra, de plus, que la solution puisse être facilement adaptable si le projet en vient à passer d'une poignée de développeurs à des dizaines, voire plus.
Ingrédient(s) :
Bazaar ou bzr est l'un des nombreux systèmes de gestion de versions en logiciel libre disponibles (RCS, CVS, Git, etc.). C'est un système de gestion de version décentralisée où chaque copie est un dépôt complet (historique inclus). Le développement de Bazaar est focalisé sur la simplicité et la flexibilité. Trac est un système de gestion de projets développé en Python (comme Bazaar). Il intègre notamment un wiki, une gestion de feuilles de route, un historique, un système de suivi de bugs et un explorateur Subversion.
1. Bazaar, SSH et Trac, c'est quoi ?
1.1 Bazaar (bzr), le gestionnaire de versions
Bazaar (aussi abrégé « bzr ») est un système de gestion de versions. Il se veut simple d'où la citation : « Version Control for Human Beings » qui signifie « Contrôle de version pour les êtres humains ». Il est conçu pour faciliter la collaboration des développeurs dans un projet et aussi conserver un historique de l'évolution d'un projet. Faire le choix d'un gestionnaire de versions, c'est faire le choix d'une manière de gérer le projet. En effet, il y a les systèmes centralisés (tels que CVS et SVN) et il y a les systèmes décentralisés (comme Git et Mercurial). Bazaar, quant à lui, peut faire les deux. Ceci peut donc se révéler être un avantage si, par la suite, le projet veut changer de schéma. Dans cet article, nous l'utiliserons de manière décentralisée. La branche principale du projet sera accessible en écriture seulement par quelques personnes (une seule peut suffire d'ailleurs), alors que n'importe qui aura le droit de récupérer le code. Seuls les développeurs du projet pourront, bien entendu, envoyer leurs branches de développement sur le serveur centralisant les données.
Figure 1 : Principe de Bazaar dans notre cas
1.2 Secure Shell (SSH), le gestionnaire d'authentification
Le protocole Secure Shell est connu comme étant un des moyens les plus sécurisés pour contrôler une machine à distance. C'est d'ailleurs son utilisation la plus commune. La connexion par SSH à une machine peut se faire soit à l'aide d'un mot de passe, soit en utilisant une ou plusieurs clefs. La seconde option offre l'avantage de ne pas entrer un mot de passe à chaque connexion, mais elle est surtout plus sécurisée, puisque la clé privée doit se trouver sur la machine d'où l'on se connecte. Pourquoi parler de SSH alors que l'on veut utiliser un système de gestion de versions ? En fait, Bazaar permet d'utiliser SSH comme système d'authentification. En gros, seules les personnes ayant un moyen de se connecter via SSH pourront avoir des accès spéciaux vers les branches Bazaar. Pour utiliser SSH avec Bazaar, on utilise soit des URL de type sftp://, soit des URL de type bzr+ssh://. C'est cette dernière forme que nous allons garder ici. Mais, pour cela, il faudra également se servir d'un serveur Bazaar (appelé aussi « Bazaar smart server »).
1.3 Trac, la gestion du projet par Internet
Trac est un système complet de gestion de projet. Il est développé en Python tout comme Bazaar et intègre un wiki, une gestion des feuilles de route, un historique, un outil de rapport de bug et un explorateur du code source. Trac est généralement utilisé en couple avec Subversion, mais il existe des greffons pour le faire cohabiter avec d'autres gestionnaires de versions. Dans notre cas, nous allons donc utiliser le greffon destiné à pouvoir utiliser Trac et Bazaar ensemble. Je reconnais que ce n'est pas toujours simple à prendre en main, en particulier la première fois. Mais, depuis quelque temps maintenant, seule la création du projet Trac requiert une utilisation de la ligne de commande plus ou moins difficile. Une fois le tout installé, il est possible d'administrer le système via l'interface web de Trac.
1.4 Avant de se lancer
L'installation et la configuration que nous allons réaliser n'est pas forcément la plus adaptée pour votre projet. Vous pouvez tout de même vous inspirer de cet article afin de comprendre les principes du fonctionnement de Bazaar. Cet article a été rédigé en utilisant la distribution Ubuntu Server (version 9.04 Jaunty Jackalope). Il se peut donc que les noms des paquets diffèrent d'une distribution à une autre. De plus, au début de l'installation, des dépôts PPA (hébergés grâce à Launchpad) sont utilisés. Il est donc nécessaire de vous rappeler que ce sont des dépôts non officiels et qu'il peut être dangereux de les utiliser. Cependant, ils proposent Bazaar dans sa dernière version. Rien ne vous empêche d'utiliser les dépôts officiels avec la version de Bazaar qui vous est proposée. Enfin, dernière chose : toutes les manipulations effectuées sur le serveur sont faites avec l'utilisateur root. Vous devez donc vous assurer que vous pouvez faire de même.
2. Mise en place de Bazaar, SSH et Trac
2.1 Configuration du serveur SSH
Lorsque l'on utilise une distribution pour un serveur, on a l'habitude d'installer un serveur SSH (si ce n'est pas déjà fait).
# aptitude install openssh-server
Par défaut, ce serveur va écouter sur le port 22. Il est conseillé de garder cette configuration pour coupler SSH à Bazaar. La configuration du serveur se fait via le fichier /etc/ssh/sshd_config. La configuration recommandée de base est de ne pas permettre de se connecter en root directement. Le fichier de configuration va donc contenir au moins ces quelques lignes :
...
# What ports, IPs and protocols we listen for
Port 22
...
PermitRootLogin no
...
On peut désormais configurer notre client SSH. L'authentification par clef est à la fois pratique et sécurisée. C'est donc celle qu'il faut préférer. Il faudra générer une clef sur chaque client. Pour cela, il faut exécuter la commande suivante (côté client) :
$ ssh-keygen
Il faut accepter le fichier proposé par la suite. Ce dernier est le fichier dans lequel la clef sera stockée. Pour finir, une passphrase est demandée. C'est un mot de passe. Il faut donc qu'elle reste secrète et qu'elle soit suffisamment longue et complexe. Maintenant que le client est configuré (oui, ce n'est pas très long), il faut simplement en autoriser l'accès sur le serveur. La liste des clefs publiques autorisées est stockée dans le fichier ~/.ssh/authorized_keys de l'utilisateur. Ainsi, un même utilisateur peut se connecter avec différentes clefs. La clef publique du client est stockée dans le fichier ~/.ssh/id_rsa.pub ou ~/.ssh/id_dsa.pub. Il faut alors ajouter le contenu de ce fichier dans le fichier d'autorisation du serveur. On peut le faire grâce à une clef USB ou en le recopiant à la main, mais également par SSH. Dans ce cas, il faut encore pouvoir se connecter avec l'authentification par mot de passe. On entre alors simplement la commande suivante depuis le client :
$ ssh login@serveur "echo `cat ~/.ssh/id_rsa.pub` >> .ssh/authorized_keys"
La configuration de SSH est alors terminée. Si une modification a été apportée au fichier de configuration, il est alors indispensable de redémarrer le serveur SSH.
# /etc/init.d/ssh restart
2.2 Configuration de Bazaar
2.2.1 Installation de Bazaar
L'installation de Bazaar se résume à l'installation d'un seul paquet. En effet, bzr est une commande comportant un nombre d'arguments plutôt impressionnant du fait de son architecture. La commande bzr n'est en fait pas qu'un simple programme. Elle est accompagnée d'un très grand nombre de greffons. En réalité, chaque commande commençant par bzr fait appel à un greffon. Pour installer Bazaar, on utilise donc la commande suivante :
# aptitude install bzr
Les utilisateurs de la distribution Ubuntu aimeront peut-être pouvoir profiter des évolutions de la version stable de Bazaar grâce au PPA des développeurs du gestionnaire de versions. Pour ajouter le dépôt non officiel, il faut éditer le fichier /etc/apt/sources.list avec les droits d'administrateur et ajouter les lignes qui suivent :
deb http://ppa.launchpad.net/bzr/ppa/ubuntu jaunty main
deb-src http://ppa.launchpad.net/bzr/ppa/ubuntu jaunty main
Une fois ajouté, on récupère la clef du dépôt qui sert à signer les paquets, puis on met à jour le système.
# apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 8C6C1EFD
# aptitude update
# aptitude full-upgrade
La version actuelle de Bazaar est la 2.0.0 (15 octobre 2009).
2.2.2 Le Bazaar smart server
Tout comme Subversion, par exemple, Bazaar possède un serveur qui lui est propre. C'est ce « serveur intelligent » qui permet d'utiliser le gestionnaire de versions en mode bzr+ssh://. Lancer un serveur Bazaar est plutôt simple. Une seule ligne de commande suffit.
# bzr serve --directory=/chemin/vers/la/racine/des/projets/
Malheureusement, une utilisation à la ligne de commande peut s'avérer assez ennuyeuse. On va donc par la suite se simplifier la vie. Avant tout, il faut préparer le terrain pour que tout soit prêt dès le lancement du smart serveur. Comme on peut le voir dans la commande ci-dessus, il faut créer la racine qui va contenir par la suite tous les projets. Ainsi, ces derniers seront tous accessibles via Bazaar. Ici, la racine sera /var/bzr/.
# mkdir /var/bzr/
Ensuite, on pourra lancer le serveur. Cependant, il faut être certain qu'il soit accessible via l'extérieur. La configuration du firewall est donc une étape qui (je l'espère) vous sera indispensable. Pour ceci, il faut savoir que le smart serveur utilise le port 4155 par défaut, mais qu'il est possible de le changer grâce à l'option --port=LE_PORT. Dans un script de configuration de iptables, on pourra écrire quelque chose comme ceci.
# Bazaar server
iptables -t filter -A OUTPUT -p tcp --dport 4155 -j ACCEPT
iptables -t filter -A INPUT -p tcp --dport 4155 -j ACCEPT
echo - Autoriser serveur Bazaar : [OK]
Pour simplifier les choses, il peut être intéressant de pouvoir lancer, redémarrer, vérifier le statut et arrêter le serveur Bazaar comme tout autre service. En général, on fait ceci via une commande du type :
# /etc/init.d/service start|restart|status|stop
Dans notre cas, du fait que le serveur est un greffon rattaché à Bazaar et qu'il n'est pas installé comme un serveur Apache par exemple, il faut créer un script dans le dossier /etc/init.d/. Ce script nous permettra donc de gérer notre serveur un peu plus facilement.
# touch /etc/init.d/bazaar_server
Maintenant, on édite le fichier avec un éditeur de texte (VIM, Emacs, etc.) pour y insérer le code suivant :
### BEGIN INIT INFO
# Provides: bazaar_server
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start daemon at boot time
# Description: Enable service provided by daemon.
### END INIT INFO
#!/bin/sh
# Path to root of repo tree
BZRROOT=/var/bzr/
# Listening port (default = 4155)
PORT=4155
# Logs file
LOG_FOLDER=/var/log/bzr
LOG_FILE=$LOG_FOLDER/smart_server.log
# Arguments to start the server
ARGS="serve --port=$PORT --directory=$BZRROOT"
bzr_smart_server_process() {
pgrep -fl "bzr $ARGS"
}
bzr_smart_server_status() {
process=`bzr_smart_server_process`
listening=`netstat -nl | grep -e ":$PORT "`
if [ -z "$process" ]; then
echo "Bazaar smart server is *not* running."
else
echo "Bazaar smart server is running."
if [ -z "$listening" ]; then
echo "The server is *not* listening on port $PORT."
else
echo "The server is listening on port $PORT."
fi
fi
}
bzr_smart_server_start() {
echo "Starting Bazaar smart server."
# Make sure the log folder is created
if [ ! -d $LOG_FOLDER ]; then
mkdir -p $LOG_FOLDER
fi
echo "" > $LOG_FILE
bzr $ARGS > $LOG_FILE 2>&1 &
bzr_smart_server_status
}
bzr_smart_server_stop() {
echo "Stopping Bazaar smart server."
pkill -f "bzr $ARGS"
bzr_smart_server_status
}
case "$1" in
start)
bzr_smart_server_start
;;
stop)
bzr_smart_server_stop
;;
status)
bzr_smart_server_status
;;
restart)
bzr_smart_server_stop
bzr_smart_server_start
;;
*)
echo "Usage: $0 { start | stop | status | restart }"
exit 1
;;
esac
L'en-tête du script va permettre de contrôler son exécution lors du démarrage de la machine. En effet, on va également ajouter ce script aux runlevels, afin de ne pas être obligé de le relancer à chaque redémarrage de la machine. Pour cela, il faut utiliser la commande ci-dessous :
# update-rc.d bazaar_server defaults
Les quatre variables principales du script (celles dont les noms sont en majuscules) sont éventuellement à modifier. Elles concernent la racine des projets à utiliser avec Bazaar, le port utilisé par le serveur et le fichier dans lequel seront enregistrés les logs. Maintenant, on rend le script exécutable et il est alors possible de lancer, redémarrer, arrêter le serveur et en voir le statut avec les lignes de commandes suivantes :
# chmod +x /etc/init.d/bazaar_server
# /etc/init.d/bazaar_server start
# /etc/init.d/bazaar_server restart
# /etc/init.d/bazaar_server stop
# /etc/init.d/bazaar_server status
2.2.3 Création du projet
Une fois que le serveur Bazaar est prêt, il suffit de créer un projet. Pour gérer les droits d'accès, on va utiliser un groupe et les utilisateurs ayant accès à SSH. On crée donc un groupe pour le projet.
# groupadd mon_projet
On peut désormais ajouter à ce groupe les utilisateurs qui auront un accès en écriture aux branches. Si l'utilisateur n'existe pas encore, on utilisera :
# adduser --ingroup mon_projet mon_utilisateur
Mais, s'il existe déjà, on fera :
adduser mon_utilisateur mon_projet
Il faut bien faire attention à inverser le nom du groupe et le nom de l'utilisateur d'une commande à l'autre. On peut alors créer le dossier dans lequel toutes les branches seront, pour ensuite lui modifier son propriétaire (qui sera donc le groupe précédemment créé).
# mkdir /var/bzr/mon_projet
# chown :mon_projet /var/bzr/mon_projet
Toutes les branches appartiendront au même groupe et donc tous les membres du groupe devront avoir un accès en lecture et en écriture, alors que toutes les autres personnes ne devront que pouvoir lire le contenu des branches sans pouvoir le modifier. C'est dans ce but que l'on va préciser les permissions.
# chmod ug+rwx,g+s,o+rx,o-w /var/bzr/mon_projet
Après avoir déposé la branche mainline qui est la branche principale du développement (l'équivalent de trunk avec SVN), tous les développeurs du projet pourront la modifier. Il peut être intéressant pour des raisons de contrôle strict du code validé de n'avoir qu'un seul gatekeeper et donc qu'une seule personne ayant accès en écriture à mainline. Pour cela, on peut simplement réajuster le propriétaire de cette branche (il est possible de le faire pour toutes les branches).
# chown mon_utilisateur:mon_utilisateur /var/bzr/mon_projet/mainline
Arrivé ici, il doit être possible pour tout le monde de créer une branche locale ou simplement de télécharger le code avec les commandes ci-dessous :
$ bzr branch bzr://domaine.tld/mon_projet/branche
$ bzr checkout bzr://domaine.tld/mon_projet/branche
En revanche, les développeurs du projet devraient être capables d'envoyer leurs branches et également de pusher leurs modifications sur les différentes branches avec les commandes qui suivent :
$ bzr push bzr+ssh://domaine.tld/var/bzr/mon_projet/branche
Il est très important d'indiquer le chemin complet, car c'est comme cela que SSH fonctionne (cela ne dépend pas de Bazaar).
Pour terminer sur la création du projet, il faut savoir que Bazaar fonctionne avec et sans working-tree. Une branche qui ne possède pas de working-tree ne permet pas à l'utilisateur de voir réellement les fichiers. C'est-à-dire que cette branche ne contient que les informations permettant de connaître les différences avec la branche mère. Il est toutefois possible de construire un working-tree dans une branche qui n'en a pas. Pour cela, on utilise les commandes suivantes :
$ cd /chemin/vers/branche/
$ bzr checkout .
La branche nommée mainline étant la branche mère des toutes les autres (soit par héritage, soit directement), il est impératif que celle-ci possède un working-tree. Cependant, un problème fait son apparition. En effet, l'action de push ne met pas à jour le working-tree. On peut le faire à la main en se connectant en SSH sur la machine, puis en exécutant la commande de mise à jour dans la branche.
$ bzr update
Ou alors, on peut utiliser, pour plus de simplicité, le greffon push-and-update. En réalité, ce dernier ne fait qu'exécuter à la suite les commandes de push et d'update, à savoir :
$ bzr push bzr+ssh://domaine.tld/var/bzr/mon_projet/branche
$ ssh domaine.tld bzr update /var/bzr/mon_projet/branche
2.3 Configuration de Trac
Par défaut, Trac ne gère pas le gestionnaire de versions Bazaar. Cependant, il existe un greffon qui permet de l'utiliser avec. De plus, dans notre cas, nous allons voir comment utiliser Trac au travers d’Apache pour ne pas avoir à lancer le démon tracd. Cela va nous permettre d'accéder à Trac comme l'on peut le faire avec une simple page web. Pour commencer, on installe donc Trac, Apache (si ce n'est pas déjà fait), et le greffon qui va bien :
# aptitude install trac trac-bzr trac-spamfilter apache2 libapache2-mod-python
Le paquet trac-bzr correspond au greffon Bazaar, trac-spamfilter lui permet d'éviter les spams sur les rapports de bug et libapache2-mod-python va nous être utile pour accéder à Trac via Apache. À présent, il faut créer un dossier qui va contenir toutes les instances de Trac pour que l'on puisse créer une instance par projet.
# mkdir /var/trac
On peut alors initialiser notre première instance pour notre projet Bazaar.
# trac-admin /var/trac/mon_projet initenv
Une suite de questions est posée. Il faut y répondre correctement pour indiquer le chemin du projet, le type de gestionnaire de versions utilisé, etc. Voici, un exemple (coupé) de ce qui doit s'afficher dans le terminal.
# Le nom du projet
Project Name [My Project]> Mon Projet
# Valider sans rien répondre
Database connection string [sqlite:db/trac.db]>
# Entrer "bzr" pour Bazaar
Repository type [svn]> bzr
# Chemin vers la racine des branches du dépôt
Path to repository [/path/to/repos]> /var/bzr/mon_projet
Après ceci, notre instance de Trac n'est ni fonctionnelle, ni accessible. En effet, il faut d'abord activer les greffons installés afin que Trac puisse prendre en compte notre projet Bazaar. Pour cela, on édite le fichier /var/trac/mon_projet/conf/trac.ini et on y ajoute, à la fin, les lignes suivantes :
[components]
tracbzr.* = enabled
tracspamfilter.* = enabled
Pour prendre en compte cette nouvelle configuration, il faut mettre à jour notre instance de Trac.
# trac-admin /var/trac/mon_projet upgrade
À ce stade, l'instance est fonctionnelle, mais pas encore accessible avec un navigateur web. De plus, aucun compte n'a été créé et donc Trac ne peut savoir si le visiteur est un administrateur, un développeur ou une personne anonyme. Pour y remédier, on va créer un fichier qui va contenir toutes les personnes autorisées à se connecter sur l'instance de Trac.
# htpasswd -c /var/trac/mon_projet/trac.htpasswd mon_utilisateur
L'option -c permet de créer le fichier. Après avoir validé, le mot de passe de l'utilisateur sera demandé. Il suffit de l'entrer et l'utilisateur sera ajouté. Pour en ajouter un autre par la suite, il faut bien veiller à ne pas utiliser l'option -c. Trac a sa propre gestion des groupes et des utilisateurs. La liste des utilisateurs de Trac est enregistrée dans le fichier /var/trac/mon_projet/trac.htpasswd que nous avons créé précédemment. Pour davantage de sécurité, il est conseillé de retirer certaines permissions aux personnes non enregistrées et non connectées. Les anonymes ne doivent pas pouvoir modifier le wiki, ni modifier les tickets déjà créés.
# trac-admin /var/trac/mon_projet permission remove anonymous WIKI_CREATE WIKI_MODIFY TICKET_MODIFY
En revanche, les développeurs du projet doivent être capables de faire de telles choses. On crée donc un groupe developer avec les droits d'édition et on y ajoute les bonnes personnes.
# trac-admin /var/trac/mon_projet permission add developer WIKI_CREATE WIKI_MODIFY TICKET_MODIFY
# trac-admin /var/trac/mon_projet permission add mon_utilisateur developer
Enfin, le mainteneur de projet se verra obtenir tous les droits sur Trac, y compris les droits qui lui permettront d'administrer le système pour modifier les types de rapport de bug, les feuilles de route et bien d'autres choses.
# trac-admin /var/trac/mon_projet permission add mon_utilisateur TRAC_ADMIN
Une fois que l'instance de Trac sera mise en ligne, les personnes enregistrées auparavant pourront se connecter et celles désignées en tant qu'administrateurs auront accès au bouton mod python. On commence donc par s'assurer qu'il est actif.
pour configurer Trac plus facilement. Maintenant, la tâche consiste à utiliser Apache pour pouvoir accéder à Trac depuis n'importe où. Pour cela, on va utiliser le# a2enmod python
Ensuite, on crée un nouveau site qui va pointer vers notre instance de Trac et qui va utiliser le bon fichier pour pouvoir se connecter avec un utilisateur enregistré. On crée et édite alors un fichier nommé /etc/apache2/sites-available/mon_projet et on y met le code suivant :
<Location /mon_projet>
SetHandler mod_python
SetHandler mod_python
PythonHandler trac.web.modpython_frontend
PythonInterpreter main
PythonOption TracEnv /var/trac/mon_projet
PythonOption TracUriRoot /mon_projet
SetEnv PYTHON_EGG_CACHE /tmp
</Location>
<Location /mon_projet/login>
AuthType Basic
AuthName "mon_projet login"
AuthUserFile /var/trac/mon_projet/trac.htpasswd
Require valid-user
</Location>
Il faut également penser à donner l'accès à Apache pour qu'il puisse accéder au contenu du projet Trac.
# chown -R www-data:www-data /var/trac/mon_projet/
Pour finir, on active le nouveau site, puis on recharge la configuration d’Apache pour le prendre en compte.
# a2ensite mon_projet
# /etc/init.d/apache2 reload
Suite à ces deux dernières commandes, l'instance de Trac doit être accessible à l'adresse http://domaine.tld/mon_projet/. Il ne reste plus qu'à se connecter et à configurer le Trac fraîchement installé de manière plus précise et complète.
Conclusion
Comme nous avons pu le constater, la configuration d'un trio Bazaar/SSH/Trac n'est pas forcément des plus simples, surtout pour des débutants. Cependant, cela vaut la peine de le faire dans le but de mener son projet correctement le plus longtemps possible. Bazaar offre une très bonne alternative à tous les autres gestionnaires de versions grâce à sa polyvalence. Le coupler avec SSH lui apporte un aspect sécurité, alors que Trac lui apportera la convivialité et la facilité de gestion du projet. De plus, sa mise en valeur, notamment grâce à la documentation, l'aspect du développement, ainsi que la connaissance des objectifs, vous permettront d'attirer le public et donc des contributeurs potentiels. Il existe bien entendu de nombreuses autres combinaisons. Certains préféreront SVN, Git ou encore Mercurial. L'essentiel reste tout de même de faire quelque chose de cohérent et fonctionnel. Les outils importent moins, mais, pour ma part, Bazaar, SSH et Trac semblent être une combinaison de force.
Sources
- http://trac.edgewall.org/wiki/TracOnDebian
- http://trac.edgewall.org/wiki/SpamFilter
- http://doc.bazaar-vcs.org/plugins/en/push_and_update-plugin.html
- http://blog.michaelgreenly.com/2008/01/setting-up-shared-bazaar-repository.html
Merci à Andrew Cowie (mainteneur de java-gnome) pour ses nombreux conseils.