paint-brush
Utiliser Git Hooks avec MySQLpar@yuridanilov
4,711 lectures
4,711 lectures

Utiliser Git Hooks avec MySQL

par Yuri Danilov7m2023/09/30
Read on Terminal Reader

Trop long; Pour lire

Créer une base de données de test Créer un git hook après la réception Exécuter des scripts SQL en push
featured image - Utiliser Git Hooks avec MySQL
Yuri Danilov HackerNoon profile picture
0-item
1-item

Les systèmes de contrôle de version, et Git en particulier, sont des outils essentiels pour suivre les modifications de code, collaborer avec votre équipe et garantir la stabilité de votre base de code. Bien que Git soit principalement conçu pour le code source, vous pouvez également l'utiliser en combinaison avec des bases de données MySQL pour le contrôle de version et la gestion des modifications de schéma.


Dans cet article, nous explorerons comment intégrer Git à MySQL pour le contrôle de version à l'aide de hooks Git, avec des exemples spécifiques sous forme de guide. Tous les scripts donnés dans les listes sont entièrement fonctionnels et complets. Vous pouvez les reproduire séquentiellement dans votre environnement de test.


Tout d’abord, créons une base de données de test et un utilisateur :

 create database testdb_remote; create user 'user_remote'@'localhost' identified WITH mysql_native_password by 'remote123'; grant all on testdb_remote.* to 'user_remote'@'localhost'; 


Création d'une base de données de tests


Ensuite, nous allons créer un référentiel distant. Il peut s'agir d'un référentiel sur n'importe quel serveur distant, mais pour plus de simplicité, nous allons le créer localement. Pour faciliter l'exécution des commandes, j'utilise git bash. Ma machine locale possède déjà un dossier git, je l'utilise donc :

 cd /c/git mkdir testdb.remote cd testdb.remote git init --bare 


Création d'un dépôt distant

Et créez un référentiel local en tant que clone du référentiel distant :

 cd /c/git git clone /c/git/testdb.remote testdb.local cd testdb.local git ls-files 


Créer un dépôt local


Il n'y a aucun fichier dans le référentiel ; Créons-en un et transférons nos modifications au dépôt distant :

 echo "Test DB repo" > readme.md git status git add . git commit -m "1st commit" git push 


Première poussée


Vérifions le contenu du référentiel distant :

 cd /c/git/testdb.remote git ls-tree --full-tree -r HEAD 


Fichier dans un dépôt distant


Il existe un dossier hooks dans le référentiel distant, qui contient plusieurs fichiers avec des exemples :

 ls -1 /c/git/testdb.remote/hooks 


Exemples de crochets


Les hooks sont des scripts exécutés lorsque des événements spécifiques se produisent. Git a des hooks côté client et côté serveur. Les hooks côté client sont déclenchés par des opérations telles que la validation et la fusion. Les hooks côté serveur s'exécutent sur des opérations réseau telles que la réception de validations poussées. Les crochets sont décrits en détail ici . Il existe différentes options pour implémenter la logique ; Je vais donner un exemple d'utilisation du hook côté serveur après réception .


Dans le dossier hooks, nous devons créer un fichier nommé « post-receive », il s'agit d'un script bash classique :

 #!/bin/sh while read oval nval ref do echo List of files changed in the commit: git diff --name-only $oval $nval done


Le script ci-dessus sera exécuté sur le serveur chaque fois qu'un push sera terminé avec succès et affichera une liste de fichiers modifiés. Vérifions comment cela fonctionne en ajoutant une ligne au fichier readme.md et en transférant les modifications vers le référentiel distant :

 cd /c/git/testdb.local echo "New line" >> readme.md git add . git commit -m "Line added" git push 


Test du script hook post-réception


Vous pouvez voir que lors de l'exécution de la commande git push, la sortie contient désormais des lignes commençant par remote: - c'est la sortie du script de post-réception qui a été exécuté sur le serveur.

En parlant de changements fondamentaux, les fichiers peuvent être ajoutés, modifiés et supprimés. Vous pouvez adopter différentes approches pour appliquer ces modifications à la base de données :


  1. Apportez des modifications à la base de données uniquement lors de l'ajout de nouveaux fichiers. Dans ce cas, vous pouvez enregistrer toutes les modifications apportées à une tâche spécifique dans un seul fichier. Ce fichier peut contenir le nom de la tâche du système de suivi des bugs. Cela n’est peut-être pas très pratique pendant le développement, mais de tels changements sont plus faciles à gérer.
  2. Conservez un fichier séparé dans le référentiel pour chaque objet (tables, procédures) et appliquez les modifications à la base de données lors de la modification ou de l'ajout de fichiers.
  3. Une approche plus complète consiste à créer un dossier distinct pour chaque tâche (demande de modification) et à y placer les fichiers qui doivent être exécutés dans le cadre de l'installation d'une version donnée. Créez en parallèle un fichier supplémentaire décrivant la liste des fichiers et l’ordre dans lequel ils doivent être installés. Cette approche est plus flexible mais, en même temps, plus complexe tant pour le développement que pour la mise en œuvre du pipeline.


Supposons que vous ayez choisi la deuxième option et que vous deviez donc exécuter les fichiers qui ont été ajoutés ou modifiés. Nous pouvons filtrer ces fichiers comme décrit ici en ajoutant le paramètre --diff-filter=AM :

 #!/bin/sh while read oval nval ref do echo List of files added or changed in the commit: git diff --name-only --diff-filter=AM $oval $nval done


Ajoutez quelques fichiers et modifiez à nouveau le fichier readme.md :

 echo "SELECT 1;" > test1.sql echo "SELECT 2;" > test2.sql echo "SELECT 3;" > test3.sql echo "New line 2" >> readme.md git add . git commit -m "New files" git push


La sortie du script hook contient 4 fichiers :

Liste de tous les fichiers modifiés


Nous modifions les fichiers test1.sql et readme.md, supprimons test2.sql et ajoutons un autre fichier :

 echo "SELECT 11;" > test1.sql echo "New line 2" >> readme.md rm test2.sql echo "SELECT 4;" > test4.sql git add . git commit -m "Modify, remove and add" git push


Seuls les fichiers modifiés et ajoutés sont affichés :

Uniquement les fichiers ajoutés ou modifiés


Notre objectif est d'exécuter des scripts SQL après chaque push réussi, nous devons donc filtrer les fichiers de ce type uniquement ; dans notre cas, nous fixerons l'exigence qu'ils doivent tous avoir l'extension « .sql ». Pour filtrer, ajoutez le paramètre -- "*.sql" à la commande git diff :

 #!/bin/sh while read oval nval ref do echo List of files added or changed in the commit: git diff --name-only --diff-filter=AM $oval $nval -- "*.sql" done


Pour exécuter des scripts, il faut également pouvoir se connecter à la base de données. Pour cela, nous allons créer des identifiants et tester la connexion :

 mysql_config_editor set --login-path=testdb_remote --host=localhost --port=3306 --user=user_remote --password mysql --login-path=testdb_remote --database=testdb_remote 


Création de crédits pour MySQL


Modifiez notre script pour parcourir les fichiers « .sql », exécutez chaque fichier et vérifiez le résultat. Nous devons également trier la sortie de la liste pour exécuter les fichiers dans l'ordre requis. Avec la commande git show, nous affichons le contenu du script SQL et le passons via le tube pour exécution par MySQL .

La variable « $ ? » contiendra 0 si le script SQL a été exécuté avec succès et une autre valeur s'il y a eu une erreur :

 #!/bin/sh while read oval nval ref do echo List of files added or changed in the commit: for file in $(git diff --name-only --diff-filter=AM $oval $nval -- "*.sql" | sort); do git show master:${file} | mysql --login-path=testdb_remote --database=testdb_remote echo "FILE: ${file} - result $?" done done


Effectuez un test supplémentaire : supprimez tous les fichiers « .sql » précédemment créés et créez des scripts pour :


  • création de tableau
  • insérer des données dans le tableau
  • créer une procédure pour recevoir les données de la table
  • script contenant une erreur


Nous devons également ajouter un préfixe (1_, 2_, etc.) à chaque nom de fichier pour garantir l'ordre d'exécution souhaité des fichiers :

 rm *.sql echo "DB Initialization" >> readme.md echo " DROP TABLE IF EXISTS customers; CREATE TABLE customers ( id int UNSIGNED NOT NULL AUTO_INCREMENT, name varchar(255) DEFAULT NULL, PRIMARY KEY (id) ); " > 1_customers.sql echo " INSERT INTO customers (id, name) VALUES (1, 'John Doe'), (2, 'Jane Smith') AS new ON DUPLICATE KEY UPDATE customers.name = new.name; " > 2_customers_init.sql echo " DROP PROCEDURE IF EXISTS get_customer; DELIMITER $$ CREATE PROCEDURE get_customer(IN customer_id int UNSIGNED) BEGIN SELECT c.id, c.name FROM customers c WHERE c.id = customer_id; END $$ " > 3_get_customer.sql echo "SELECT FROM customers;" > 4_error_select.sql ls -1


Nous avons donc quatre fichiers « .sql » qui doivent être exécutés :

Liste des fichiers

Nous apportons des modifications au référentiel :

Seuls les fichiers SQL sont exécutés


Et nous voyons que lorsque git push est exécuté, les fichiers sont exécutés séquentiellement et le résultat de l'exécution (code de sortie de la commande MySQL) de chaque fichier est affiché. Le fichier « 4_error_select.sql » contient une erreur de syntaxe, le résultat de son exécution est donc 1.


Et enfin, vérifions ce que nous avons dans la base de données :

 mysql --login-path=testdb_remote --database=testdb_remote show tables; call get_customer(1); call get_customer(2); 


Tester les objets créés dans la base de données


Comme vous pouvez le constater, la table et la procédure ont été créées dans la base de données distante. La procédure s'exécute avec succès et renvoie des données.


Pour améliorer la lisibilité de la sortie du script hook, vous pouvez supprimer la sortie de la CLI MySQL ou la rediriger vers un fichier journal. Vous pouvez également analyser le résultat de l'exécution de la commande MySQL et ajouter plus de logique au script hook.


Par exemple, vous pouvez exécuter des scripts SQL sur une base de données de test, puis y exécuter des tests (comme je l'ai décrit ici ). Si les tests sont terminés avec succès sur la base de données de test, exécutez des scripts SQL sur la base de données de production et exécutez probablement également des tests sur celle-ci.

En analysant les résultats de chaque étape, vous pouvez créer des pipelines de n'importe quelle configuration.


Bien entendu, chaque approche présente un certain nombre d’avantages et de limites. Avec la deuxième approche, il faut s'assurer de l'ordre dans lequel les scripts sont exécutés car on ne peut pas, par exemple, insérer des données dans une table tant qu'elle n'est pas créée. Il est également nécessaire de s'assurer que vous pouvez réexécuter les scripts, c'est-à-dire gérer correctement les situations où l'objet en cours de création est déjà dans la base de données ou où la base de données contient déjà les données à ajouter.


Lors de l'utilisation d'un système de versioning, le processus de développement devient un peu plus compliqué car il est nécessaire de formaliser en plus les modifications dans des scripts d'un format prédéterminé. Cependant, vous pouvez obtenir une certaine flexibilité en utilisant un fichier d'installation.


Le principal avantage de la technique décrite est la mise en œuvre du versioning dans la base de données avec très peu d'effort, ainsi que la possibilité de mettre en œuvre des pipelines CI/CD .

Pour évaluer si cela pourrait vous être utile, vous pouvez commencer par vous demander : à quelle fréquence écrivez-vous du code directement en production ?