<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.3">Jekyll</generator><link href="blog.luxifer.fr/atom.xml" rel="self" type="application/atom+xml" /><link href="blog.luxifer.fr/" rel="alternate" type="text/html" /><updated>2023-09-01T12:29:52+00:00</updated><id>blog.luxifer.fr/atom.xml</id><title type="html">Blog de Florent Viel</title><subtitle>Blog centré sur le développement php et symfony2</subtitle><author><name>Florent Viel</name><email>florent.viel69@gmail.com</email><uri>https://plus.google.com/+FlorentViel</uri></author><entry><title type="html">Déploiement avec Go et Ansible dans Docker</title><link href="blog.luxifer.fr/2016/04/04/deploiement-avec-go-et-ansible-dans-docker/" rel="alternate" type="text/html" title="Déploiement avec Go et Ansible dans Docker" /><published>2016-04-04T00:00:00+00:00</published><updated>2016-04-04T00:00:00+00:00</updated><id>blog.luxifer.fr/2016/04/04/deploiement-avec-go-et-ansible-dans-docker</id><content type="html" xml:base="blog.luxifer.fr/2016/04/04/deploiement-avec-go-et-ansible-dans-docker/">&lt;p&gt;La semaine dernière je me suis mis en tête de développer une application afin de centraliser tous les déploiements qu’on fait à &lt;a href=&quot;https://www.xotelia.com&quot;&gt;Xotelia&lt;/a&gt;. J’ai fait le tour et il existe en SaaS ou en Open source des solutions pour ça. Je n’en ai pas trouvé qui fonctionne avec ansible (bien que lors d’un déploiement on puisse installer ce qu’on veut), ou alors trop cher. De plus on ne déploie pas chaque branche, seulement &lt;em&gt;master&lt;/em&gt; ou une feature-branch qu’on veut tester sur un environnement différent de la production. C’est la que j’ai décidé de développer notre propre outil de déploiement. À savoir que sur chacun de nos projets nous avons un playbook ansible de déploiement, mais que jusqu’à maintenant on les lance sur nos propres machines. Il me fallait aussi un outil qui me permette de lancer une commande dans hipchat pour déclencher un déploiement.&lt;/p&gt;

&lt;p&gt;Étant un grand fan de &lt;a href=&quot;/2015/03/13/pourquoi-choisir-go/&quot;&gt;go&lt;/a&gt; et de docker je me suis dit que ça serait pas mal de pouvoir lancer un container docker, dans lequel je lance ansible, et avoir par dessus un petit frontent avec un flux des logs.&lt;/p&gt;

&lt;p&gt;J’ai donc commencé a chercher un client docker en go et je suis tombé sur &lt;a href=&quot;https://github.com/docker/engine-api&quot;&gt;celui-la&lt;/a&gt;. Il me semblait qu’il n’y en avait pas à part dans le core de docker ou alors développé par des tiers, mais je me suis trompé. Et qui plus est, très bien documenté et &lt;em&gt;idiomatic&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Pour le stockage des résultats des builds je me suis tourné vers &lt;a href=&quot;https://www.rethinkdb.com/&quot;&gt;RethinkDB&lt;/a&gt;. Une base de données NoSQL.&lt;/p&gt;

&lt;p&gt;Le principe de fonctionnement est simple, quand je reçois un événement de déploiement depuis github, je crée un container à partir d’une image qui contient ansible. Dans ce container je clone le dépôt à déployer et je lance le playbook ansible. Je notifie github et hipchat de l’état du déploiement via leurs API respective. Une fois le déploiement terminé je supprime le container.&lt;/p&gt;

&lt;h2 id=&quot;les-embûches&quot;&gt;Les embûches&lt;/h2&gt;

&lt;p&gt;Je suis tombé sur plusieurs problèmes lors du développement de ce projet. Tout d’abord il faut savoir que quand dans la console on lance &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker run&lt;/code&gt; en fait en interne docker va faire un &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;create&lt;/code&gt; puis un &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;start&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ensuite il faut que depuis ce container je puisse me connecter en ssh sur les serveurs sur lesquels je vais déployer mes projets, et que je puisse aussi cloner les projets que je vais déployer. Pour ce faire je passe en &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bind&lt;/code&gt; la clé SSH de l’hôte sur lequel est installé &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deployer&lt;/code&gt; vers le root du container comme ceci :&lt;/p&gt;

&lt;div class=&quot;language-go highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;github.com/docker/engine-api/types/container&quot;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;hostConfig&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HostConfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Binds&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/home/deployer/.ssh/id_rsa:/root/.ssh/id_rsa&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Je crée donc mon container avec cette configuration, et je le lance. Comme je ne m’attache pas a celui-ci, tout se passe en background. Donc il faut que j’attende la fin de l’exécution pour récupérer l’exit code.&lt;/p&gt;

&lt;div class=&quot;language-go highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;exitCode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;err&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dockerClient&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ContainerWait&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Je fais beaucoup d’appels à l’API docker dans la même fonction et donc beaucoup d’erreur à gérer. Comme go permet de retourner plusieurs éléments par fonction, à chaque fois que j’ai une erreur, je la remonte. Il me faut donc un moyen pour arrêter le container en cours à la moindre erreur pour ne pas laisser de déchêts sur la route. C’est la qu’intervient le mot-clé &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;defer&lt;/code&gt;. Ce mot-clé permet de définir un comportement qui sera exécuté juste avant le retour d’une fonction. Très pratique pour fermer un fichier ou un &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;io.Reader&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On arrive à la partie la plus intéressante, que j’ai fais en deux fois. La récupération des logs du container une fois l’exécution terminée.&lt;/p&gt;

&lt;div class=&quot;language-go highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;github.com/docker/engine-api/types&quot;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;logOpts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;types&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ContainerLogsOptions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ContainerID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ShowStdout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;  &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ShowStderr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;  &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Follow&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;      &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Ce qui a été exécuté dans le container a peut–être écrit dans la sortie standard ou la sortie d’erreur. Il faut donc que je récupère les deux. C’est la que je suis tombé sur une partir qui manque de documentation. Quand on demande à l’API docker les logs d’un container avec les deux sorties, docker va les multiplexer pour les mettre dans le même &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;io.Reader&lt;/code&gt;. Et pour savoir sur quelle sortie correspond quelle ligne, docker va rajouter un header à chaque ligne pour indiquer si ça correspond a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stdin&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stdout&lt;/code&gt; ou &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stderr&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Il faut donc je de démultiplexe ce que me renvoit docker pour avoir un résultat lisible. En fouyant un peu sur github et google, je suis tombé sur ce &lt;a href=&quot;https://godoc.org/github.com/docker/docker/pkg/stdcopy&quot;&gt;petit package&lt;/a&gt; dans le projet docker. et en particulier la fonction &lt;a href=&quot;https://godoc.org/github.com/docker/docker/pkg/stdcopy#StdCopy&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StdCopy&lt;/code&gt;&lt;/a&gt;. Cette fonction permet de démultiplexer une source (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;io.Reader&lt;/code&gt;) et d’écrire &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stdout&lt;/code&gt; et &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stderr&lt;/code&gt; vers deux &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;io.Writer&lt;/code&gt; distinct.&lt;/p&gt;

&lt;p&gt;Et voilà le tour est joué, j’ai mes logs propre pour chaque déploiement. Sauf que les problèmes ne s’arrêtent pas là. J’ai voulu rajouter de la couleur dans ces logs. Car la commande ansible écrit sur &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stdout&lt;/code&gt; avec différentes couleurs. Pour ce faire il faut que le terminal utilisé supporte la couleur. Il suffit de rajouter &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ENV TERM xterm&lt;/code&gt; dans le &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dockerfile&lt;/code&gt; du container et ansible va pouvoir afficher de la couleur. Mais ce n’est pas tout, il faut aussi dire à docker d’utiliser un pseudo terminal (PTY) pour le container sinon cette variable d’environnement ne servira a rien. Pour ça il faut modifier la configuration utilisée pour créer le container :&lt;/p&gt;

&lt;div class=&quot;language-go highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;github.com/docker/engine-api/types/container&quot;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Tty&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;       &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;OpenStdin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Mais voilà, en rajoutant cette configuration, quand on récuère les logs, docker ne va pas multiplexer les sorties &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stdout&lt;/code&gt; et &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stderr&lt;/code&gt; mais va renvoyer la sortie brut du pseudo terminal. Donc il ne faut plus utiliser &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stdcopy.StdCopy&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Comme je l’ai dit plus haut, je voulais avoir une page pour suivre le déploiement et afficher le flux des logs. J’avais deux possibilités pour ça, soit utiliser les &lt;a href=&quot;https://developer.mozilla.org/fr/docs/WebSockets&quot;&gt;Websocket&lt;/a&gt; ou &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events&quot;&gt;Server-sent event&lt;/a&gt;. Le premier est en full duplexe, c’est à dire que le serveur et le client peuvent écrire dedans. Le deuxième est dans un sens seulement, le serveur envoi des messages au client. Je suis parti sur Server-sent event, car je n’ai pas besoin que le client (la page web) envoi de message au serveur.&lt;/p&gt;

&lt;p&gt;Côté serveur, j’utilise un petit &lt;a href=&quot;https://godoc.org/github.com/manucorporat/sse&quot;&gt;package&lt;/a&gt; go qui me permet de créer les événements. Ensuite, pour que dans mon handler du flux je puisse renvoyer les logs sous la forme d’événements j’ai créé une &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;struct&lt;/code&gt; qui contient un &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http.ResponseWriter&lt;/code&gt; et la quantité de data envoyée. Avec cette &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;struct&lt;/code&gt; j’implémente l’interface &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;io.Writer&lt;/code&gt;. Je me suis inspiré de ce que j’ai trouvé dans le projet &lt;a href=&quot;https://github.com/drone/drone&quot;&gt;drone&lt;/a&gt; :&lt;/p&gt;

&lt;div class=&quot;language-go highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;http&quot;&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;strconv&quot;&lt;/span&gt;

    &lt;span class=&quot;s&quot;&gt;&quot;github.com/manucorporat/sse&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;StreamWriter&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;writer&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ResponseWriter&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;  &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StreamWriter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;err&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;writer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;strconv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Itoa&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Event&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;message&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;  &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;writer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Flusher&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Flush&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;// ne pas oublier de flush le ResponseWriter à chaque message pour que le serveur envoi l'événement au client.&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;err&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Il ne me reste plus qu’a copier le &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;io.Reader&lt;/code&gt; que me renvoi docker pour les logs dans cet &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;io.Writer&lt;/code&gt;. Ne pas oublier de définir le &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Content-Type&lt;/code&gt; à &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;text/event-stream&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-go highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;http&quot;&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;io&quot;&lt;/span&gt;

    &lt;span class=&quot;s&quot;&gt;&quot;github.com/manucorporat/sse&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;streamHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ResponseWriter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;req&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Content-Type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ContentType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;reader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dockerClient&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ContainerLogs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logOpts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;writer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StreamWriter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;io&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Copy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;writer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Je peux donc récupérer ces événements depuis la page du déploiement et les afficher.&lt;/p&gt;

&lt;h2 id=&quot;résultat-final&quot;&gt;Résultat final&lt;/h2&gt;

&lt;p&gt;J’ai donc maintenant une application qui reçoit les événements de déploiement de github et qui lance le déploiement dans un container docker. Je peux suivre le tout dans une joli page web. Ainsi est né &lt;a href=&quot;https://github.com/Xotelia/deployer&quot;&gt;Deployer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;La suite du projet ? Avoir une meilleure gestion des releases, savoir qui a déployer quoi à quel moment, un historique des commits déployés, une intégration avec une application github oauth pour simplifier l’ajout de projet à déployer, une sécurisation du webhook github avec un secret, etc. La liste est longue.&lt;/p&gt;</content><author><name>Florent Viel</name><email>florent.viel69@gmail.com</email><uri>https://plus.google.com/+FlorentViel</uri></author><category term="golang" /><category term="docker" /><category term="ansible" /><summary type="html">La semaine dernière je me suis mis en tête de développer une application afin de centraliser tous les déploiements qu’on fait à Xotelia. J’ai fait le tour et il existe en SaaS ou en Open source des solutions pour ça. Je n’en ai pas trouvé qui fonctionne avec ansible (bien que lors d’un déploiement on puisse installer ce qu’on veut), ou alors trop cher. De plus on ne déploie pas chaque branche, seulement master ou une feature-branch qu’on veut tester sur un environnement différent de la production. C’est la que j’ai décidé de développer notre propre outil de déploiement. À savoir que sur chacun de nos projets nous avons un playbook ansible de déploiement, mais que jusqu’à maintenant on les lance sur nos propres machines. Il me fallait aussi un outil qui me permette de lancer une commande dans hipchat pour déclencher un déploiement.</summary></entry><entry><title type="html">Les bonnes pratiques de développement - partie 2</title><link href="blog.luxifer.fr/2015/03/27/bonnes-pratiques-de-developpement-partie-2/" rel="alternate" type="text/html" title="Les bonnes pratiques de développement - partie 2" /><published>2015-03-27T00:00:00+00:00</published><updated>2015-03-27T00:00:00+00:00</updated><id>blog.luxifer.fr/2015/03/27/bonnes-pratiques-de-developpement-partie-2</id><content type="html" xml:base="blog.luxifer.fr/2015/03/27/bonnes-pratiques-de-developpement-partie-2/">&lt;p&gt;Parties : [&lt;a href=&quot;/2015/03/20/bonnes-pratiques-de-developpement-partie-1/&quot;&gt;1&lt;/a&gt;][2]&lt;/p&gt;

&lt;p&gt;Dans la première partie de ce sujet j’ai plus parlé du côté humain dans le développement, aujourd’hui on va rentrer dans le code et savoir ce qu’il faut faire pour qu’un projet dure sans devenir &lt;em&gt;legacy&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&quot;disclaimer&quot;&gt;Disclaimer&lt;/h2&gt;

&lt;p&gt;Tout ce que je vais écrire dans cette série d’article reflète uniquement ma propre opinion.&lt;/p&gt;

&lt;h2 id=&quot;gestion-des-dépendances&quot;&gt;Gestion des dépendances&lt;/h2&gt;

&lt;p&gt;Le plus important dans un projet, et surtout en équipe, c’est la gestion des dépendances, non seulement applicative, mais aussi logicielle, et même matérielle (au moins virtuelle) quand c’est possible.&lt;/p&gt;

&lt;p&gt;Les dépendances applicatives c’est quoi ? Ce sont les &lt;em&gt;vendors&lt;/em&gt; de son application. Typiquement définie dans ton &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;composer.json&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Gemfile&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;requirements.txt&lt;/code&gt;, etc. Garder la même version de ces dépendances sur tous les postes de tous les développeurs est assez simple. A peu près chaque système de gestion de dépendance stocke dans le répertoire du projet un fichier dans lequel il indique toutes les versions de tous les &lt;em&gt;vendors&lt;/em&gt; installés. Avec &lt;em&gt;composer&lt;/em&gt; c’est le fichier &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;composer.lock&lt;/code&gt;. Très important de le versionner, ainsi les vendors seront les même en dev, &lt;em&gt;CI&lt;/em&gt;, stagging, prod, etc.&lt;/p&gt;

&lt;p&gt;Les dépendances logicielles c’est quoi ? Ce sont les logiciels nécessaires pour faire tourner son application. Pour une application &lt;em&gt;Symfony&lt;/em&gt; il s’agit d’un Nginx, de PHP et sûrement de MySQL. Alors en équipe ou même tout seul, je déconseille fortement d’installer manuellement ces dépendances. Car on va se retrouver avec une version de nginx en local, une autre en CI et encore une autre en prod. C’est le meilleur moyen de laisser passer des erreurs pour les voir seulement en prod, trop tard… Ce que je conseille plutôt c’est d’utiliser &lt;a href=&quot;https://www.vagrantup.com/&quot;&gt;vagrant&lt;/a&gt; ou encore mieux &lt;a href=&quot;https://www.docker.com/&quot;&gt;docker&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Vagrant par exemple, permet de créer une machine virtuelle, de dire comment la provisionner, c’est à dire qu’est-ce qu’il faut installer dessus, et ensuite de pouvoir partager cette machine virtuelle entre tous les collaborateurs du projet. Comme ça tout le monde à la même version des mêmes logiciels d’installés.&lt;/p&gt;

&lt;p&gt;Ensuite Docker. Ça peut être un meilleur choix si tout le monde est sous linux. Car en plus de pouvoir utiliser les mêmes images en dev, ces images pourront servir en &lt;em&gt;CI&lt;/em&gt; et pourquoi pas en prod. Je dis sous linux seulement car actuellement, sous mac ou windows, la seule façon d’utiliser docker est de passer par &lt;a href=&quot;http://boot2docker.io/&quot;&gt;boot2docker&lt;/a&gt; et il y a certains problèmes au niveau du partage de fichiers entre l’hôte et la machine virtuelle qui contient docker, voir &lt;a href=&quot;https://github.com/boot2docker/boot2docker/issues/581&quot;&gt;ici&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Revenons à vagrant, ça règle les problèmes de la dev, mais pas de la prod ni de la &lt;em&gt;CI&lt;/em&gt;. C’est à dire qu’il nous faut encore installer manuellement nos dépendances logicielle. Il existe des solutions pour ça comme &lt;a href=&quot;http://www.ansible.com/home&quot;&gt;ansible&lt;/a&gt;. Un peu comme Chef ou Puppet, ces solutions permettent de transposer en code la façon d’installer ses dépendances, et donc de pouvoir versionner tout ça. Ainsi, on peut utiliser ces &lt;em&gt;recettes&lt;/em&gt; pour notre vagrant, mais aussi en &lt;em&gt;CI&lt;/em&gt; et en prod. Comme ça on est à peu près sûr de pouvoir reproduire un bug de prod en local.&lt;/p&gt;

&lt;p&gt;Les dépendances matérielles c’est quoi ? C’est le matériel qu’on utilise pour développer, faire tourner sa prod, etc. Autant que possible, si plusieurs personnes travaillent sur un même projet, qu’elles aient le même matériel (un MacBook Pro 13” Retina c’est parfait :D). Après si on utilise vagrant ça limite la casse de ce côté là car on émule les ressources, elles seront donc les mêmes pour tout le monde dans la machine virtuelle.&lt;/p&gt;

&lt;p&gt;En prod on utilise forcément pas le même matériel, par contre on peut essayer d’avoir une architecture similaire à la prod en dev. Je dis bien similaire car si on a 50 frontaux avec du load balancing, 10 MySQL et 20 Redis, ça va être compliqué d’avoir la même chose sur sa seule machine de dev.&lt;/p&gt;

&lt;h2 id=&quot;tests&quot;&gt;Tests&lt;/h2&gt;

&lt;p&gt;On attaque une grosse partie, les tests. Alors je ne suis pas un fou furieux du TDD ou BDD, mais j’essaye d’utiliser les deux en fonction du besoin. Actuellement, je travaille sur Xotelia. À l’origine c’est un gros projet monolithique basé sur un framework maison. Autant dire que se mettre à faire du TDD la dedans c’était du suicide. Par contre le BDD s’y prête bien. Au fur et à mesure de l’apprentissage du projet j’ai pu mettre en place quelques briques de BDD pour valider certaines fonctionnalités, à commencer par le login.&lt;/p&gt;

&lt;p&gt;C’est grâce à cet effort de fond que j’ai pu transformer ce lourd framework maison et hybride Symfony. Qui est devenu beaucoup agréable pour développer et avoir des bons retours d’erreurs.&lt;/p&gt;

&lt;p&gt;Tout ça pour dire que l’utilisation du TDD ou du BDD se fait au jugement. Il ne faut pas foncer tête baissée. Comme cité plus haut, pour le cas d’un projet &lt;em&gt;legacy&lt;/em&gt;, le TDD est exclu. Trop complexe à mettre en place et à maintenir, pour au final quel gain ? Au contraire sur un nouveau projet, le TDD s’avère très utile. À bon escient, il permet de développer de manière moins couplée, de valider le fonctionnement de ses classes, etc. Par contre il n’est pas nécessaire de faire du TDD pour &lt;strong&gt;tout&lt;/strong&gt;. Inutile de tester un &lt;em&gt;controller&lt;/em&gt; Symfony, c’est déjà fait au niveau du framework. De plus la logique métier ne doit pas se situer dans le &lt;em&gt;controller&lt;/em&gt; (dans le meilleur des mondes).&lt;/p&gt;

&lt;p&gt;Ensuite pour une API &lt;em&gt;rest&lt;/em&gt; par exemple, pas besoin non plus de faire de TDD. Seul ce qui importe dans une API c’est son interface, qu’elle soit consistante et une fois déployée en prod, qu’elle ne change pas. Donc peut importe le mécanisme derrière une API ce qu’il faut valider c’est la sortie. Et là une fois de plus le BDD s’y prête à merveille.&lt;/p&gt;

&lt;p&gt;Je recommande de lire &lt;a href=&quot;http://everzet.com/post/107204911916/economy-of-tests&quot;&gt;cet article&lt;/a&gt; pour un point de vue plus détaillé sur les tests.&lt;/p&gt;

&lt;h2 id=&quot;code-review&quot;&gt;Code review&lt;/h2&gt;

&lt;p&gt;Quand on travaille en équipe on ne peut pas se permettre de &lt;em&gt;pusher&lt;/em&gt; directement sur le master les yeux fermés. On risque d’introduire des bugs, d’avoir oublié des choses, il va être difficile de revenir en arrière, etc. Il vaut mieux dans ce cas utiliser le système de &lt;em&gt;Pull Request&lt;/em&gt; de GitHub, ou les &lt;em&gt;Merge Request&lt;/em&gt; de Bitbucket. Voire pourquoi pas se coupler à un vrai système de code review comme &lt;a href=&quot;https://code.google.com/p/gerrit/&quot;&gt;gerrit&lt;/a&gt;, pas très sexy mais très puissant.&lt;/p&gt;

&lt;p&gt;Il est très important de faire relire son code par au moins une autre personne. Ça permet de détecter les oublis de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;;&lt;/code&gt;, un développement manquant, une autre façon de faire les choses, etc. Couplé à un système de branche, on se retrouve avec un historique clair, on peut savoir quelles features ont été &lt;em&gt;mergées&lt;/em&gt; a quel moment et on peut facilement revenir en arrière si besoin.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;J’espère que vous pratiquez déjà tout ça. Si non il est temps de s’y mettre. n’hésitez pas à me donner vos impressions et vos bonne pratiques dans les commentaires. J’en intégrerai peut-être certaines à cet article.&lt;/p&gt;</content><author><name>Florent Viel</name><email>florent.viel69@gmail.com</email><uri>https://plus.google.com/+FlorentViel</uri></author><category term="dev" /><category term="développement" /><category term="équipe" /><category term="team" /><summary type="html">Parties : [1][2]</summary></entry><entry><title type="html">Les bonnes pratiques de développement - partie 1</title><link href="blog.luxifer.fr/2015/03/20/bonnes-pratiques-de-developpement-partie-1/" rel="alternate" type="text/html" title="Les bonnes pratiques de développement - partie 1" /><published>2015-03-20T00:00:00+00:00</published><updated>2015-03-20T00:00:00+00:00</updated><id>blog.luxifer.fr/2015/03/20/bonnes-pratiques-de-developpement-partie-1</id><content type="html" xml:base="blog.luxifer.fr/2015/03/20/bonnes-pratiques-de-developpement-partie-1/">&lt;p&gt;Parties : [1][&lt;a href=&quot;/2015/03/27/bonnes-pratiques-de-developpement-partie-2/&quot;&gt;2&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;Voilà bien un sujet pour lequel j’ai pu discuter pendant des heures cumulées autour de la machine à café. Ce sujet sera traité en plusieurs articles, pour qu’il soit plus digeste à lire. Je mettrai à jour au cours de l’écritures les références vers les différentes parties.&lt;/p&gt;

&lt;h2 id=&quot;disclaimer&quot;&gt;Disclaimer&lt;/h2&gt;

&lt;p&gt;Tout ce que je vais écrire dans cette série d’article reflète uniquement ma propre opinion.&lt;/p&gt;

&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;

&lt;p&gt;Commençons par définir le périmètre des &lt;em&gt;bonnes pratiques de développement&lt;/em&gt;. Pour moi ce sujet couvre l’organisation de l’équipe, la façon de répondre à un besoin, son implication dans le projet, la façon de concevoir et d’écrire du code, le tester. Dans cette première partie je vais traiter le niveau humain.&lt;/p&gt;

&lt;h2 id=&quot;lhumain&quot;&gt;L’humain&lt;/h2&gt;

&lt;p&gt;En tant que développeur on est avant tout un humain, ce qui implique des relations sociales et pas seulement homme - machine. On voit ce type de relation à tous les niveaux. Dans le métro pour aller au travail, autour de la machine à café, il s’agit le plus souvent de relations informelles. Au travail on les retrouves lors de réunions, de rendez-vous, mais aussi lorsqu’on répond à un email, un ticket de bug. Il y a toujours quelqu’un de l’autre côté qui va lire et interpréter ce qu’on a écris. Le plus souvent pas comme on le pensait car on a tous des grilles de perception différentes. C’est pourquoi être un bon développeur c’est avant tout savoir bien communiquer, tant à l’oral qu’à l’écrit.&lt;/p&gt;

&lt;h2 id=&quot;communication-orale&quot;&gt;Communication orale&lt;/h2&gt;

&lt;p&gt;C’est un type de communication facile, en face à face, au téléphone, skype, whatever. C’est très pratique, mais très souvent un piège. Par exemple, ton client t’appelle, te demande de faire telle ou telle correction &lt;em&gt;urgente&lt;/em&gt;, toi tu t’exécute, et là, le lendemain ou la semaine suivante, on te demande d’ou sort cette demande. Comment la justifier ? impossible… Ce genre de problèmes m’est arrivé plusieurs fois, c’est pourquoi depuis je pars du principe que &lt;strong&gt;toute&lt;/strong&gt; communication orale est &lt;strong&gt;informelle&lt;/strong&gt;. Dès qu’il s’agit d’une communication formelle, je retranscris par écrit.&lt;/p&gt;

&lt;h2 id=&quot;communication-écrite&quot;&gt;Communication écrite&lt;/h2&gt;

&lt;p&gt;Là non plus ce n’est pas si simple. Certes, c’est écrit, mais toujours sujet à interprétation. Chaque personne à son vécu, son éducation, etc. Bref on a tous un milliards de facteurs qui font qu’on va interpréter différemment ce qu’on lit. C’est pourquoi il faut être &lt;strong&gt;explicite&lt;/strong&gt; au maximum sur le message qu’on veut faire passer. Par exemple, si un ticket est vague, toujours demander un maximum d’explications aux personnes concernées avant de se lancer dans le code. Car au final ça retombe souvent sur le développeur et on peut se retrouver à avoir travailler pendant une semaine pour rien… Un cahier des charges est toujours soumit au changement, et sur un projet en perpétuelle évolution, difficile d’écrire un cahier des charges qui couvre tout de manière exhaustive. En tant que développeur, j’essaye de toujours avoir une trace de tout ce qui est fait sur les projets sur lesquels je travaille. Tickets, mails, historique git, &lt;em&gt;pull request&lt;/em&gt;, etc.&lt;/p&gt;

&lt;h2 id=&quot;gestion-du-temps&quot;&gt;Gestion du temps&lt;/h2&gt;

&lt;p&gt;Bien coder, s’est aussi bien gérer son temps. Ça commence par l’estimation d’une tâche, souvent fausse car on a jamais tous les paramètres. Mais c’est aussi la façon de le découper dans la journée pour allouer tant de temps aux mails, tant au code, et ainsi de suite. En tant que développeur on a souvent besoin de longue session non interrompue de code. Car le changement de tâche a un coût. Si on commence une tâche, qu’au bout d’une heure on reçoit un mail ou un appel, et qu’en suite on retourne dans le code, il va falloir du temps pour retrouver où on en était. J’essaye donc au maximum de dépiler mes mails en début de journée, faire un tour des tickets, en choisir un et m’y atteler. J’essaye de préférence d’avoir des tâches ayant un périmètre le plus petit possible, ainsi je peux en traiter plusieurs dans la journée. C’est beaucoup plus motivant car à la fin de la journée on à l’impression d’avoir abattu beaucoup de travail. Ce n’est pas toujours possible, certaines demandes peuvent nécessiter plusieurs jours. Dans ce type de tâche il est important de se définir plusieurs objectifs afin qu’elles ne paraissent pas insurmontables.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Pour être un bon développeur, il faut donc savoir communiquer et bien gérer son temps. Dans le prochain article je rentrerai plus en détail sur le code. La façon de l’organiser, gérer un environnement de développement, comment éviter les régressions. Si vous avez des questions, des remarques, des choses à ajouter, n’hésitez pas à utiliser les commentaires pour m’en faire part.&lt;/p&gt;</content><author><name>Florent Viel</name><email>florent.viel69@gmail.com</email><uri>https://plus.google.com/+FlorentViel</uri></author><category term="dev" /><category term="développement" /><category term="équipe" /><category term="team" /><summary type="html">Parties : [1][2]</summary></entry><entry><title type="html">Pourquoi choisir Go</title><link href="blog.luxifer.fr/2015/03/13/pourquoi-choisir-go/" rel="alternate" type="text/html" title="Pourquoi choisir Go" /><published>2015-03-13T00:00:00+00:00</published><updated>2015-03-13T00:00:00+00:00</updated><id>blog.luxifer.fr/2015/03/13/pourquoi-choisir-go</id><content type="html" xml:base="blog.luxifer.fr/2015/03/13/pourquoi-choisir-go/">&lt;p&gt;Je suis un grand fan du langage de programmation Go. Dans cet article je vais essayer d’expliquer pourquoi c’est un bon choix en entreprise, quels sont ses avantages.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://blog.golang.org/gopher/header.jpg&quot; alt=&quot;Golang mascot&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;

&lt;p&gt;Petite remise dans le contexte. Go (Golang) est un langage de programmation compilé, développé par Google qui a maintenant 5 ans. C’est un langage qui se veut simple dans sa conception et son utilisation. Pour ceux qui ne connaissent pas, je conseille d’aller jeter un oeil à &lt;a href=&quot;http://go-tour-fr.appspot.com/welcome/1&quot;&gt;Un tour de Go&lt;/a&gt;. C’est un didacticiel en ligne qui permet de faire le tour du langage et de découvrir ses fonctionnalités.&lt;/p&gt;

&lt;p&gt;Venant d’un langage interprété comme PHP ça peut être un peu déroutant au début, mais sa syntaxe s’inspire du C, du C++ et du Python, donc rien de fondamentalement nouveau. La où Go innove, c’est au niveau des fonctionnalités. Globalement vous pouvez à peu près tout faire avec les &lt;strong&gt;Slice&lt;/strong&gt;, les &lt;strong&gt;Map&lt;/strong&gt;, les &lt;strong&gt;channels&lt;/strong&gt; et les &lt;strong&gt;Goroutines&lt;/strong&gt;. Vous allez me dire, mais ce langage est vide, on ne peut rien faire avec, où sont les generics ? les generator ? et j’en passe. À l’heure actuelle, on part du principe qu’un nouveau langage de programmation doit reprendre les concepts et les fonctionnalités de ses prédécesseurs. Go n’a pas choisi cette voie car ses concepteurs voulaient un langage simple par nature. Je vous laisse consulter &lt;a href=&quot;http://commandcenter.blogspot.it/2012/06/less-is-exponentially-more.html&quot;&gt;ce billet&lt;/a&gt; de Rob Pike, un des trois fondateurs du langage.&lt;/p&gt;

&lt;h2 id=&quot;tour-des-fonctionnalités&quot;&gt;Tour des fonctionnalités&lt;/h2&gt;

&lt;p&gt;Je vous ai cité précédemment les principales fonctionnalités du langage. Ce qui en fait un langage simple c’est que pour une fois, la spécification est &lt;a href=&quot;https://golang.org/ref/spec&quot;&gt;lisible&lt;/a&gt;, tout y est bien documenté, il existe même un genre de résumé de cette spécification &lt;a href=&quot;https://golang.org/doc/effective_go.html&quot;&gt;ici&lt;/a&gt;. Je ne vais pas m’étendre sur les Slice et les Map, en gros un Slice c’est un tableau indexé de data, et un Map permet de définir une structure de data.&lt;/p&gt;

&lt;p&gt;Je vais rentrer un peu plus dans le détail sur les &lt;em&gt;channels&lt;/em&gt; et les &lt;em&gt;goroutines&lt;/em&gt;. Une &lt;em&gt;goroutine&lt;/em&gt; est un genre de &lt;em&gt;thread&lt;/em&gt; simplifié qui permet d’écrire du code asynchrone très rapidement. le simple fait de placer le mot-clé &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;go&lt;/code&gt; devant un appel de fonction ou une fonction anonyme crée une &lt;em&gt;goroutine&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-go highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;go&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Sort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// run list.Sort concurrently; don't wait for it.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Alors tout ça c’est bien gentil, mais comment on récupère le traitement d’une &lt;em&gt;goroutine&lt;/em&gt; ? Comment sait-on que son exécution est terminée ? C’est là qu’entre en jeu les &lt;em&gt;channels&lt;/em&gt;. Un &lt;em&gt;channel&lt;/em&gt; permet de communiquer avec des &lt;em&gt;goroutines&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-go highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;make&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;chan&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// Allocate a _channel.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;// Start the sort in a goroutine; when it completes, signal on the _channel.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;go&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Sort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// Send a signal; value does not matter.&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;doSomethingForAWhile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;   &lt;span class=&quot;c&quot;&gt;// Wait for sort to finish; discard sent value.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Dans cet exemple, on crée un &lt;em&gt;channel&lt;/em&gt; d’&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int&lt;/code&gt;, on crée une &lt;em&gt;goroutine&lt;/em&gt; dans laquelle on va procéder au tri de notre &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;list&lt;/code&gt;, à la fin de ce tri on informe le &lt;em&gt;channel&lt;/em&gt; que le tri est terminé en envoyant un signal, dans cet exemple, la valeur du signal n’a pas d’importance. Pendant ce temps on a appelé la fonction &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;doSomethingForAWhile&lt;/code&gt; qui va réaliser un traitement assez long. et la dernière ligne indique qu’on attend de recevoir le signal pour passer à la suite. De cette façon on est prévenu de la fin de l’exécution de notre &lt;em&gt;goroutine&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Ces deux fonctionnalités permettent d’écrire des programmes complexes, avec des traitements asynchrones tout en restant simple dans l’écriture.&lt;/p&gt;

&lt;h2 id=&quot;avantages&quot;&gt;Avantages&lt;/h2&gt;

&lt;p&gt;Le premier avantage de Go, particulièrement en entreprise, quand on travaille en équipe c’est la convention de codage. Elle est écrite dans le compilateur, ce qui fait qu’un programme qui ne respecte pas cette convention ne fonctionnera pas. Le langage met à disposition plusieurs outils pour formater son code correctement comme &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;go fmt&lt;/code&gt; qui est inclus et &lt;a href=&quot;https://github.com/golang/lint&quot;&gt;golint&lt;/a&gt; qui propose des suggestions d’amélioration ainsi que &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;go vet&lt;/code&gt; qui inspecte les constructeurs. Comme ça pas de discussion sans fin pour savoir si on met son accolade en fin de ligne ou sur la ligne suivante.&lt;/p&gt;

&lt;p&gt;L’autre avantage est que pratiquement tout est intégré dans la bibliothèque de base. Besoin de faire un serveur web ? &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;net/http&lt;/code&gt; à la rescousse. Besoin de toucher à l’&lt;em&gt;I/O&lt;/em&gt; ? &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;io&lt;/code&gt; et &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;io/ioutil&lt;/code&gt; sont la. Pour travailler avec les fichiers ? &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;os&lt;/code&gt; est la pour vous servir. Vous faites une API en &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JSON&lt;/code&gt; ? &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;encoding/json&lt;/code&gt; est là. Bref vous l’aurez compris, tout est déjà inclus. Mais ça ne vous empêche pas d’utiliser des bibliothèques d’autres développeurs.&lt;/p&gt;

&lt;p&gt;On en vient donc à la gestion de dépendances. Avec Go, pas de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;composer.json&lt;/code&gt;, pas de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Gemfile&lt;/code&gt;, pas de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;requirements.txt&lt;/code&gt;. Les dépendances dont on a besoin se déclarent dans le fichier qui les utilise, et le compilateur râle s’il y a des dépendances qui ne sont pas utilisés.&lt;/p&gt;

&lt;div class=&quot;language-go highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;package&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;fmt&quot;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;fmt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Println&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Hello, world!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Alors vous allez dire, comment on spécifie la version d’une dépendance pour être sûr que notre programme sera compilé avec les mêmes &lt;em&gt;vendors&lt;/em&gt; sur notre machine, sur notre CI et sur notre &lt;em&gt;prod&lt;/em&gt; ? Il existe plusieurs solutions pour ça comme &lt;a href=&quot;http://labix.org/gopkg.in&quot;&gt;gopkg.in&lt;/a&gt; qui sert d’alias dans les imports en spécifiant une version :&lt;/p&gt;

&lt;div class=&quot;language-go highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;gopkg.in/yaml.v1&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Il existe aussi &lt;a href=&quot;https://github.com/tools/godep&quot;&gt;godep&lt;/a&gt; qui permet de sauvegarder son workspace local de dépendances, qui sera à ajouter dans sons &lt;em&gt;VCS&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;La plupart du temps, il suffit d’utiliser la technique de base de déclarer ses dépendances dans le block &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;import&lt;/code&gt; car un programme en Go ne doit pas casser la compatibilité. Si c’est le cas, il faut faire un nouveau projet. On évite ainsi avec le &lt;a href=&quot;http://en.wikipedia.org/wiki/Dependency_hell&quot;&gt;Dependency hell&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Un autre avantage de Go est que celui-ci est compilé en un binaire statique. Ainsi, un simple &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scp&lt;/code&gt; puis un &lt;em&gt;restart&lt;/em&gt; permet de déployer une nouvelle version de son programme. Go à été pensé par ses créateurs pour des gros code source, des gros projets avec des grosses équipes qui travaillent dessus. Alors oui, un &lt;em&gt;Hello world&lt;/em&gt; en Go génère un binaire plus gros que la même chose en C ou C++. Mais c’est un langage conçu avec son temps. On a des teraoctets de stockage et des gigaoctets de mémoire vive à l’heure actuelle sur nos machines de production, donc pas besoin d’avoir un binaire qui fait &lt;em&gt;18Ko&lt;/em&gt; au lieu de &lt;em&gt;3Mo&lt;/em&gt;. Pas de &lt;em&gt;Makefile&lt;/em&gt; non plus pour compiler son programme, un simple &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;go build&lt;/code&gt; suffit.&lt;/p&gt;

&lt;h2 id=&quot;inconvénients&quot;&gt;Inconvénients&lt;/h2&gt;

&lt;p&gt;Comment ça des inconvénients ?&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/trollface.png&quot; alt=&quot;Troll face&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;preuve-par-lexemple&quot;&gt;Preuve par l’exemple&lt;/h2&gt;

&lt;p&gt;Il y a maintenant des dizaines d’entreprise qui ont fait le choix de Golang, alors pourquoi pas vous ?&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/facebookgo&quot;&gt;facebook&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://highscalability.com/blog/2014/5/7/update-on-disqus-its-still-about-realtime-but-go-demolishes.html&quot;&gt;Disqus&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://bowery.io/posts/Nodejs-to-Golang-Bowery/&quot;&gt;Bowery&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://sendgrid.com/blog/convince-company-go-golang/&quot;&gt;Sendgrid&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://blog.iron.io/2013/03/how-we-went-from-30-servers-to-2-go.html&quot;&gt;Iron.io&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://word.bitly.com/post/33232969144/nsq&quot;&gt;Bitly&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Je ne vais pas faire une liste exhaustive ici de toutes les entreprises qui ont fais le paris de Go, mais le simple fait de lire ces articles permet d’avoir un bon aperçu de pourquoi c’est une bonne décision.&lt;/p&gt;

&lt;p&gt;J’ai moi même eu l’occasion de faire un peu de Go en entreprise. Chez mon &lt;a href=&quot;https://www.wanadev.fr/&quot;&gt;ancien employeur&lt;/a&gt;, je travaillais sur un réseau social qui traitait beaucoup d’images dans beaucoup de formats. J’ai développé un worker en Go qui permet de générer les miniatures de façon asynchrone sans surcharger les requêtes HTTP, tout en profitant de toutes les capacités d’un serveur dédié à ce process.&lt;/p&gt;

&lt;p&gt;Pour &lt;a href=&quot;http://www.xotelia.com/&quot;&gt;mon employeur actuel&lt;/a&gt; j’ai développé un petit programme qui permet de faire du debug sur des requêtes HTTP sans pourrir la réponse. Quand c’est de l’AJAX et qu’on renvoie du &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JSON&lt;/code&gt;, pas facile de faire un &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;var_dump&lt;/code&gt; au milieu de tout ça. Il s’agit d’un petit programme connecté à Redis, qui possède un seul point d’entrée sur son API pour envoyer les messages, et il suffit d’ouvrir une page web sur l’index pour avoir le flux en temps réel (Websocket) des messages qu’on lui envoie. Je vous laisse regarder &lt;a href=&quot;https://github.com/Xotelia/RemoteDebugCenter&quot;&gt;ici&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Je suis actuellement en train de développer un mini clone open source de &lt;em&gt;Vagrantcloud&lt;/em&gt; (désormais &lt;a href=&quot;https://atlas.hashicorp.com/boxes/search&quot;&gt;Atlas&lt;/a&gt;) qui permettra de gérer sois-même ses versions de box sur son propre serveur, avec du &lt;em&gt;continuous build&lt;/em&gt; des box via &lt;a href=&quot;https://packer.io/&quot;&gt;packer&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;J’espère vous avoir donné l’envie de tester ce langage de programmation, et pourquoi pas avoir l’occasion de travailler sur un gros projet en Go dans votre entreprise.&lt;/p&gt;

&lt;p&gt;Happy Coding!&lt;/p&gt;</content><author><name>Florent Viel</name><email>florent.viel69@gmail.com</email><uri>https://plus.google.com/+FlorentViel</uri></author><category term="go" /><category term="golang" /><summary type="html">Je suis un grand fan du langage de programmation Go. Dans cet article je vais essayer d’expliquer pourquoi c’est un bon choix en entreprise, quels sont ses avantages.</summary></entry><entry><title type="html">Mes impressions sur le télétravail</title><link href="blog.luxifer.fr/2015/03/06/mes-impressions-sur-le-teletravail/" rel="alternate" type="text/html" title="Mes impressions sur le télétravail" /><published>2015-03-06T00:00:00+00:00</published><updated>2015-03-06T00:00:00+00:00</updated><id>blog.luxifer.fr/2015/03/06/mes-impressions-sur-le-teletravail</id><content type="html" xml:base="blog.luxifer.fr/2015/03/06/mes-impressions-sur-le-teletravail/">&lt;p&gt;Celà fait maintenant 9 mois que je suis en télétravail et je peux tout de suite dire que j’apprécie ça.&lt;/p&gt;

&lt;h2 id=&quot;-pursuit-of-happiness-&quot;&gt;“ Pursuit of Happiness ”&lt;/h2&gt;

&lt;p&gt;Tout d’abord, qu’est-ce qui m’a amené à faire du télétravail ? Le désir d’avoir plus d’autonomie, mais aussi de pouvoir voir mon fils toute la journée et m’occuper de lui la journée autant que ma femme.&lt;/p&gt;

&lt;p&gt;J’ai d’abord commencé le fonctionnement en tant que freelance, puis ensuite en CDI pour Xotelia. J’ai d’abord commencé en tant que freelance car ça m’a permis d’organiser mon emploi du temps comme je le voulais, tout en gardant des moments de disponible pour mon client. J’avais besoin de cette souplesse pour passer mon permis de conduire, ainsi que d’autres obligations. Étant en freelance je pouvais travailler tous les jours de la semaine. J’essayais quand même de garder du temps libre à consacrer à ma famille. Cette expérience de freelance n’a duré que 4 mois, à la suite desquels j’ai été embauché en CDI chez mon client.&lt;/p&gt;

&lt;p&gt;J’ai perdu la souplesse d’organisation de mon emploi de temps car les jours et les horaires de travail sont fixes. Mais je n’ai pas perdu les avantages du télétravail. À savoir :&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Le temps de trajet entre mon domicile et mon lieu de travail est d’environ 3 secondes, le temps d’aller dans mon bureau :),&lt;/li&gt;
  &lt;li&gt;La possibilité de travailler d’où je veux,&lt;/li&gt;
  &lt;li&gt;L’organisation de mon poste de travail comme bon me semble.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Il faut savoir qu’il y à quand même quelques inconvénients :&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Pas de discussion &lt;em&gt;off&lt;/em&gt; à la machine à café,&lt;/li&gt;
  &lt;li&gt;Tout seul toute la journée,&lt;/li&gt;
  &lt;li&gt;Pas de contact humain (enfin dans mon cas je vois ma femme et mon fils :)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Il existe beaucoup d’outils, surtout dans le développement informatique, qui permettent de contourner ces inconvénients. Tout d’abord mettre en place un chat pour que l’équipe reste soudée et puisse discuter toutes la journée, nous utilisons &lt;a href=&quot;https://www.hipchat.com/&quot;&gt;HipChat&lt;/a&gt;. Mettre en place un système de ticket comme &lt;a href=&quot;https://plan.io/&quot;&gt;Redmine&lt;/a&gt; et surtout un gestionnaire de version décentralisé comme &lt;a href=&quot;https://github.com/&quot;&gt;GitHub&lt;/a&gt;. Enfin bref, presque tout ce qui est fait en interne dans l’entreprise, peut être mis sur une plateforme en ligne. Vous trouverez une liste des outils pratique en télétravail &lt;a href=&quot;http://thenextweb.com/apps/2014/12/06/tools-remote-teams/&quot;&gt;ici&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;the-graal&quot;&gt;The Graal&lt;/h2&gt;

&lt;p&gt;D’une manière générale, ce mode de fonctionnement me va plutôt bien. Certes il impose une certaine rigueur pour ne pas finir sur Twitter, Hacker News ou Reddit toutes les 5 minutes. Mais avec de la concentration, et surtout, un métier passionnant, ce n’est pas vraiment un problème. Celà dit, ce n’est pas fait pour tout le monde non plus. Le seul problème que je peux noter pour ce mode de travail c’est de voir rarement l’équipe. Mais ce problème est en partie résolu par le fait que je descende régulièrement sur Lyon dans les bureaux de la société pour quelques jours. Ça permet de renforcer l’équipe, pour moi de voir des gens et d’une manière générale que personne ne soit oublié. Je peux citer un excellent &lt;a href=&quot;http://justinjackson.ca/remote/&quot;&gt;article sur le sujet&lt;/a&gt; mais aussi un excellent &lt;a href=&quot;http://www.amazon.fr/Remote-Required-David-Heinemeier-Hansson/dp/0091954673/&quot;&gt;bouquin&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;J’arrive globalement à rester concentré 6 heures dans la journée, je peux me prendre une petite pause quand bon me semble pour boire un café, ou simplement me dégourdir les jambes. Le midi je mange chez moi. Ce qui me permet d’économiser par mois un abonnement aux transports en communs, des pleins d’essence et des dépenses inutiles pour m’acheter un sandwich ou me payer un resto à l’extérieur.&lt;/p&gt;

&lt;p&gt;Pour conclure, ce mode de travail me correspond parfaitement et s’il le fallait je pourrai intégrer d’autres personnes en télétravail au sein de l’équipe Xotelia. Dans un futur plus ou moins proche je serai peut être de nouveau amené à travailler dans des bureaux, mais ce n’est pas au programme pour l’instant. Pour ceux que ça intéresse, il existe un site d’offres d’emploi uniquement consacré au télétravail &lt;a href=&quot;https://weworkremotely.com/&quot;&gt;We Work Remotely&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy remote work!&lt;/p&gt;</content><author><name>Florent Viel</name><email>florent.viel69@gmail.com</email><uri>https://plus.google.com/+FlorentViel</uri></author><category term="télétravail" /><category term="remote" /><category term="work" /><summary type="html">Celà fait maintenant 9 mois que je suis en télétravail et je peux tout de suite dire que j’apprécie ça.</summary></entry><entry><title type="html">Retours d'expériences sur le recrutement</title><link href="blog.luxifer.fr/2015/02/27/retours-experience-recrutement/" rel="alternate" type="text/html" title="Retours d'expériences sur le recrutement" /><published>2015-02-27T00:00:00+00:00</published><updated>2015-02-27T00:00:00+00:00</updated><id>blog.luxifer.fr/2015/02/27/retours-experience-recrutement</id><content type="html" xml:base="blog.luxifer.fr/2015/02/27/retours-experience-recrutement/">&lt;p&gt;Ces dernières semaines j’ai été amené à faire passer des entretiens techniques pour trouver deux personnes avec qui je vais partager mes tâches au quotidien.&lt;/p&gt;

&lt;h2 id=&quot;remise-dans-le-contexte&quot;&gt;Remise dans le contexte&lt;/h2&gt;

&lt;p&gt;Tout d’abord, une petite remise dans le contexte s’impose. Je travaille pour &lt;a href=&quot;http://www.xotelia.com/&quot;&gt;Xotelia&lt;/a&gt;, un gestionnaire de canaux de ventes en SaaS. Je suis tout seul à m’occuper des corrections de bugs, des évolutions et des nouveaux projets. L’entreprise vient de faire une levée de fonds et il faut donc agrandir l’équipe technique pour pouvoir tenir la charge qui va arriver.&lt;/p&gt;

&lt;p&gt;On m’a donc confié la tâche de trouver des personnes avec qui je travaillerai. Pour préciser, je m’occupe seulement de l’entretien technique et je suis en bout de chaîne. Nous passons par un cabinet de recrutement pour aller au plus vite, donc il y a un premier filtre à ce niveau là et ensuite le candidat a un entretien avec le patron, ce qui fait un second filtre. Je me retrouve donc avec des candidats qui correspondent à la fiche de poste et qui ont été jugés comme capables de travailler en équipe chez Xotelia. Un autre point à prendre en compte est le fait que je suis en télétravail, la société est sur Lyon donc tous les entretiens que je fais passer se déroulent sur Skype.&lt;/p&gt;

&lt;p&gt;Comme c’est une expérience nouvelle pour moi, je me suis un peu renseigné en quoi consiste un entretien technique, et oui jusqu’à présent j’ai toujours été à la place du candidat, maintenant je suis à la place du recruteur. J’ai donc trouvé plusieurs articles &lt;a href=&quot;http://reprogramming.com/hiring-programmers/&quot;&gt;ici&lt;/a&gt; et &lt;a href=&quot;http://www.nicolasbize.com/blog/how-i-ended-up-conducting-the-most-successful-technical-interviews-with-a-single-question/&quot;&gt;là&lt;/a&gt;. Je sais comment je suis, je veux travailler avec des gens comme moi, mais il me fallait définir les critères qui me définissent pour trouver quelqu’un comme moi.&lt;/p&gt;

&lt;p&gt;En lisant ces deux articles, je me suis rendu compte qu’au final c’était assez simple. Il me fallait quelqu’un de motivé, mais surtout de passionné.&lt;/p&gt;

&lt;p&gt;Quelqu’un qui a vu des lumières s’allumer dans ses yeux le jour où il a compilé son premier programme et qui a voulu le montrer à tout le monde. Même si ce programme ne faisait qu’afficher &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Hello, World!&lt;/code&gt; dans la console.&lt;/p&gt;

&lt;h2 id=&quot;déroulement-de-lentretien-prévu&quot;&gt;Déroulement de l’entretien prévu&lt;/h2&gt;

&lt;p&gt;Je me suis donc basé sur le retour d’expérience de Nicolas Bize pour le déroulement de mes entretiens :&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Rapide passage en revue du CV (10 min)&lt;/li&gt;
  &lt;li&gt;Présentation de la stack technique de Xotelia (10 min)&lt;/li&gt;
  &lt;li&gt;Questions sur quels sont les projets dont il est le plus fier et discussions (25-30 min)&lt;/li&gt;
  &lt;li&gt;Test technique par mail&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Après avoir fait passer plusieurs entretiens, je peux confirmer que la méthode de Nicolas fonctionne.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“ we have about 30 minutes left. Will you please tell me about the best project that you’ve ever created? ”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Je me rendais rapidement compte de la motivation du candidat en voyant pétiller ses yeux quand il me parlait de ses projets. J’essaye au début de l’entretien de le mettre en confiance en posant des questions naïves sur des technos qu’il a pu utiliser, etc. Pour l’explication de la stack Xotelia, je mentionnais quelques technos mais rien de trop explicite non plus, il ne s’agit pas d’un meetup d’experts PHP. Puis ensuite venait la question fatidique &lt;em&gt;“ Parle-moi des projets dont tu es le plus fier ”&lt;/em&gt;. La plupart du temps, j’écoutais le candidat parler mais je pouvais aussi appuyer ce qu’il disait à certains moment en mentionnant qu’il m’est arrivé la même chose dans ma carrière ou que j’ai aussi utilisé telle techno. À la fin de cet entretien, je savais déjà si la personne correspondait au profil ou pas. Mais je faisais quand même passer un petit test technique. Rien de bien compliqué, pas non plus le questionnaire de la certification Zend. Un petit développement en rapport avec le métier de Xotelia.&lt;/p&gt;

&lt;p&gt;Ce test me permet d’avoir un aperçu de la façon de penser du candidat, de comment il organise son code pour résoudre un problème. Un candidat m’a même dit qu’il s’est bien amusé à faire ce test.&lt;/p&gt;

&lt;p&gt;Ma responsabilité dans ce recrutement n’est pas moindre, car il s’agit pour moi de trouver les bonnes personnes qui seront à même techniquement de monter au créneau sur le projet pour le faire décoller et soutenir les défis techniques qui vont arriver avec la levée de fond.&lt;/p&gt;

&lt;p&gt;J’ai trouvé cette expérience très intéressante et je serai prêt à recommencer, la prochaine fois dans la même pièce !&lt;/p&gt;</content><author><name>Florent Viel</name><email>florent.viel69@gmail.com</email><uri>https://plus.google.com/+FlorentViel</uri></author><category term="recrutement" /><category term="entretien" /><category term="tech" /><summary type="html">Ces dernières semaines j’ai été amené à faire passer des entretiens techniques pour trouver deux personnes avec qui je vais partager mes tâches au quotidien.</summary></entry><entry><title type="html">Shell interactif Symfony2</title><link href="blog.luxifer.fr/2014/04/30/shell-interactif-symfony/" rel="alternate" type="text/html" title="Shell interactif Symfony2" /><published>2014-04-30T00:00:00+00:00</published><updated>2014-04-30T00:00:00+00:00</updated><id>blog.luxifer.fr/2014/04/30/shell-interactif-symfony</id><content type="html" xml:base="blog.luxifer.fr/2014/04/30/shell-interactif-symfony/">&lt;p&gt;En python avec le framework django ou en ruby avec rails on dispose d’un shell interactif qui permet de jouer avec ses modèles, la base de donnée, etc. Cette possibilité manquant dans Symfony2. C’est pourquoi j’ai développé une petite lib basée sur &lt;a href=&quot;http://psysh.org/&quot;&gt;psysh&lt;/a&gt; qui permet d’avoir un shell interactif php avec l’application bootée dedans.&lt;/p&gt;

&lt;p&gt;Le projet est disponible &lt;a href=&quot;https://github.com/luxifer/symfony-repl&quot;&gt;ici&lt;/a&gt;. L’installastion est simple :&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;composer require-dev luxifer/symfony-repl
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Ou en le rajoutant à la main dans son &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;composer.json&lt;/code&gt; et en lançant un &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;composer update&lt;/code&gt; :&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;require-dev&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;luxifer/symfony-repl&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;dev-master&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Ensuite à la racine de son projet Symfony, il suffit de lancer &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bin/symfony-repl&lt;/code&gt; et le shell se lance.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Psy Shell v0.1.8 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;PHP 5.5.11 — cli&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; by Justin Hileman
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Depuis ce shell on a la variable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$kernel&lt;/code&gt; qui est exposée et qui est le kernel Symfony. Depuis ce shell on peut lancer &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$kernel-&amp;gt;getContainer()&lt;/code&gt; pour accéder au conteneur de service symfony et donc ainsi accéder à tous les services définis. Tout le code qu’on a écrit dans le dossier &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/&lt;/code&gt; est disponible et on peut donc facilement instancier un modèle comme &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Acme\UserBundle\Entity\User&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Cette petite lib va instancier un kernel Symfony avec l’environnement de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dev&lt;/code&gt;, c’est une sorte de &lt;em&gt;proof of concept&lt;/em&gt;, par la suite je vais rajouter des fonctionnalités pour changer l’environnement ou même le fichier de bootstrap de Symfony.&lt;/p&gt;

&lt;p&gt;Happy development!&lt;/p&gt;</content><author><name>Florent Viel</name><email>florent.viel69@gmail.com</email><uri>https://plus.google.com/+FlorentViel</uri></author><category term="Dev" /><category term="php" /><category term="symfony" /><category term="shell" /><category term="repl" /><summary type="html">En python avec le framework django ou en ruby avec rails on dispose d’un shell interactif qui permet de jouer avec ses modèles, la base de donnée, etc. Cette possibilité manquant dans Symfony2. C’est pourquoi j’ai développé une petite lib basée sur psysh qui permet d’avoir un shell interactif php avec l’application bootée dedans.</summary></entry><entry><title type="html">Permissions sur le dossier .ssh de linux</title><link href="blog.luxifer.fr/2013/12/31/permissions-dossier-ssh-linux/" rel="alternate" type="text/html" title="Permissions sur le dossier .ssh de linux" /><published>2013-12-31T00:00:00+00:00</published><updated>2013-12-31T00:00:00+00:00</updated><id>blog.luxifer.fr/2013/12/31/permissions-dossier-ssh-linux</id><content type="html" xml:base="blog.luxifer.fr/2013/12/31/permissions-dossier-ssh-linux/">&lt;p&gt;Je ne sais pas si certains d’entre vous ont déjà eu ce problème. La connexion ssh par clé publique est bien configurée, et pourtant ssh demande quand même un mot de passe. Dans la plupart des cas il s’agit d’un problème de permissions sur le dossier &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.ssh&lt;/code&gt;. Voici les bonnes permissions à appliquer sur ce dossier :&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# dossier .ssh&lt;/span&gt;

drwxr-xr-x  2 luxifer luxifer 4096 oct.  18 20:11 &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
drwx------ 21 luxifer luxifer 4096 déc.  30 10:59 ..
&lt;span class=&quot;nt&quot;&gt;-rw-r--r--&lt;/span&gt;  1 luxifer luxifer  803 oct.  18 20:11 authorized_keys
&lt;span class=&quot;nt&quot;&gt;-rw-------&lt;/span&gt;  1 luxifer luxifer 1675 oct.  16 15:43 id_rsa
&lt;span class=&quot;nt&quot;&gt;-rw-r--r--&lt;/span&gt;  1 luxifer luxifer  404 oct.  16 15:43 id_rsa.pub
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# dossier home&lt;/span&gt;

drwxr-xr-x   2 luxifer luxifer  4096 oct.  18 20:11 .ssh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Pour la petite explication, dans le dossier &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.ssh&lt;/code&gt;, le dossier &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;..&lt;/code&gt; doit avoir un chmod de &lt;strong&gt;700&lt;/strong&gt; qui autorise seulement le propriétaire à aller vers le dossier supérieur. De ce fait lors de la connexion ssh, tant qu’on est pas connecté, le dossier home est protégé. ensuite, les fichiers &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;authorized_keys&lt;/code&gt; et &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;id_rsa.pub&lt;/code&gt; doivent être en chmod &lt;strong&gt;644&lt;/strong&gt; car ce sont eux qui sont utiles lors de la connexion. Pour finir le ficher &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;id_rsa&lt;/code&gt; doit être en chod &lt;strong&gt;600&lt;/strong&gt; car c’est la clé privée.&lt;/p&gt;

&lt;p&gt;Ensuite dans le dossier home, le dossier &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.ssh&lt;/code&gt; doit être en chmod &lt;strong&gt;755&lt;/strong&gt; car ssh a besoin d’y accéder lors de la connexion.&lt;/p&gt;

&lt;p&gt;Et voilà :)&lt;/p&gt;</content><author><name>Florent Viel</name><email>florent.viel69@gmail.com</email><uri>https://plus.google.com/+FlorentViel</uri></author><category term="linux" /><category term="ssh" /><category term="chmod" /><category term="permissions" /><summary type="html">Je ne sais pas si certains d’entre vous ont déjà eu ce problème. La connexion ssh par clé publique est bien configurée, et pourtant ssh demande quand même un mot de passe. Dans la plupart des cas il s’agit d’un problème de permissions sur le dossier .ssh. Voici les bonnes permissions à appliquer sur ce dossier :</summary></entry><entry><title type="html">Intégration continue avec Symfony 2, Composer et Jenkins</title><link href="blog.luxifer.fr/2013/05/31/integration-continue-avec-symfony-2-composer-et-jenkins/" rel="alternate" type="text/html" title="Intégration continue avec Symfony 2, Composer et Jenkins" /><published>2013-05-31T00:00:00+00:00</published><updated>2013-05-31T00:00:00+00:00</updated><id>blog.luxifer.fr/2013/05/31/integration-continue-avec-symfony-2-composer-et-jenkins</id><content type="html" xml:base="blog.luxifer.fr/2013/05/31/integration-continue-avec-symfony-2-composer-et-jenkins/">&lt;p&gt;Bonjour,&lt;/p&gt;

&lt;p&gt;Aujourd’hui on va parler d’intégration continue avec Symfony2, Composer et Jenkins.&lt;/p&gt;

&lt;p&gt;Après plusieurs jours de galère à chercher de la doc sur comment mettre en place des tests automatisé sur symfony2 avec jenkins, j’ai finalement réussi à faire ce que je voulais.
Tout d’abord, plusieurs problèmatiques se posent. Pour les tests unitaires pas besoin de grand chose, on test juste une classe, une fonction ou une méthode. Pour les tests fonctionnels c’est différent. Il faut un environnement, une base de donnée et potentiellement un jeu de donnée.&lt;/p&gt;

&lt;p&gt;Passons donc aux choses sérieuses.&lt;/p&gt;

&lt;p&gt;Symfony permet de créer différents environnements, typiquement &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dev&lt;/code&gt; et &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;prod&lt;/code&gt;. Les besoins ne sont pas les mêmes, en dev on a besoin de debug, de sandbox, etc. En prod on a besoin de cache, etc. On va donc commencer par mettre en place en environnement pour les test et faire en sorte qu’il soit le plus petit et le plus indépendant possible.&lt;/p&gt;

&lt;p&gt;À la création d’un projet Symfony 2, l’environnement de test est déjà créé, il nous reste à le customiser.&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# app/config_test.yml&lt;/span&gt;

&lt;span class=&quot;na&quot;&gt;doctrine&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;dbal&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;driver&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;     &lt;span class=&quot;s&quot;&gt;pdo_sqlite&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;       &lt;span class=&quot;err&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;kernel.root_dir%/var/test.db&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;       &lt;span class=&quot;s&quot;&gt;root&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;On va donc dire à symfony qu’on veut utiliser sqlite comme base de donnée car les jeux de données sont petit et qu’on a pas besoin de performance. J’ai choisi de stocker la base dans un fichier, mais il est très bien possible de la stocker en mémoire en remplaçant l’option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;path&lt;/code&gt; par &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;memory: true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ensuite pour exécuter sa suite de tests, il faut un &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bootstrap&lt;/code&gt; pour initialiser une requête d’un test fonctionnel. La le problème c’est que le &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bootstrap.php.cache&lt;/code&gt; de symfony de base va seulement faire un autoload des vendors et initialiser le kernel. Avec un environnement de test il faut monter une base donnée, créer les tables et charger les fixtures. Il est possible de dire à phpunit d’utiliser un fichier de bootstrap spécifique qui va faire les choses à notre place.&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;&amp;lt;!-- app/phpunit.xml.dist --&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;phpunit&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;bootstrap =&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;tests.bootstrap.php&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Dans ce fichier on indique à phpunit d’utiliser un fichier spécifique pour exécuter nos tâches de bootstrap.&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// app/tests.bootstrap.php&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;isset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$_ENV&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'BOOTSTRAP_DB_ENV'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;passthru&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sprintf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;'rm &quot;%s/var/test.db&quot;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;__DIR__&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;passthru&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sprintf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;'php &quot;%s/console&quot; doctrine:schema:update --force --env=%s'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;__DIR__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$_ENV&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'BOOTSTRAP_DB_ENV'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;passthru&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sprintf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;'php &quot;%s/console&quot; doctrine:fixtures:load --append --env=%s'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;__DIR__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$_ENV&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'BOOTSTRAP_DB_ENV'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;__DIR__&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'/bootstrap.php.cache'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Dans ce fichier on liste les tâches à exécuter si la variable d’environement &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BOOTSTRAP_DB_ENV&lt;/code&gt; est définie. Là on indique qu’on veut supprimer la base de test existante, créer le schéma et charger les fixtures.&lt;/p&gt;

&lt;p&gt;Ensuite pour définir cette variable d’environnement, il faut rajouter ceci dans son fichier &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;phpunit.xml.dist&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;&amp;lt;!-- app/phpunit.xml.dist --&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;php&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;env&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;BOOTSTRAP_DB_ENV&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;test&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/php&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Cette modification va permettre de créer une fase de donnée et de charger les fixtures, nécessaires à l’exécution de la suite de tests.&lt;/p&gt;

&lt;p&gt;Désormais, lors de l’exécution de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bin/vendor/phpunit&lt;/code&gt; la base de données de test sera supprimée, créée et les fixtures seront chargées avant d’exécuter les tests.&lt;/p&gt;

&lt;p&gt;Ensuite il faut dire à Jenkins de récupérér composer et d’installer les vendors avant de lancer phpunit.&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;&amp;lt;!-- build.xml --&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;target&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;composer&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;depends=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;clean&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;description=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Download composer and install project dependancies&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
     &lt;span class=&quot;nt&quot;&gt;&amp;lt;exec&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;executable=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;wget&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;failonerror=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;true&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;arg&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;-nc&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;arg&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://getcomposer.org/composer.phar&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/exec&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;exec&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;executable=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;php&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;arg&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;composer.phar&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;arg&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;config&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;arg&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;--global&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;arg&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;github-oauth.github.com&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;arg&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;github_oauth-key&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/exec&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;exec&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;executable=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;php&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;failonerror=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;true&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;arg&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;composer.phar&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;arg&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;install&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;arg&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;--dev&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;arg&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;--prefer-dist&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;arg&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;--no-progress&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;arg&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;--no-interaction&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;arg&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;--no-scripts&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/exec&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/target&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;target&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;phpunit&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;description=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Execute tests&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;exec&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;executable=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;${basedir}/vendor/bin/phpunit&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;failonerror=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;true&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;arg&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;-c&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;arg&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;path=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;${basedir}/app&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/exec&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/target&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Le paramètre &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;github-oauth.github.com&lt;/code&gt; sert a passer sa clé oauth à composer pour éviter les problèmes de &lt;em&gt;fair-use&lt;/em&gt; avec l’api github.&lt;/p&gt;

&lt;p&gt;Cette tâche ant va donc dire jenkins de télécharger composer, de configurer la clé oauth github et ensuite de lancer l’installation des vendors en utilisant &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--prefer-dist&lt;/code&gt; qui permet de récupérer en priorité les archives plutôt qu’un git clone. L’exécution des scripts est la aussi inutiles car tout les scripts nécessaires sont lancés par le bootstrap de test.&lt;/p&gt;

&lt;p&gt;La deuxième tâche sert a lancer phpunit avec le fichier de config situé dans &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;app/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;En configurant Jenkins au post-receive git, l’exécution des tests sera faite à chaque git push. Pour finir il suffit d’activer les rapports nécessaires jenkins pour avoir des statistiques sur son dashboard projet.&lt;/p&gt;

&lt;p&gt;J’espère que ça vous sera utile. Bonne journée.&lt;/p&gt;</content><author><name>Florent Viel</name><email>florent.viel69@gmail.com</email><uri>https://plus.google.com/+FlorentViel</uri></author><category term="Dev" /><category term="php" /><category term="xml" /><category term="composer" /><category term="jenkins" /><category term="symfony" /><summary type="html">Bonjour,</summary></entry><entry><title type="html">Corriger le problème de GDM sur Archlinux après la màj 3.8</title><link href="blog.luxifer.fr/2013/05/25/corriger-le-probleme-de-gdm-sur-archlinux-apres-la-maj-3-8/" rel="alternate" type="text/html" title="Corriger le problème de GDM sur Archlinux après la màj 3.8" /><published>2013-05-25T00:00:00+00:00</published><updated>2013-05-25T00:00:00+00:00</updated><id>blog.luxifer.fr/2013/05/25/corriger-le-probleme-de-gdm-sur-archlinux-apres-la-maj-3-8</id><content type="html" xml:base="blog.luxifer.fr/2013/05/25/corriger-le-probleme-de-gdm-sur-archlinux-apres-la-maj-3-8/">&lt;p&gt;Bonjour,&lt;/p&gt;

&lt;p&gt;Je ne pense pas être le seul a avoir eu ce problème étant donné qu’il est dans le &lt;a href=&quot;https://wiki.archlinux.org/index.php/GDM&quot; title=&quot;GDM&quot;&gt;wiki&lt;/a&gt; d’Archlinux.
Après la dernière mise à jour majeur de gnome vers la version 3.8, gdm ne se lance plus et impossible de trouver pourquoi dans les logs.
Le problème vient de la méthode d’accélération du pilote graphique intel. Par défaut c’est &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UXA&lt;/code&gt; qui est plus stable techniquement mais qui est plus lente que la méthode &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SNA&lt;/code&gt;.
Il faut donc changer de méthode pour passer à &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SNA&lt;/code&gt; qui est plus rapide et nécessaire pour gnome.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#/etc/X11/xorg.conf.d/20-intel.conf&lt;/span&gt;

Section &lt;span class=&quot;s2&quot;&gt;&quot;Device&quot;&lt;/span&gt;
   Identifier  &lt;span class=&quot;s2&quot;&gt;&quot;Intel Graphics&quot;&lt;/span&gt;
   Driver      &lt;span class=&quot;s2&quot;&gt;&quot;intel&quot;&lt;/span&gt;
   Option      &lt;span class=&quot;s2&quot;&gt;&quot;AccelMethod&quot;&lt;/span&gt;  &lt;span class=&quot;s2&quot;&gt;&quot;sna&quot;&lt;/span&gt;
EndSection
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Il suffit de redémarrer et le tour est joué.&lt;/p&gt;</content><author><name>Florent Viel</name><email>florent.viel69@gmail.com</email><uri>https://plus.google.com/+FlorentViel</uri></author><category term="system" /><category term="linux" /><category term="gnome" /><category term="archlinux" /><summary type="html">Bonjour,</summary></entry></feed>