Dans cette partie également, vous travaillerez en pair-programming.
1. Automatisation des hooks
Comme vu précédemment, il est nécessaire de copier les hooks versionnés dans le dossier .git/hooks
pour qu’ils soient
pris en compte par Git. Cela poser des problèmes de maintenabilité et de synchronisation.
Un outil tel que 🐶 Husky permet d’automatiser cette tâche. C’est une librairie Node.js qui pourra s’intégrer assez “facilement” dans un projet web.
Or ce n’est pas forcément notre cas et il n’est pas nécessaire de surcharger l’environnement avec du Node.
Git propose une solution native pour aider à la synchronisation des hooks ; il s’agit d’une configuration :
core.hooksPath
.
Remarque : D’ailleurs, Husky repose sur l’utilisation de cette configuration.
1.1. 📋️ Instructions de la configuration Git
Manipuler et tester la configuration core.hooksPath
- Positionnez-vous sur la branche
main
et synchronisez votre dépôt local avec le dépôt distant (git pull
). - Récupérez le pre-commit hook :
cp bin/hooks/pre-commit .git/hooks
. - Tentez un commit “à vide” :
git commit -m "Test"
.
Cette action doit être refusée par le hook :Interdiction de commiter sur la branche principale 'main' !
. - Supprimez les hooks personnalisés dans le
.git/hooks
:rm .git/hooks/pre-commit .git/hooks/pre-push
. - Retentez le commit “à vide”. Vous devriez avoir un message natif à Git vous indiquant qu’il n’y a rien à commiter.
- Configurez le chemin vers les hooks versionnés :
git config --local core.hooksPath bin/hooks
.
Faites attention à bien préciser l’option--local
, vous ne voudriez pas que cette configuration spécifique soit définie pour tous vos repositories. - Retentez de nouveau le commit “à vide”. Vous retrouvez le message d’erreur du hook personnalisé.
- Modifiez le fichier
bin/hooks/pre-commit
pour ajoutererror "Test !" && exit 1
à la ligne 8 (après la fonctionerror
). - Retentez une dernière fois le commit “à vide”. Vous devriez avoir votre message d’erreur
Test !
. - Annulez vos modifications :
git reset --hard
.
Communiquer la procédure
- Créez la branche
local-hooks-config
. - Modifiez le fichier
README.md
pour compléter la tâcheHooks
en ajoutant ces deux lignes juste en-dessous :
⚠️ Attention à bien garder les espaces en début de ligne pour créer une sous-liste.
- [x] Utilisation des scripts versionnés. - [ ] Automatiser la configuration.
- Modifiez aussi le fichier
README.md
au niveau de la partie📋️ Instructions du repository
pour ajouter la mise en place de la configuration Git vue au-dessus.
Voir plus bas… - Commitez ces modifications :
git commit -m "📝 [hooks] Git configuration"
. - Vous devriez connaître maintenant les instructions à suivre ensuite.
Proposition de rédaction du README.md
## 📋️ Instructions du repository
### Git - Configuration
```bash
# Définit le chemin vers les hooks versionnés.
git config --local core.hooksPath bin/hooks
```
1.2. 📋️ Instructions de l’automatisation
On ne va pas exactement faire d’automatisation ; on va éviter de faire une tâche manuelle, ce qui est une sorte d’automatisation, par le biais d’un script bash.
- Créez la branche
local-setup-hooks
. - Créez le fichier
bin/setup/hooks
et ajoutez-y le contenu défini ci-après. - Pensez à rendre ce script exécutable… Et n’oubliez pas de remplacer les
TODO
par le code adéquat. - Modifiez le fichier
README.md
pour cocher la deuxième sous-tâche deHooks
définie dans la partie précédente. - Modifiez de nouveau le fichier
README.md
pour remplacer ce qui avait été écrit sur les instructions du repository concernant la configuration Git. Toute la partieGit - Configuration
peut être remplacée par le contenu fourni ci-après. - Commitez :
git commit -m "🔨 [hooks] Setup script"
. - Pushez, créez la PR et demandez-moi une review.
📝 Contenu initial du script bin/setup/hooks
#!/bin/bash
set -eu
ROOT_PATH="$(realpath "$(dirname "$(realpath "${BASH_SOURCE[0]}")")/../..")"
HOOKS_DIR="bin/hooks"
HOOKS_PATH="${ROOT_PATH}/${HOOKS_DIR}"
# 1. Vérifie si la configuration locale est définie
hooks_path_config=$(git config --local --get core.hooksPath || echo "")
# TODO: Définir la configuration locale sur la valeur de HOOKS_DIR
# Si elle n'est pas définie ou si la valeur est différente de HOOKS_DIR => exécuter la commande correspondante
# Pensez à afficher un message pour informer de l'action effectuée
# Par exemple : echo "Configuration locale 'core.hooksPath' définie sur '${HOOKS_DIR}'"
# 2. Vérifie si les hooks sont exécutables
# TODO: Rendre chaque fichier hook exécutable
# Pensez à ignorer les dossiers
# Comme plus haut, affichez un message pour informer des actions effectuées
📝 Contenu du README.md à remplacer
Ce contenu remplace la sous-partie Git - Configuration
de la partie 📋️ Instructions du repository
, puisqu’elle
n’est plus d’actualité grâce à notre script.
### Setup du repository
Les scripts définis dans le dossier [bin/setup](bin/setup) sont des scripts de "setup" à exécuter une première fois
après le clonage du repository. Certains scripts peuvent être lancés à nouveau pour prendre en compte certains
changements.
* [bin/setup/hooks](bin/setup/hooks) : Agit sur les hooks Git spécifiques au repository.
1. Définie la configuration locale pour utiliser les hooks versionnés.
2. Rend les hooks exécutables.
- Ce script peut être exécuté à nouveau dès qu'un nouveau hook est ajouté au repository afin de le rendre exécutable.
2. GitHub Actions
GitHub met à disposition un outil d’automatisation permettant notamment de réaliser des tâches de CI/CI : GitHub Actions.
Il faut définir des workflows qui seront exécutés lors d’événements spécifiques (push, pull request, etc.). Ces workflows intègrent un ensemble de jobs qui sont eux-mêmes composés d’étapes.
Lorsqu’un événement GitHub déclenche un workflow, celui-ci va exécuter les jobs dans l’ordre défini sur des machines virtuelles mises à disposition (appelées « runners »). Chaque job exécute ses propres étapes.
Dès lors qu’une étape échoue, le job et le workflow associés sont échus également et l’événement GitHub peut alors s’interrompre complètement tant que le problème n’est pas résolu.
On peut, par exemple, empêcher un push sur une branche si les tests unitaires ne passent pas.
2.1. 📋️ Instructions de la prise en main de GitHub Actions
1) Créez la branche ci-actions-quality-git
.
2) Modifiez le fichier .editorconfig
pour ajouter une nouvelle règle sur les fichiers yaml
:
[*.yaml]
indent_size = 2
3) Créez un nouveau fichier .github/workflows/quality.yaml
et ajoutez-y le contenu défini suivant :
name: Qualité
on: [pull_request]
jobs:
git_standards:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: git fetch origin
- name: Vérification des commits de la branche
run: "echo \"PR from: ${{ github.head_ref }} to: ${{ github.base_ref }}\""
4) Commitez vos modifications, cette fois avec un message plus complet :
👷 [quality] Init
👷 GitHub Actions
=================
* Define new `workflow` to check defined Git standards
🐁 EditorConfig
===============
* New rules for `yaml` files
5) Pushez et créez la PR sur GitHub.
GitHub prend alors en compte le workflow et l’exécute : un cadre apparaît sur la PR pour indiquer que le workflow est en
cours d’exécution et une nouvelle entrée apparaît dans l’onglet Actions
du repository, correspondant à l’exécution de
l’ensemble des GitHub Actions générées par la PR.
6) Vérifiez que le workflow s’est bien exécuté, qu’il n’y a pas d’erreur et que la step avec l’instruction echo
a
bien affiché le message attendu.
2.2. 📋️ Instructions du script exécuté par GitHub Actions
Maintenant, il faut écrire le script qui va effectuer l’action “qualité” que l’on souhaite implémenter, à savoir une vérification du nombre de commits sur la branche à merger, comme on l’avait fait avec les hooks.
L’environnement Git
de la VM de GitHub étant un peu différent de celui de vos machines, le hook pre-push
ne pourra
pas être utilisé tel quel. Il faut écrire un script qui effectue la même action, mais qui soit plus adapté à
l’environnement de GitHub.
Il a fallu plusieurs essais pour arriver à un script fonctionnel, donc je vous le donne directement.
- Récupérez le fichier : actions-quality-git-01.
- Déplacez-le dans le dossier
bin/actions/quality/git_standards
et renommez-lebranch-commits
. - Pensez à rendre ce script exécutable.
- Modifiez la step
Vérification des commits de la branche
du fichierquality.yaml
pour exécuter le script :run: bin/actions/quality/git_standards/branch-commits ${{ github.head_ref }}
.
On fournit le nom de la branche à merger en paramètre du script grâce aux variables des contextes GitHub Actions.
Bien sûr, vous remplacez l’instructionecho
définie précédemment. - Rajoutez une clef
if
entre les clefsruns-on
etsteps
du job afin d’ajouter une condition sur l’exécution du job :if: github.base_ref == github.event.repository.default_branch
.
Cette condition permet de n’exécuter le job que si la branche de destination est la branche principale du repository. - Ajoutez ces changements au commit précédent :
git commit --amend --no-edit
. - Avant de pushez, n’oubliez pas la modification habituelle du
README.md
au sujet des tâches à faire / réalisées. Rajoutez une nouvelle tâche à la liste :- [x] **GitHub Actions** : Initialisation du workflow `Quality` pour l'assurance qualité (QA).
. - Cette fois, créez un deuxième commit pour tester le job.
Pour rappel, l’option--no-verify
permet de ne pas exécuter les hooks lors d’ungit commit
ou d’ungit push
. - Vous devriez avoir 2 commits en local et donc 2 commits sur votre PR.
- Le workflow s’exécute de nouveau et cette fois échoue à l’étape
Vérification des commits de la branche
avec le message d’erreurVous avez plusieurs commits. [...]
. - Faites un rebase interactif en local pour squasher vos 2 commits en un seul. Ne gardez que le message du premier commit.
- Faites ensuite un
git push --force
pour forcer la mise à jour de l’historique de la branche distante. - Le workflow devrait cette fois être en succès.
- Demandez-moi une review pour valider tout ça.
Pour la suite…
Vous vous êtes familiarisés avec le scripting afin d’effectuer des actions manuelles ou d’exécuter des vérifications répétitives, notamment dans le cadre de l’intégration continue (CI) avec les GitHub Actions. Tout ceci est assez sommaire et il sera nécessaire de vous investir personnellement pour mieux appréhender et manipuler ces sujets.
Dans la prochaine partie du TP, vous allez continuer à utiliser le scripting pour mettre en place un environnement avec l’aide de Docker.