Tous les articles par jbnahan

Pourquoi les auto-incréments sont dangereux ?

Serveurs
Source https://www.pxfuel.com/en/free-photo-ojibu

Lors du développement des sites web ou des applications web, nous utilisons une fonctionnalité courante dans les bases de données : l’auto-incrément.

L’auto-incrément est une colonne spéciale dans la base de données qui est alimentée par le moteur de base de données. Il est unique pour la table dans laquelle les données sont ajoutées. Il sert généralement de clé primaire (principale) pour charger des données précises.

La confidentialité

Le premier problème est la confidentialités. Ces clés primaires auto incrément sont utilisé par la suite dans les URL.

Prenons un exemple, votre entreprise propose un service dans lequel l’utilisateur peux enregistrer des données. Ces données sont stocké dans une base de données avec un auto incrément pour les retrouver plus tard. Cet auto incrément est utilisé dans l’URL pour afficher les données.

Je suis l’un de vos concurents et j’aimerai avoir une idée du volume d’utilisateur. Bien sûr vous ne donnez aucune indication sur les volumes que vous traitez. Et bien malgrè tout je peux en avoir une idée.

Pour cela, je m’inscrit comme un utilisateur, j’ajoute des données, puis j’attends un mois ou plus. Je reviens sur votre service et j’enregistre de nouvelles données.

Je récupère maintenant l’auto incrément présent dans les URL pour connaitre le volume de données enregistré sur la période sur votre service.

La sécurité

Comme je l’ai déjà dit dans la vidéo « Comment mon site a été piraté 2 fois (injection SQL)« , une URL avec un auto-incrément est dangereuse.

Continuons avec notre exemple données pour la confidentialité. Si je vais sur la page d’affichage des données. Et que je modifie l’auto-incrément présent dans l’URL pour mettre le précédent. Que ce passe-t-il ?

Si le site est sécurisé, j’ai droit à un message d’erreur m’indiquant un refus d’accès.

Et malheureusement dans de trop nombreux cas, je vois les données ! C’est une fuite de données qu’il faut déclarer à la CNIL et dont-il faut assumer les conséquences !

L’article de la CNIL sur le sujet « Sécurité des sites web : les 5 problèmes les plus souvent constatés » (point 3)

Mais ce n’est pas tout, il y a encore un autre risque. Dans le cas d’une faille de sécurité de type « Injection SQL » la présence d’auto incrément simplifie la tache des malveillants.

En effet, la colonne se nomme dans 90% (pourcentage arbitraire pour dire presque tout le temps) des cas id. Et pour la table des utilisateurs nommé « users » dans 80% des cas (toujours arbitraire mais c’est moins souvent) il est très simple d’exfiltrer la liste des utilisateurs.

Par quoi les remplacer ? Par un identifiant généré aléatoirement grâce à des fonctions de hachages fiables. Utilisez les mêmes que pour la cryptographie.

Je vous conseil les GUID ou UUID qui sont disponible dans tous les langages de programmation. C’est un texte de 36 caractères qu’il est possible d’utiliser en tant que clé primaire.

Malheureusement il n’est pas toujours possible de les utiliser en tant que clé primaire. Certaine logiciel de base de données ont des limites qui empêche de réaliser des liaisons entre table si les tables utilise des clés primaire trop longue.

Pour palier à ce défaut, vous pouvez modifier la configuration du logiciel de base de données. Mais dans la pire des situations qu’est l’hébergement mutualisé, vous n’aurez pas le choix d’utiliser un auto incrément pour réaliser la liaison.

Conclusion

La confidentialité (secret des affaires) est en jeu lors de l’utilisation d’un auto incrément, mais le plus grave reste la sécurité.

La sécurité permet de garantir l’intégrité des données, leur sécurités et leur confidentialité et ces 3 points sont abordés dans le RGPD. Tout manquement est donc punissable par la CNIL.

Vidéo

Vidéo Youtube « Pourquoi les auto-incréments sont dangereux ? »

[Tutoriel] Comment piloter Chrome avec Behat ?

Source https://www.pxfuel.com/en/free-photo-oclmc

Suite au succès de mon précédent tutoriel sur Behat, ce tutoriel est le premier d’une série consacrée au pilotage des navigateurs.

J’utilise le projet todo list disponible sur GitHub pour ce tutoriel.

Choix du navigateur

Avant de commencer, il est nécessaire de choisir le navigateur à utiliser pour l’exécution des tests. Pour ce premier tutoriel, nous allons utiliser Chromium sous Linux.

Il est possible de piloter un grand nombre de navigateurs pour ordinateur ou smartphone. Ce sera l’objet de prochains tutoriels.

Lancement du navigateur

Les navigateurs basés sur Chromium peuvent être pilotés directement par Behat grâce à l’extension Mink et le pilote Chrome dmore/chrome-mink-driver.

Avant de lancer Behat, il est nécessaire de lancer le navigateur avec les bonnes options pour que Behat puisse l’utiliser.

Chromium via snap

Commandes pour installer Snapd et Chrmium : apt-get install snapd
snap install core chromium

Le binaire à utiliser dans la commande ci dessous est : /snap/bin/chromium

Exécuter cette commande dans un terminal pour utiliser Chromium installé sur le système. Il faudra le laisser ouvert pendant toute la durée des tests.

chromium --enable-automation --disable-background-networking --no-default-browser-check --no-first-run --disable-popup-blocking --disable-default-apps --disable-translate --disable-extensions --no-sandbox --enable-features=Metal --remote-debugging-port=9222 https://127.0.0.1 

Pour mettre fin à l’exécution du navigateur, appuyer sur Ctrl + C.

Pour exécuter Chromium sans la fenêtre, ajouter l’option --headless.

Configurer le projet

Ce tutoriel part du principe que vous avez déjà installé Behat tel que présenté dans le précédent tutoriel. Si ce n’est pas le cas, réaliser l’installation avant de continuer.

Ajouter l’extension Behat et le driver Mink au projet:

composer require --dev dmore/behat-chrome-extension

Dans le fichier behat.yml.dist, ajouter la configuration suivante:

default:
    extensions:
        DMoreChromeExtensionBehatServiceContainerChromeExtension: ~
        BehatMinkExtension:
            base_url: "https://127.0.0.1:8000/"
            javascript_session: chrome_headless
            sessions:
                chrome_headless:
                    chrome:
                        api_url: "http://127.0.0.1:9222"
                        validate_certificate: false

Configurer les scénarii

Pour exécuter des scénarii avec un navigateur piloté, il est nécessaire d’ajouter le tag @javascript au début du fichier de fonctionnalité ou d’un scénario en particulier.

Exécuter les tests

Le navigateur est déjà lancé, il est nécessaire de lancer le serveur web. Pour cela j’utilise Rymfony (vidéo de présentation). Pour le lancer, exécuter APP_ENV=test rymfony serve -d depuis le dossier racine du projet.

Le projet utilise une base de données SQLite. Si votre projet a besoin d’un serveur MariaDb ou Postgres, lancez-le pour que votre projet ait accès aux données.

Voici le résultat en vidéo

Pour vous montrer le résultat obtenu, voici la vidéo de la réalisation de ce tutoriel sur le projet Todo list

Voir la vidéo : https://www.youtube.com/watch?v=VKZXb5yFYMA

Lancement de ma chaîne Youtube

Chaîne Youtube JB Dev Labs

Voilà maintenant quelques temps que je travaille sur le projet de chaîne Youtube. Abonnez-vous à ma chaîne JB Dev Labs ! Vous y trouverez mes réalisations personnelles et professionnelles (celles dont je peux parler).

Pour commencer, voici la présentation de Rymfony.

https://youtu.be/y0BEkzZZCmM

Malgré de très nombreux tests, tout n’est pas encore au point. Faites-moi vos commentaires sous la vidéo. Je les lirai tous !

Bon visionnage !

Cas pratique d’écriture d’un test automatique en français

Source: https://www.pxfuel.com/en/free-photo-jepee

Dans mon précédent article sur les tests automatisés, je parlais d’écrire les tests en français. Je vous ai présenté un test et parlé de son anatomie. Vous connaissez maintenant la base de la syntaxe Gherkin.

Des outils comme Cucumber et Behat permettent d’interpréter les fichiers de fonctionnalité (feature) contenant les scénarii de test.

Terminologie

Avant d’aller plus loin, un petit point terminologie, nous réalisons ici des tests d’acceptation. Il est courant d’entendre parler de tests fonctionnels mais ce terme peut s’appliquer à d’autres types de test.

Voyons maintenant comment écrire le scénario pour tester la connexion d’un utilisateur sur notre application web.

Déterminer les cas d’usage de la fonctionnalité à tester

Nous allons donc tester la connexion d’un utilisateur. Quelles sont les différentes situations qu’un utilisateur peut rencontrer lors de la connexion ?

Le premier cas est une connexion réussie avec son identifiant et son mot de passe.

Le deuxième cas est une connexion échouée en raison d’un mauvais mot de passe.

Le troisième cas est une connexion échouée en raison d’un identifiant inconnu.

Et c’est tout. Notre application n’utilise pas de double authentification et ne dispose pas de la mémorisation de l’utilisateur (remember me).

Déterminer les pré-requis, l’état initial du test

Maintenant que nous avons tous les cas de figure métier de la connexion d’un utilisateur, quel doit être l’état du système avant de commencer un cas de test ?

Le premier pré-requis est que nous devons ouvrir un navigateur Internet et charger la page de connexion d’un utilisateur sur notre application web.

Le second est qu’un utilisateur doit être présent en base de données pour permettre la réalisation de deux des scénarii.

Et c’est tout.

Déterminer ce qui sera vérifié

Maintenant, qu’allons-nous vérifier ?

Dans le cas d’une connexion réussie, nous devons arriver sur la page du compte de l’utilisateur.

Dans le cas d’une connexion échouée, nous devons être sur la page de connexion et le message « Identifiant ou mot de passe invalide ».

Pour des raisons de sécurité, la distinction entre un compte inconnu et un mot de passe erroné n’est pas affichée.

Écrire les scénarii

Maintenant, nous pouvons passer à l’écriture d’un fichier de fonctionnalité (feature).

#language fr
Fonctionnalité: Connexion d'un utilisateur

  Contexte:
    Etant donné que l'utilisateur "test" est enregistré avec le mot de passe "test123456!"
    Et que je suis sur la page de connexion

  Scénario: Connexion réussie
    Lorsque je me connecte en tant que "test" avec le mot de passe "test123456!"
    Et que je valide la connexion de l'utilisateur
    Alors je dois être sur la page du compte de l'utilisateur "test"

  Plan du Scénario: Identifiant incorrect
    Lorsque je me connecte en tant que "<identifiant>" avec le mot de passe "<mot_de_passe>"
    Alors je dois être sur la page de connexion
    Et le message d'erreur "Identifiant ou mot de passe incorrect" est visible

  Exemples:
    | identifiant | mot_de_passe |
    | test        | abracadabra  |
    | toto        | abracadabra  |

Avez-vous remarqué que j’ai regroupé les deux scénarii d’échec ? C’est une fonctionnalité de la syntaxe Gherkin. Il est possible de jouer plusieurs fois le même scénario avec des informations différentes.

Explication du fichier

Mais revenons au début du fichier. Si vous comparez avec ce que je vous ai montré dans mon précédent article, il y a beaucoup de chose en plus !

Contexte

A la ligne 1, nous trouvons la définition de la langue utilisée dans le fichier.

A la ligne 2, le terme « Fonctionnalité: » est un mot clé Gherkin qui lui indique le début du test d’une fonctionnalité. Le texte qui suit le mot clé est un commentaire (il peut être sur plusieurs lignes).

A la ligne 4, le terme « Contexte » indique que les phrases (ou étapes) qui suivent (ligne 5 et 6) doivent être réalisées avant chaque scénario de la fonctionnalité. Le contexte est très utile pour alléger les scénarii. Cela permet de disposer le système dans un état donné commun à toute la fonctionnalité.

Scénario simple

Le premier scénario débute à la ligne 6 et ressemble plus à ce dont j’ai parlé dans le précédent article.

Cependant, il y deux points que je souhaite vous montrer :

Les textes entre guillemets est celui qui sera saisi sur la page de connexion par l’outil de tests. Il est possible de récupérer ainsi des informations depuis les phrases permettant leur réutilisation.

A la ligne 10 (comme à la ligne 6 et 16), la phrase commence par le mot clé « Et que » (ou « Et »). Ce mot clé est utilisé en remplacement des autres mots clés pour éviter la répétition et obtenir un texte compréhensible.

Plan de scénario

A la ligne 13 nous découvrons le mot clé « Plan du Scénario ». Celui-ci indique à l’outil qu’il doit exécuter le scénario plusieurs fois en fonction d’un tableau de données.

Dans les phrases du plan, les éléments qui changent entre chaque exécution sont placés entre les signes « inférieur » et « supérieur ». Le texte présent entre ces deux signes désigne le nom de la colonne où trouver la donnée.

Les données en elles-mêmes sont présentées sou forme de tableau après le mot clé « Exemples » (ligne 18 et suivantes).

Récapitulons

Dans cet article, nous avons vu comment analyser une fonctionnalité et écrire un fichier de scénario contenant tous les cas que nous souhaitons tester.

Nous avons également découvert quelques mots clés supplémentaires nous permettant d’écrire des scénarii simples et concis.

La simplicité des phrases et la concision des tests permet à tous les intervenants de comprendre facilement et rapidement le fonctionnement de l’application.

Cadeau

Après avoir bien travaillé, je vous offre un cadeau. En plus d’avoir écrit un test qui sera exécuté avant chaque livraison de votre application, nous venons d’écrire de la documentation.

Oui, les tests d’acceptation (comme les autres d’ailleurs) font partie de la documentation de votre application.

La documentation fournie par les tests a la particularité d’être maintenue à jour. Il serait dommage de s’en priver.

Intéressé par le sujet ?

Merci d’avoir lu jusqu’à la fin ! Contactez-moi pour en discuter et restez connecté !

Quand les tests vous sauvent

Test
https://www.pxfuel.com/en/free-photo-ogmwi

Quand on parle de développement logiciel, nous pensons à du code, à des choses incompréhensibles, abstraites, à un homme barbu qui reste toute la journée devant son ordinateur.

Loin des clichés, qu’est-il possible de comprendre quand on n’a pas les connaissances ?

En un mot : les tests.

Quels sont les tests qu’un chef de produit peut comprendre sans entrer dans la technique ?

Il existe plusieurs façons de réaliser des tests. La méthode que vous connaissez sûrement et que vous pratiquez, c’est l’utilisation du produit.

Réaliser des tests manuels sera toujours nécessaire. Ils ne doivent pas être sous-évalués.

Mais vous est-il arrivé de retomber sur un bug déjà corrigé quelque temps plus tôt ? Vous est-il déjà arrivé d’être lassé de réaliser toujours les mêmes tests ?

Sûrement ! Et c’est normal ! L’être humain n’est pas une machine. Il a même inventé des machines pour se débarrasser des tâches répétitives.

C’est la même chose avec les projets informatiques. Il est possible d’automatiser la réalisation des tests tout en vous permettant de comprendre.

Écrire des tests en langage naturel

Oui, il est possible d’écrire des tests en langage naturel moyennant un certain formalisme.

Ainsi le scénario suivant est correct:

Étant donné que je suis sur la page d’accueil du blog de Jean-Baptiste Nahan
Lorsque je clique sur « PHP 8 » dans le menu
Alors je suis sur la liste des articles disposant du tag « PHP 8 »

Comprenez-vous ce qui se passe lors de l’exécution de ce scénario ?

Il est possible de formaliser tous vos tests ainsi !

Anatomie du test

L’exemple est très court, mais est composé des éléments clés :

La phrase commençant par « Étant donné que » indique un prérequis, une situation préétablie. Elle ne se trouve en général qu’au début d’un scénario de test. Dans l’exemple, le prérequis est que le navigateur soit ouvert sur la page d’accueil de mon site.

La phrase commençant par « Lorsque », indique l’action que vous réalisez. Le résultat de cette action sera vérifié plus tard. Dans l’exemple, le testeur clique sur le lien nommé « PHP 8 » situé dans le menu du site.

Enfin la phrase commençant par « Alors » indique ce que l’on attend, ce qui est vérifié. Dans l’exemple, tous les tags des articles présents sur la page seront récupérés, puis la présence du tag « PHP 8 » sera vérifiée sur chacun d’eux. Si un article n’a pas le tag, alors une erreur sera levée et le test échouera.

Transcription

Bien que vous écriviez en langage naturel et en français (oui, ça fonctionne dans toutes les langues), il n’y a rien de magique.

Un développeur devra écrire du code pour chaque phrase permettant la réalisation des actions, et la vérification des attendus.

Ils vous sauveront

La mise en place de ces tests prend du temps, ce serait une erreur de le négliger. Mais ils vous sauveront !

Après la phase de mise en place et d’écriture des scénarii, vous pourrez demander à votre équipe de développeurs d’exécuter les tests périodiquement. Avant une mise en production par exemple, ou avant chaque modification (c’est utile pour certains projets). Quand vous le souhaitez.

À plusieurs reprises les tests m’ont épargné de très grosses galères, et je trouve dommage que vous ne puissiez pas en profiter pour vous économiser du temps et de nombreuses galères, et surtout gagner en qualité.

Intéressé par le sujet ?

Contactez-moi pour en discuter et restez connecté !

Bonne année 2021 !

Développement d'un logiciel (Tous droits réservé 2021 - Jean-Baptiste Nahan)
Développement d’un logiciel (Tous droits réservés 2021 – Jean-Baptiste Nahan)

Après une année 2020 très particulière sur de nombreux points, voici que l’année 2021 arrive avec son lot d’espoirs et de défis.

Que s’est-il passé pour moi en 2020 ?

Cela fait maintenant 4 ans et demi (oui c’est important à cet âge-là) que je maintiens l’extension Win32Service pour PHP. La version 1.0 est sortie peu de temps après PHP 8.0. N’hésitez pas à me contacter pour venir en discuter.

C’est également en 2020 que j’ai commencé à utiliser le langage Rust pour écrire des logiciels. Après quelques contributions au logiciel Rymfony (clone libre de Symfony Cli), j’ai entamé un projet écrit en Rust (plus de détails en 2021).

En 2020, j’ai découvert un nouveau concept pour améliorer l’écriture de test Behat et particulièrement les contextes. Je l’utilise régulièrement et c’est un vrai plaisir.

Côté sécurité, j’ai utilisé ma première clé de sécurité physique SoloKeys. Elles ont la particularité d’être Open Source.

La carte MicroSD du RaspBerry Pi qui me permet de faire le télérelevé client de mon compteur Linky a décidé de ne plus fonctionner.

A quoi s’attendre en 2021 ?

N’étant pas coutumier de la prédiction, je me limiterai à des événements fortement probables.

Je peux prédire la version 8.1 de PHP et avec elle sûrement une nouvelle version de l’extension Win32Service.

Il y aura sûrement des informations sur mon projet écrit en Rust. Je peux vous dire qu’il est dans un domaine que j’aime particulièrement dans le développement logiciel.

Bien sûr il y aura des projets dont j’ignore encore l’existence et qui me passionneront !

Et vous quelles sont vos prédictions pour 2021 ?

Win32Service 1.0.0 is available

Win32Service Logo
Win32Service Logo

The new version 1.0.0 of Win32Service extension for PHP is available.

Or

Win32Service is a PHP extension. The version 0.4.x is for PHP7 and the version 1.0.x is for PHP8. This extension provides a simple way to run your PHP script like a service into the Windows Service Manager. Win32Service is same as supervisorD or SystemD for Linux.

The PHP documentation for win32service is up to date.

The v1.0.0 change log

  • Add Win32ServiceException (extends Exception)
  • The return value is no longer false when call method with wrong parameters
    • win32_start_service_ctrl_dispatcher
    • win32_set_service_exit_mode
    • win32_set_service_exit_code
    • win32_set_service_status
    • win32_create_service
    • win32_delete_service
    • win32_get_last_control_message
    • win32_query_service_status
    • win32_start_service
    • win32_stop_service
    • win32_pause_service
    • win32_continue_service
    • win32_send_custom_control
  • Add check in array information provided to win32_create_service. On error, this method throw a ValueError.
  • For function win32_send_custom_control, the PHP error The control argument value is not between 128 and 255. is now throw on ValueError.
  • For all function needed the service name, a ValueError is throw if the string is empty.
  • The PHP Error This function work only when using the CLI SAPI and called into the service code. has been converted to Win32ServiceException for this method
    • win32_start_service_ctrl_dispatcher
    • win32_set_service_exit_mode
    • win32_set_service_exit_code
    • win32_set_service_status
    • win32_get_last_control_message
  • The PHP Warning Service ctrl dispatcher already running has been converted to Win32ServiceException.
    This exception is throw if function win32_start_service_ctrl_dispatcher is called when the control dispatcher is already started.
  • The PHP Warning Failed to start dispatcher thread has been converted to Win32ServiceException.

Edit on December 1, 2020 : I have updated this blog post to add download pre-built DLL links.

More blogpost about Win32Service

Win32Service 1.0.0-alpha2 is available

Win32Service Logo
Win32Service Logo

The new version 1.0.0-alpha2 of Win32Service extension for PHP is available for test.

Win32Service is a PHP extension. The version 0.4.x is for PHP7 and the version 1.0.x is for PHP8. This extension provides a simple way to run your PHP script like a service into the Windows Service Manager. Win32Service is same as supervisorD or SystemD for Linux.

The v1.0.0-alpha2 change log

  • Add Win32ServiceException (extends Exception)
  • The return value is no longer false when call method with wrong parameters
    • win32_start_service_ctrl_dispatcher
    • win32_set_service_exit_mode
    • win32_set_service_exit_code
    • win32_set_service_status
    • win32_create_service
    • win32_delete_service
    • win32_get_last_control_message
    • win32_query_service_status
    • win32_start_service
    • win32_stop_service
    • win32_pause_service
    • win32_continue_service
    • win32_send_custom_control
  • Add check in array information provided to win32_create_service. On error, this method throw a ValueError.
  • For function win32_send_custom_control, the PHP error The control argument value is not between 128 and 255. is now throw on ValueError.
  • For all function needed the service name, a ValueError is throw if the string is empty.
  • The PHP Error This function work only when using the CLI SAPI and called into the service code. has been converted to Win32ServiceException for this method
    • win32_start_service_ctrl_dispatcher
    • win32_set_service_exit_mode
    • win32_set_service_exit_code
    • win32_set_service_status
    • win32_get_last_control_message
  • The PHP Warning Service ctrl dispatcher already running has been converted to Win32ServiceException.
    This exception is throw if function win32_start_service_ctrl_dispatcher is called when the control dispatcher is already started.
  • The PHP Warning Failed to start dispatcher thread has been converted to Win32ServiceException.

The release 1.0.0-alpha2 on the GitHub project

The next version of Win32Service

Win32Service Logo
Win32Service Logo

I work in my free time to improve the win32service extension to make it great and easier to use. The future version is 1.0.0 only for PHP 8.

I’m excited about this future version.

What is the planned changes?

This extension needs a little cleanup. In many cases, the Windows version is checked. All this check will be removed because VS16 is used to build PHP 8 and this extension works only on Windows 7 SP1 and newer or Windows 2012 R2 or newer.

With PHP 8 a new ValueError exception is available. Many checks will be added to improve the work of this extension. Especially the win32_create_service function.

And the last, same as many other functions in PHP extensions, all function who returns an error code will be changed to throw an exception. All PHP Errors and some PHP Warning will be changed by throwing an exception.

What is the side effect to change?

You need to change your code when you upgrade your project to PHP 8.

The Win32Service project provides a PHP library and a Symfony Bundle. Both will be upgraded to PHP 8 on a new major version.

My Actual To-do List

All this plan needs more work. This is my to-do list but you can help me.

  • Upgrade the extension code.
  • Write more tests for the extension.
  • Update the English PHP documentation for Win32Service.
  • Update the French PHP documentation for Win32Service.
  • Update the PHP library win32service/service-library.
  • Update the Symfony Bundle win32service/win32servicebundle.
  • Update the example project.

Help me

You can help me in many ways:

You are interested in this project, but you cannot help in this way, you can buy a day of work. Please contact me.

Or ping me to encourage me.

Comment ne plus penser à PHP CS Fixer

PHP CS Fixer c’est quoi ? A quoi sert PHP CS Fixer ?

PHP CS Fixer est un outil permettant de vérifier et corriger le formatage du code PHP selon le code style défini dans la configuration du projet (fichier .php_cs.dist ou .php_cs).

Le style code est une convention qui définit comment doit être écrit le code. Par exemple l’emplacement des accolades des structures de contrôle, des classes, des fonctions, les espaces autour d’un signe égal, etc.

Cela permet de faciliter la lecture du code pour tout le monde.

Le PHP-FIG a défini plusieurs conventions dont la dernière en date est la PSR-12. Il existe également des conventions plus spécifiques comme le Coding Standards de Symfony.

Pourquoi ne plus y penser ?

Le style de code est une nécessité, mais très franchement c’est frustrant quand l’intégration continue échoue à cause du style code.

Tout comme voir des messages de commit tels que fix style code, fix cs ou cs ou bien d’autre encore.

Il existe une solution pour ne plus y penser et l’appliquer tout de même, le hook (crochet) GIT pre-commit.

Un hook (crochet en français) est un point d’extension d’une application permettant à l’utilisateur d’exécuter des actions qu’il a lui-même définies. En général, ce sont des scripts Shell.

Pré requis

Cette procédure a été écrite pour les systèmes GNU/Linux. La compatibilité pour les Mac est quasi assurée. Pour Windows, il est nécessaire d’adapter la procédure au système.

PHP 7 et PHP CS Fixer doivent être installé sur le poste qui exécute les commandes GIT. Si PHP CS Fixer n’est pas installé, suivre la procédure d’installation globale manuelle.

Pour ce blog post, PHP CS Fixer est installé à cet emplacement /usr/local/bin/php-cs-fixer. Pour connaitre l’emplacement du binaire exécuter la commande type php-cs-fixer.

Le projet sur lequel vous choisissez de définir ce hook contient déjà une configuration pour PHP CS Fixer (fichier .php_cs.dist ou .php_cs).

Ajout d’un hook sur un dépôt

Pour ne pas perturber les projets qui ne dispose pas de configuration ou qui n’ont pas de fichier PHP, le hook vérifie la présence du fichier de configuration .php_cs.dist et n’appliquera les modifications que sur les fichiers PHP inclus dans le commit.

Pour l’ajouter, se placer dans le dossier de votre projet puis ouvrir le fichier .git/hooks/pre-commit (il peut déjà exister ou devra être ajouté).

Puis coller le contenu du script suivant :

#!/bin/sh

ROOT=$(dirname "$0")
ROOT=$(dirname "$ROOT")
ROOT=$(dirname "$ROOT")

echo "php-cs-fixer pre commit hook start"

# Modifier le chemin de PHP CS Fixer ici si votre binaire n'est pas installé au même endroit :
PHP_CS_FIXER="/usr/local/bin/php-cs-fixer"

HAS_PHP_CS_FIXER=false

if [ -x  "$PHP_CS_FIXER" ]; then
    HAS_PHP_CS_FIXER=true
else
    echo "PHP CS Fixer not installed into $PHP_CS_FIXER"
fi

#PHP_CS_CONFIG=

for file in .php_cs.dist .php_cs
do
    if [ -f "$ROOT/$file" ]; then
        echo PHP CS Fixer config file found in projet at $file
        PHP_CS_CONFIG=$file
    fi
done

if [ "x$PHP_CS_CONFIG" = "x" ]; then
    echo "No PHP CS Fixer config file found !"
    HAS_PHP_CS_FIXER=false
fi

if $HAS_PHP_CS_FIXER; then
    git status --porcelain | grep -e '^[AM]\(.*\).php$' | cut -c 3- | while read line; do
        $PHP_CS_FIXER fix --config=$ROOT/$PHP_CS_CONFIG --verbose "$line";
        git add "$line";
    done
else
    echo ""
    echo "Please install php-cs-fixer, see:"
    echo ""
    echo "  https://github.com/FriendsOfPHP/PHP-CS-Fixer#installation"
    echo ""
fi

echo "php-cs-fixer pre commit hook finish"

Il est nécessaire de s’assurer que ce fichier est exécutable grâce à cette commande : chmod u+x .git/hooks/pre-commit.

Exécuter la commande dans un terminal après s’être placé dans le dossier de votre projet.

Pour tester son efficacité, modifier le placement d’accolade dans un fichier PHP du projet puis ajouter un commit.

PHP CS Fixer est exécuté sur chaque fichier modifié pour corriger le style code avant le commit.

Ajout d’un hook pour tous les dépôts

Maintenant que notre hook fonctionne, nous pouvons l’ajouter au modèle de dépôt GIT. Ainsi tout nouveau dépôt disposera du hook.

La première étape consiste à définir un dossier de template pour les nouveaux dépôts GIT.

Exécuter la commande git config --global init.templatedir '~/.git-templates'

Le dossier n’existant pas, nous allons l’ajouter à notre dossier utilisateur avec cette commande mkdir -p ~/.git-templates/hooks

Toujours depuis le dossier du projet où le hook a été ajouté exécuter la commande suivante pour copier le hook cp .git/hooks/pre-commit ~/.git-templates/hooks/

Cette fois, nous allons nous assurer que tout le monde peut l’exécuter avec cette commande : chmod a+x ~/.git-templates/hooks/pre-commit.

Ajouter le hook sur un dépôt existant

Maintenant que le hook est dans le template de GIT, il est possible de l’ajouter à un projet existant en exécutant la commande : git init dans le dossier du projet.

Pour les dépôts ayant déjà un hook pre-commit, il ne sera pas modifié.

Besoin d’aide pour mettre en place cette solution ? Contactez-moi !

Il est nécessaire de s’assurer que ce fichier est exécutable grâce à cette commande : chmod u+x .git/hooks/pre-commit.

Exécuter la commande dans un terminal après s’être placé dans le dossier de votre projet.

Pour tester son efficacité, modifier le placement d’accolade dans un fichier PHP du projet puis ajouter un commit.

PHP CS Fixer est exécuté sur chaque fichier modifié pour corriger le style code avant le commit.