philpep's blog - tag git philpep's blog - tag git rss http://blog.philpep.org fr Sun, 09 May 2010 00:00:00 GMT Pblog Un bot IRC à la CIA en python http://blog.philpep.org/post/Un-bot-IRC-a-la-CIA-en-python http://blog.philpep.org/post/Un-bot-IRC-a-la-CIA-en-python Sun, 09 May 2010 00:00:00 GMT <p>Quand vous utilisez <a href="http://git-scm.com/">git</a> à plusieurs et qu'en plus vous utilisez IRC pour en discuter, il peut être agréable d'avoir un bot qui informe le canal des commit sur le serveur. En particulier pour éviter des <code>merge branch</code> à tout va si on oublie de <code>pull</code> avant de <code>commit</code>. Il y a un service sur le net qui propose de tels bots IRC, c'est <a href="http://cia.vc">CIA.vc</a>. Sauf que le service est à des fins de statistiques sur les logiciels libres et j'aime pas trop que ces données sortent du serveur même si elles sont publiques, puis leur bot on sait pas trop ce qu'il fait.</p> <p>Donc je me suis mis à coder ce petit bot en python qui se connecte sur le canal IRC et attend des ordre via <a href="http://en.wikipedia.org/wiki/XML-RPC">xmlrpc</a>, cet ordre est lancé à chaque commit via un <a href="http://www.kernel.org/pub/software/scm/git/docs/githooks.html">hooks</a> sur le serveur git.</p> <p>Pour ça, tout est dans la librairie python standard, sauf <a href="http://python-irclib.sourceforge.net/">irclib</a> et <a href="http://packages.python.org/GitPython/">gitpython</a>.</p> <p>Le serveur (j'ai enlevé toutes les fonctionnalités qui ne rentrent pas dans le cadre de ce billet) :</p> <div class="codehilite"><pre><span class="c">#!/usr/bin/env python</span> <span class="kn">import</span> <span class="nn">threading</span> <span class="kn">import</span> <span class="nn">irclib</span> <span class="n">chan</span> <span class="o">=</span> <span class="s">&#39;#staff&#39;</span> <span class="n">nick</span> <span class="o">=</span> <span class="s">&#39;napalm0&#39;</span> <span class="n">server</span> <span class="o">=</span> <span class="p">(</span><span class="s">&#39;irc.philpep.org&#39;</span><span class="p">,</span> <span class="mi">6667</span><span class="p">)</span> <span class="n">xmlrpcserver</span> <span class="o">=</span> <span class="p">(</span><span class="s">&#39;localhost&#39;</span><span class="p">,</span> <span class="mi">8888</span><span class="p">)</span> <span class="k">class</span> <span class="nc">PbotIRCClient</span><span class="p">(</span><span class="n">irclib</span><span class="o">.</span><span class="n">SimpleIRCClient</span><span class="p">):</span> <span class="k">def</span> <span class="nf">on_welcome</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">s</span><span class="p">,</span> <span class="n">e</span><span class="p">):</span> <span class="n">s</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">chan</span><span class="p">)</span> <span class="c"># Classe de contrôle du bot par xmlrpc</span> <span class="k">class</span> <span class="nc">PbotControl</span><span class="p">:</span> <span class="k">def</span> <span class="nf">commit</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">files</span><span class="p">,</span> <span class="n">summary</span><span class="p">,</span> <span class="n">base</span><span class="p">,</span> <span class="nb">id</span><span class="p">):</span> <span class="c"># On formate la chaine de commit (Projet: Commiter (fichiers_touchés) sommaire_du_commit</span> <span class="nb">str</span> <span class="o">=</span> <span class="s">&#39;</span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="s"> (</span><span class="se">\x03</span><span class="s">23</span><span class="si">%s</span><span class="se">\x03</span><span class="s">) </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">base</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">files</span><span class="p">,</span> <span class="n">summary</span><span class="p">)</span> <span class="n">pbot</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">privmsg</span><span class="p">(</span><span class="n">chan</span><span class="p">,</span> <span class="nb">str</span><span class="p">)</span> <span class="c"># Et un lien vers le commit diff</span> <span class="n">pbot</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">privmsg</span><span class="p">(</span><span class="n">chan</span><span class="p">,</span> <span class="s">&#39;http://git.philpep.org/&#39;</span><span class="o">+</span><span class="n">base</span><span class="o">+</span><span class="s">&#39;.git/commit/?id=&#39;</span><span class="o">+</span><span class="nb">id</span><span class="p">)</span> <span class="c"># Le serveur xmlrpc</span> <span class="k">class</span> <span class="nc">PbotXMLRPCServer</span><span class="p">(</span><span class="n">threading</span><span class="o">.</span><span class="n">Thread</span><span class="p">):</span> <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="n">obj</span> <span class="o">=</span> <span class="n">PbotControl</span><span class="p">()</span> <span class="n">srv</span> <span class="o">=</span> <span class="n">SimpleXMLRPCServer</span><span class="p">(</span><span class="n">xmlrpcserver</span><span class="p">,</span> <span class="n">allow_none</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span> <span class="n">srv</span><span class="o">.</span><span class="n">register_instance</span><span class="p">(</span><span class="n">obj</span><span class="p">)</span> <span class="n">srv</span><span class="o">.</span><span class="n">serve_forever</span><span class="p">()</span> <span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span> <span class="n">pbot</span> <span class="o">=</span> <span class="n">PbotIRCClient</span><span class="p">()</span> <span class="n">pbot</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="n">server</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">server</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">nick</span><span class="p">)</span> <span class="n">t</span> <span class="o">=</span> <span class="n">PbotXMLRPCServer</span><span class="p">()</span> <span class="n">t</span><span class="o">.</span><span class="n">start</span><span class="p">()</span> <span class="n">pbot</span><span class="o">.</span><span class="n">start</span><span class="p">()</span> </pre></div> <p>Et le hooks à mettre dans le bare repo <code>hooks/post-commit</code> :</p> <div class="codehilite"><pre><span class="c">#!/usr/bin/env python</span> <span class="kn">from</span> <span class="nn">sys</span> <span class="kn">import</span> <span class="n">argv</span> <span class="kn">from</span> <span class="nn">git</span> <span class="kn">import</span> <span class="n">Repo</span> <span class="kn">from</span> <span class="nn">xmlrpclib</span> <span class="kn">import</span> <span class="n">ServerProxy</span> <span class="c"># Path vers le bare repo (peut être avec &#39;.&#39; ça marche aussi ?)</span> <span class="n">r</span> <span class="o">=</span> <span class="n">Repo</span><span class="p">(</span><span class="s">&#39;/usr/home/git/repositories/pblog2.git&#39;</span><span class="p">)</span> <span class="n">c</span> <span class="o">=</span> <span class="n">r</span><span class="o">.</span><span class="n">commit</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span> <span class="n">s</span> <span class="o">=</span> <span class="n">ServerProxy</span><span class="p">(</span><span class="s">&#39;http://localhost:8888&#39;</span><span class="p">,</span> <span class="n">allow_none</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span> <span class="c"># Liste des fichiers touchés par le commit</span> <span class="k">try</span><span class="p">:</span> <span class="nb">file</span> <span class="o">=</span> <span class="s">&#39; &#39;</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="n">e</span><span class="o">.</span><span class="n">a_blob</span><span class="o">.</span><span class="n">path</span> <span class="k">for</span> <span class="n">e</span> <span class="ow">in</span> <span class="n">c</span><span class="o">.</span><span class="n">diff</span><span class="p">(</span><span class="n">r</span><span class="p">,</span> <span class="n">c</span><span class="o">.</span><span class="n">parents</span><span class="p">[</span><span class="mi">0</span><span class="p">])])</span> <span class="k">except</span><span class="p">:</span> <span class="nb">file</span> <span class="o">=</span> <span class="s">&#39;&#39;</span> <span class="c"># Appel de la méthode xmlrpc</span> <span class="n">s</span><span class="o">.</span><span class="n">commit</span><span class="p">(</span><span class="n">c</span><span class="o">.</span><span class="n">author</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="nb">file</span><span class="p">,</span> <span class="n">c</span><span class="o">.</span><span class="n">summary</span><span class="p">,</span> <span class="s">&#39;pblog2&#39;</span><span class="p">,</span> <span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span> </pre></div> <p>Voilà, en quelques lignes de python vous avez un bot sympa et vous savez comment il fonctionne laissez parler votre imagination pour l'améliorer.</p> git-daemon sous FreeBSD http://blog.philpep.org/post/git-daemon-sous-FreeBSD http://blog.philpep.org/post/git-daemon-sous-FreeBSD Tue, 26 Jan 2010 21:09:39 GMT <p>Si vous avez un serveur git sous FreeBSD, vous aurez très rapidement des problèmes avec <code>/usr/local/etc/rc.d/git_daemon</code>, genre il démarre mal, et refuse de redémarrer.</p> <p>En fait il suffit d'utiliser l'option <code>--reuseaddr</code> qui passe SO_REUSEADDR à <a href="http://www.freebsd.org/cgi/man.cgi?query=setsockopt">setsockopt</a> pendant la création du socket serveur. Du coup il peut redémarrer même si il y avait une connexion active sur le port.</p> <p>En lisant le script <a href="http://www.freebsd.org/cgi/man.cgi?query=rc">rc</a>, on peut même éviter de le modifier et devoir le refaire à chaque mise à jours de git, dans <code>/etc/rc.conf</code></p> <div class="codehilite"><pre>git_daemon_enable=&quot;YES&quot; git_daemon_directory=&quot;--reuseaddr --base-path=/usr/home/git/repositories&quot; </pre></div> <p>EDIT : ce n'est plus nécessaire maintenant <a href="http://www.freebsd.org/cgi/query-pr.cgi?pr=143275">PR ports/143275</a></p> Gitweb fastcgi lighttpd et FreeBSD http://blog.philpep.org/post/Gitweb-fastcgi-lighttpd-et-FreeBSD http://blog.philpep.org/post/Gitweb-fastcgi-lighttpd-et-FreeBSD Thu, 10 Sep 2009 22:04:31 GMT <p>Vu la galère pour mettre en place un gitweb sous lighttpd en fastcgi, voici un petit mémo pour moi et j'èspère qu'il servira à d'autres. (J'explique sous FreeBSD mais ça peut être transposé facilement sur d'autres OS)</p> <p>Donc, d'abord mettre en place git et lighttpd :</p> <div class="codehilite"><pre>make -C /usr/ports/devel/git install clean make -C /usr/ports/www/lighttpd install clean <span class="nb">echo </span><span class="nv">lighttpd_enable</span><span class="o">=</span><span class="se">\&quot;</span>YES<span class="se">\&quot;</span> &gt;&gt; /etc/rc.conf </pre></div> <p>Ensuite j'ai utilisé un script de la doc lighttpd.</p> <div class="codehilite"><pre>fetch http://philpep.org/pub/perl-cgi mv perl-cgi /usr/local/bin </pre></div> <p>Ce script utilise deux modules Perl qu'il faut installer, le premier (CGI::Fast) est dans les ports FreeBSD, mais je n'ai pas trouvé le second (Embed::Persistent) donc je l'ai installé "à la mano"</p> <div class="codehilite"><pre>make -C /usr/ports/www/p5-FastCGI install clean fetch http://search.cpan.org/CPAN/authors/id/D/DO/DOUGM/ExtUtils-Embed-1.14.tar.gz tar xvzf ExtUtils-Embed-1.14.tar.gz <span class="nb">cd </span>ExtUtils-Embed-1.14 perl Makefile.PL make make install </pre></div> <p>Ensuite la conf lighttpd : (je met tout dans /usr/local/www)</p> <div class="codehilite"><pre>cp /usr/local/share/examples/git/gitweb/gitweb* /usr/local/www cp /usr/local/share/examples/git/gitweb/*.png /usr/local/www </pre></div> <p>Et ceci dans /usr/local/etc/lighttpd.conf</p> <div class="codehilite"><pre><span class="c1"># /usr/local/etc/lighttpd.conf</span> <span class="k">server.port</span> <span class="o">=</span> <span class="m">80</span> <span class="k">server.bind</span> <span class="o">=</span> <span class="s2">&quot;10.0.0.3&quot;</span> <span class="k">server.username</span> <span class="o">=</span> <span class="s2">&quot;www&quot;</span> <span class="k">server.groupname</span> <span class="o">=</span> <span class="s2">&quot;www&quot;</span> <span class="k">server.document-root</span> <span class="o">=</span> <span class="s2">&quot;/usr/local/www/&quot;</span> <span class="k">server.event-handler</span> <span class="o">=</span> <span class="s2">&quot;freebsd-kqueue&quot;</span> <span class="k">server.pid-file</span> <span class="o">=</span> <span class="s2">&quot;/var/run/lighttpd.pid&quot;</span> <span class="k">index-file.names</span> <span class="o">=</span> <span class="p">(</span> <span class="s2">&quot;gitweb.cgi&quot;</span> <span class="p">)</span> <span class="k">server.errorlog</span> <span class="o">=</span> <span class="s2">&quot;/var/log/error_log&quot;</span> <span class="k">server.modules</span> <span class="o">=</span> <span class="p">(</span> <span class="s2">&quot;mod_setenv&quot;</span><span class="p">,</span> <span class="s2">&quot;mod_fastcgi&quot;</span><span class="p">,</span> <span class="s2">&quot;mod_rewrite&quot;</span><span class="p">,</span> <span class="p">)</span> <span class="k">fastcgi.server</span> <span class="o">=</span> <span class="p">(</span> <span class="s2">&quot;.cgi&quot;</span> <span class="o">=&gt;</span> <span class="p">((</span> <span class="s2">&quot;socket&quot;</span> <span class="o">=&gt;</span> <span class="s2">&quot;/tmp/application.fcgi.socket&quot;</span><span class="p">,</span> <span class="s2">&quot;bin-path&quot;</span> <span class="o">=&gt;</span> <span class="s2">&quot;/usr/local/bin/perl-cgi&quot;</span><span class="p">,</span> <span class="p">))</span> <span class="p">)</span> <span class="k">setenv.add-environment</span> <span class="o">=</span> <span class="p">(</span> <span class="s2">&quot;GITWEB_CONFIG&quot;</span> <span class="o">=&gt;</span> <span class="s2">&quot;/home/git/gitweb.conf&quot;</span><span class="p">,</span> <span class="p">)</span> <span class="c1"># Le petit rewrite qui fait bien</span> <span class="k">url.rewrite-once</span> <span class="o">=</span> <span class="p">(</span> <span class="s2">&quot;^/([a-zA-Z]+.git)(.*)$&quot;</span> <span class="o">=&gt;</span> <span class="s2">&quot;/gitweb.cgi/$1$2&quot;</span> <span class="p">)</span> <span class="k">mimetype.assign</span> <span class="o">=</span> <span class="p">(</span> <span class="s2">&quot;.png&quot;</span> <span class="o">=&gt;</span> <span class="s2">&quot;image/png&quot;</span><span class="p">,</span> <span class="s2">&quot;.css&quot;</span> <span class="o">=&gt;</span> <span class="s2">&quot;text/css&quot;</span><span class="p">,</span> <span class="c1"># default mime type</span> <span class="s2">&quot;&quot;</span> <span class="o">=&gt;</span> <span class="s2">&quot;application/octet-stream&quot;</span><span class="p">,</span> <span class="p">)</span> </pre></div> <p>Et voilà, un petit</p> <div class="codehilite"><pre><span class="sr">/usr/</span><span class="nb">local</span><span class="sr">/etc/</span><span class="n">rc</span><span class="o">.</span><span class="n">d</span><span class="o">/</span><span class="n">lighttpd</span> <span class="n">start</span> </pre></div>