WebHook Google Code – recevoir un mail à chaque commit

Dans Google code il y a la possibilité d’utiliser un gestionnaire de version tel que subversion (svn) ou mercurial (hg). C’est bien pratique, mais malheureusement, de base, rien n’est prévu pour prévenir (excepté par flux RSS) les gens de ces mises à jour. Cependant, Google code permet d’utiliser un webhook en post commit.

Qu’est-ce qu’un webhook?

Un webhook c’est un « crochet web », c’est-à-dire une URL a appelée après (avant ou pendant) une action X. Dans notre cas, après chaque commit une URL est appelée.

Utilisation

Voici un exemple de code que j’utilise pour plusieurs de mes projets :

<?php
// project name
$projects = array('mon-super-projet');
 
// google code webhook key
$keys = array(
	'b-box'	=> 'Top-Secret_key_fourni_par_google-dans-l-adminsitration'
);
 
//user agent from google code
$useragent = 'Google Code Project Hosting (+http://code.google.com/p/support/wiki/PostCommitWebHooks)';
 
//email of all owner (eg. project chief)
$owners = array('vous@example.com');
 
//email of all team members except owners
$users = array('toi@example.com');
 
//sender of email
$sender = 'WebHook mailer<webmaster@exemple.com>';
 
//----------------------------------------------------------------------
$project = (isset($_GET['p']))?$_GET['p']:'';
$revision = (isset($_GET['r']))?intval($_GET['r']):-99;
$data = file_get_contents('php://input');
$digest = (isset($_SERVER['HTTP_GOOGLE_CODE_PROJECT_HOSTING_HOOK_HMAC']))?$_SERVER['HTTP_GOOGLE_CODE_PROJECT_HOSTING_HOOK_HMAC']:'';
 
//----------------------------------------------------------------------
/**
 * Send a mail
 * @param string $from email of the sender : sample@example.com or "name"<sample@example.com>;
 * @param array $to [a] => list of email [cc], [bcc] (hidden), ...
 * @param string $subject
 * @param string $body
 * @return bool true if success
 */
function mailer($from, array $to, $subject, $body)
{
	if (empty($to))
	{
		return false;
	}
 
	$headers = 'From: ' . $from . "\n";
 
	$a = '';
 
	if (isset($to['a']) &amp;&amp; !empty($to['a']))
	{
		$a = implode(',', $to['a']);
	}
 
	if (isset($to['bcc']) &amp;&amp; !empty($to['bcc']))
	{
		$headers .= 'Bcc: ' . implode(',', $to['bcc']) . "\n";
	}
 
	if (isset($to['cc']) &amp;&amp; !empty($to['cc']))
	{
		$headers .= 'Cc: ' . implode(',', $to['cc']) . "\n";
	}
 
	$headers .= 'MIME-Version: 1.0' . "\n";
	$headers .= 'Content-Type: text/plain; charset="UTF-8"' . "\n";
	$headers .= 'Content-Transfer-Encoding: 8bit' . "\n";
	$headers .= 'X-Mailer: PHP/' . phpversion();
 
	return mail($a, '[webhook]' . $subject, $body, $headers);
}
 
function failed($test_id, $msg)
{
	global $sender, $owners;
 
	$msg .= "\n--\nWebHook mail from the Google code project";
 
	mailer($sender, array('bcc' => $owners), 'failed test #' . $test_id, $msg);
 
	die('KO');
}
 
function get_ip()
{ 
	return (isset($_SERVER['HTTP_X_FORWARDED_FOR']))?$_SERVER['HTTP_X_FORWARDED_FOR']:(isset($_SERVER['HTTP_CLIENT_IP']))?$_SERVER['HTTP_CLIENT_IP']:$_SERVER['REMOTE_ADDR'];
}
 
//----------------------------------------------------------------------
if ($useragent != $_SERVER['HTTP_USER_AGENT'])
{
	// failed 1
	failed(1, 'User agent is bad : ' . htmlspecialchars($_SERVER['HTTP_USER_AGENT']) . "\n\nFrom : " . get_ip());
}
elseif (empty($project) || !in_array($project, $projects))
{
	// failed 2
	failed(2, 'No project set : ' . htmlspecialchars($project) . "\n\nFrom : " . get_ip());
}
else
{
	$hmac = hash_hmac('md5', $data, $keys[ $project ]);
	$data = json_decode($data, true);
 
	if (empty($digest) || $digest != $hmac)
	{
		// failed 3
		failed(3, 'Bad digest : ' . $digest . ' vs ' . $hmac . "\n\nFrom : " . get_ip());
	}
	elseif (intval($data['revision_count']) != count($data['revisions']))
	{
		// failed 4
		failed(4, 'Bad count : ' . count($data['revisions']) . ' vs ' . intval($data['revision_count']) . "\n\nFrom : " . get_ip());
	}
	else
	{
		$mail_body = '';
		foreach($data['revisions'] as $_revision)
		{
			$mail_body .= 'Revision : ' . "\t" . htmlentities($_revision['revision']) . ' from ' . htmlentities($_revision['author']) . ' at ' . date('Y-m-d H:i', intval($_revision['timestamp'])) . "\n";
			$mail_body .= 'Added : ' . "\t" . implode("\n\t\t", htmlentities($_revision['added'])) . "\n";
			$mail_body .= 'Modified : ' . "\t" . implode("\n\t\t\t", htmlentities($_revision['modified'])) . "\n";
			$mail_body .= 'Removed : ' . "\t" . implode("\n\t\t\t", htmlentities($_revision['removed'])) . "\n\n";
//			$mail_body .= 'URL : ' . "\t\t" . htmlentities($_revision['url']) . "\n\n";
			$mail_body .= 'Message : ' . "\t" . htmlentities($_revision['message']) . "\n\n\n";
//			$_revision['path_count'];
		}
		$mail_body .= "\n--\nWebHook mail from the Google code project : " . $project . "\nhttp://code.google.com/p/" . $project . "/\n";
 
		mailer($sender, array('bcc' => $owners + $users), '[' . $project . ']New revision #' . $revision, $mail_body);
	}
}
 
exit('OK');
 
# EOF

Plus d’info : PostCommitWebHooks

Wampserver : quick switch xdebug menu

Pour une fois, un article sous Ms Windows. Stage oblige, je passe du temps sous celui-ci (XP 🙁 ). Afin d’optimiser son travail, il y a parfois des petites choses bien pratiques, telles que ce que je vais vous présenter.

XDebug est un outil merveilleux, parfois capricieux, certes, mais très utile. Il permet, notamment1 :

  • Affichage de tracé d’erreur
  • Meilleures lectures des exceptions
  • Débogage pas-à-pas
  • Profiling d’application

Bref, des choses essentielles en développement. Et, contrairement à ce que certains IDE2 font, il permet surtout de le faire sur un serveur « réel », donc avec une utilisation « réel ».

Le but de ce billet n’est pas de présenter XDebug, d’autres le font mieux que moi 3, mais bien de vous présenter un petit script vous permettant d’activer et désactiver XDebug sur wampserver.

Installation

  1. Téléchargez le fichier 4 et décompressez-le.
  2. Suivez les instructions d’installation décrite dans le fichier installe. Il y a seulement 1 fichier à modifier + 1 fichier par version de PHP installée.
  3. Relancer wampserver et tester!

Si vous avez des questions, n’hésitez pas.

Plus d’informations

  1. On parle de serveur web avec PHP …
  2. Par exemple, Zend Studio permet un débogage pas à pas mais en interne donc réduit …
  3. cf. plus d’informations
  4. XDebug quick switch menu for wampserver

[note]Zend Framework et dojo : auto-complétion

Ceci est une note rapide … j’espère produire un article plus intéressant une autre fois …

Nous allons regarder les bases de l’auto-complétion  avec ZF et Dojo. Dojo simplement parce qu’il est le mieux intégré des frameworks javascript. Sachant que pour l’instant seul jQuery et Dojo sont intégré

Le code

application/views/scripts/test/index.phtml

<?php
$this->dojo()->enable();	//activation de dojo
 
echo $this->comboBox(
	'toto',	//id html de l'élément
	'',	//valeur par défaut
	array(
		'autocomplete'	=> true,								//activation de l'auto-complétion
		'store'		=> 'stateStore',
		'storeType'		=> 'dojo.data.ItemFileReadStore',
		'storeParams'	=> array('url' => $this->baseUrl('/test/records')),	//url où les données JSON sont récupérée
		'searchAttr'		=> 'title',								//donnée recherchée pour remplir le combobox
	)
);
?>

application/layoutes/scripts/layout.phtml

// ...
		if ($this->dojo()->isEnabled())	//Évite les chargement inutile ....
		{
			$this->dojo()->setDjConfigOption('isDebug', (APPLICATION_ENV == 'development'));	//affiche une console de deboguage si on est en mode dev
			$this->dojo()->setDjConfigOption('usePlainJson', true);						//utilise du json texte
			$this->dojo()->setLocalPath($this->baseUrl('/themes/js/dojo/dojo/dojo.js'));			//chemin vers les fichier dojo
			$this->dojo()->addStyleSheetModule('dijit.themes.tundra');					//thème à chargé
			echo $this->dojo();												//affichage du tout ...
		}
// viennent ensuite nos jabvascript, css, etc
//...
//</head>
// ne pas oublier la class tundra dans le body
<body class="tundra">
//...

application/Bootstrap.php

//...
//dans _initView()
		//dojo
		Zend_Dojo::enableView($view);
//...

application/controllers/TestController.php

<?php
 
class TestController extends Zend_Controller_Action
{
	public function indexAction()
	{
	}
 
	public function recordsAction()
	{
		// on désactive l'affichage
		$this->_helper->layout()->disableLayout();
 
		//on va cherchée les données et les met dans un objet Zend_Dojo_Data
		$book = new Default_Model_DbTable_Book();
		$dojo = new Zend_Dojo_Data('title', $book->fetchAll());
		echo $dojo->toJson();
 
		// on sort ... c'est pas joli mais en attendant cela fonctionne!
		exit();
	}
}
 
# EOF

Choses à retenir comprendre

Les choses à retenir :

  • storeParams est l’url où les donnée au format JSON seront prise
  • searchAttr est l’élément qui va servir pour recherchée les données dans la masse de donnée JSON
  • ne pas oublier de mettre la class css ‘tundra’
  • Dojo peut, via ses styles css modifier votre rendu …

Remarque

Version de ZF : 1.9.6

Version de Dojo (fourni avec zf dans extras) : 1.3

Zend Framework aide de vue partialLoop et cycle

Il y a des moment où l’on se dit que la doc est vraiment incomplète … Voici un exemple assez tordu…

Rappel

  • L’aide de vue (view helper)  cycle permet d’alterner des valeurs dans la vue,
  • L’aide de vue partialLoop permet de faire une boucle sur une vue (fichier) afin de l’incorporer dans un autre fichier…

Utilisation

Pour utiliser les deux ensembles, par exemple dans le cas d’un listing dont la sortie serait dans un tableau, il vous suffit de définir les valeurs assigner au cycle avant de faire le partialLoop.
Exemple :
Vue views/scripts/membres/listing.phtml

<table class="table">
	<thead>
		<tr>
			<th>Nom</th>
			<th>Prénom</th>
			<th>Adresse</th>
			<th>Code postal</th>
			<th>Ville</th>
			<th>Pays</th>
			<th>Téléphone</th>
		</tr>
	</thead>
	<tbody>
	<?php
		$this->cycle()->assign(array('tr_1', 'tr_2', 'tr_3'), '_user_listing');
		echo $this->partialLoop('utilisateurs/_user_list_listing.phtml', $this->entries);
	?>
	</tbody>
</table>

Vue views/scripts/utilisateurs/_user_list_listing.phtml

<tr class="<?php echo $this->cycle(array(),'_user_listing')->next()?>">
	<td><?php echo $this->escape($this->name) ?></td>
	<td><?php echo $this->escape($this->firstName) ?></td>
	<td><?php echo $this->escape($this->Addrese) ?></td>
	<td><?php echo $this->postCode ?></td>
	<td><?php echo $this->escape($this->cityName) ?></td>
	<td><?php echo $this->escape($this->countryName) ?></td>
	<td><?php echo $this->tel_prefix ?></td>
</tr>

Openvibe everywhere in the future?

Pour le titre j’aurais pu mieux faire 😉 Donc commençons ma réflexion du jour …

Openvibe est un logiciel permettant de faire du BCI c’est-à-dire un logiciel permettant d’utiliser sont cerveaux comme interface d’accès à un ordinateur remplaçant ainsi une souris ou un clavier… Les ondes qu’émet le cerveau sont captés par des capteurs et traité en un signal utilisable pour le logiciel d’interphasage. Ce genre de logiciel permet le contrôle -expérimental- de chaise roulante ou d’un tas d’autres trucs …. (suffit de chercher et youtube regorge de vidéo à ce sujet).

Ceci fait très sciences-fiction mais c’est la réalité d’aujourd’hui et se sera le quotidien de demain, sachant qu’il existe déjà des produits commerciaux pour jouer! Mais côté sciences-fiction cela n’est rien comparé à l’ordinateur biologique! Ordinateur fonctionnant avec une interaction d’enzyme et d’ADN. D’après ce que j’ai lu, les dernières recherches en était « seulement » à la conception de puce mémoire stockant l’information sur l’ADN.

À force de voir ce genre de choses j’en vient à me dire que dans le futur les interfaces BCI devrait se généraliser et permettre ainsi d’imaginer un téléphone dont le clavier serait supprimé et où il ne resterait que : un haut parleur et un micro … ou encore, avec la bio-informatique, l’homme bio-informatisé, et pourquoi pas tel qu’on le voit dans les livres de Hamilton (L’étoile de pandore), des « tatouage » informatique permettant d’étendre les possibilités de l’homme!

Voilà c’était la petite réflexion du jour, le délire futuris d’un fou, maintenant j’attends vos commentaires … ou alors j’écouterai vos ricanements ou vos pas lorsque vous vous encourerez.

ps : oui je sais aucune référence …. mais j’ai la flemme ….