diff --git a/GPT_PROJET/mini_projet.md b/GPT_PROJET/mini_projet.md
index a6ab3ccc32afcf601f32962a8f6102c7fdb702d9..e42da40a24db759f0c6d82cd7785fd64a0dcbc81 100644
--- a/GPT_PROJET/mini_projet.md
+++ b/GPT_PROJET/mini_projet.md
@@ -4,7 +4,7 @@
 Réaliser une application Web, qui permet de demander à *ChatGPT* de créer une fonction avec des tests unitaires dans un langage de programmation donné.
 
 ## Dates limites 
-- point d'étape : **mardi 14 février** matin
+- point d'étape : **mardi 14 février** matin : présentation des tests et du worklow CI/CD.
 - dépôt final : **dimanche 19 février** minuit
 
 ## Moyens
@@ -12,7 +12,6 @@ Langage de développement : au choix
 Framework Web : au choix
 Dépôt GIT : https://gitlab.univ-lorraine.fr 
 
-Peut-être qe que pour le framework, une bonne idée serait d'utiliser Laravel en partant du modèle de projet GitLab : https://gitlab.com/gitlab-org/project-templates/laravel
 
 ## Langages cibles
 **Groupe 1** : Python / Prolog
@@ -40,6 +39,8 @@ Le formulaire doit contenir les élements suivants :
 
 Votre logiciel de création de fonction devra pouvoir être testé sans accès à ChatGPT, ni Internet. Vous utiliserez donc un *mock* (https://en.wikipedia.org/wiki/Mock_object) avec des réponses prédéfinies pour simuler le comportement de l'accès à *ChatGPT*. 
 
+On mettra en place avec .gitlab-ci.yml un workflow CI/CD d'installation, de tests et de déploiement du projet. On peut s'inspirer de ce modèle adapaté à votre framework de développement : https://gitlab.com/gitlab-org/project-templates/laravel/-/blob/main/.gitlab-ci.yml
+
 On mettra en place des scénarios de tests fonctionnels avec le framework *Selenium*.
 
 La fonction créée devra passer et valider les tests générés par *ChatGPT*. Comme dans le programme *Mira* (voir ci-dessous), il peut être nécessaire de demander à *ChatGPT* de refaire le programme pour qu'il passe les tests. On limitera le nombre d'itérations à 10, et on mettra un message d'erreur si la fonction ne peut pas être validée.
diff --git a/Makefile b/Makefile
index 129844af69ab1fe39842c76391d0d10c61c22e2a..04afff51ac445fc0b8ae46140c4b71336787fc49 100644
--- a/Makefile
+++ b/Makefile
@@ -1,2 +1,10 @@
 pdf: cours_qualite_logicielle.md
-	marp -o cours_qualite_logicielle.pdf --allow-local-files cours_qualite_logicielle.md
+	marp -o cours_qualite_logicielle.pdf --html --allow-local-files --theme theme/univ-lorraine.css cours_qualite_logicielle.md
+
+linters: linters/3-linters.md
+	marp -o linters.pdf --html --allow-local-files --theme theme/univ-lorraine.css linters/3-linters.md
+
+clean:
+	rm ./*.pdf
+
+all: pdf, linters
diff --git a/documentation/The Pragmatic Programmer Quick Reference Guide.pdf b/documentation/The Pragmatic Programmer Quick Reference Guide.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..36acbc2c913841ff15a051c90595d9152ac2189a
Binary files /dev/null and b/documentation/The Pragmatic Programmer Quick Reference Guide.pdf differ
diff --git a/linters/3-linters.md b/linters/3-linters.md
new file mode 100644
index 0000000000000000000000000000000000000000..6f50d5f17536dbdb3c47701be08750227ddce72c
--- /dev/null
+++ b/linters/3-linters.md
@@ -0,0 +1,363 @@
+---
+marp: true
+theme: univ-lorraine
+---
+<!-- _class: lead -->
+
+![bg left:30% 80%](./images/logo.png)
+
+
+# **Qualité de développement**
+
+## Linters
+
+*Philippe Dosch*
+philippe.dosch@univ-lorraine.fr
+*Florian Ferbach*
+florian.ferbach@univ-lorraine.fr
+
+Adaptation :
+*Laurent Pierron*
+laurent.pierron@inria.fr
+
+**BUT S4.02 GB**
+
+---
+
+<!-- _class: lead -->
+
+# C'est quoi un linter ?
+
+<!--
+Contrôle qualité du code. Vérifie :
+- respect standards
+- pas de code smell
+- pas de complexité trop grande
+- bonne façon d'écrire
+- ... ce que vous voulez (les règles sont généralement configurables étendables)
+-->
+
+---
+
+## Projet Fil Rouge : ZombiLingo
+
+![bg](./images/background-home.png)
+
+**ZombiLingo** : https://zombiludik.org
+
+* GitHub : https://github.com/lpierron/zombilingo
+* SonarCloud : https://sonarcloud.io/project/overview?id=lpierron_zombilingo
+
+---
+
+## PHP Lint
+
+Vérifie les erreurs de syntaxe PHP.
+
+##### Installation
+
+Rien à faire, inclus à PHP.
+
+##### Usage
+
+- Fichier seul
+```bash
+$ php -l cfg/conf.sample.php 
+PHP Parse error:  Unterminated comment starting line 1 in cfg/conf.sample.php on line 1
+Errors parsing cfg/conf.sample.php
+```
+- Tous les .php
+```bash
+$ find . -type f -name '*.php' -exec php -l {} \; 
+```
+
+---
+
+## PHP Code Sniffer  
+
+Vérifie la bonne application des standards PSR.
+
+##### Installation
+
+L'installation s'effectue sur le projet directement.
+
+```bash
+# prérequis : extension PHP xml writer
+$ sudo apt install php-xmlwriter
+$ composer require --dev "squizlabs/php_codesniffer=3.*"
+```
+
+##### Configuration
+
+Configurable via CLI uniquement.
+[Documentation](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Configuration-Options)
+
+---
+
+##### Usage
+
+```bash
+$ ./vendor/bin/phpcs --extensions=php ./lib/
+FILE: ./lib/Configuration.php
+------------------------------------------------------------------------------------------------------
+FOUND 42 ERRORS AND 15 WARNINGS AFFECTING 47 LINES
+------------------------------------------------------------------------------------------------------
+   5 | ERROR   | [ ] Doc comment long description must start with a capital letter
+   7 | ERROR   | [ ] The tag in position 1 should be the @copyright tag
+   9 | WARNING | [ ] Line exceeds 85 characters; contains 90 characters
+  10 | WARNING | [ ] Invalid version "1.5.1" in file comment; consider "CVS: <cvs_id>" or "SVN:
+     |         |     <svn_id>" or "GIT: <git_id>" or "HG: <hg_id>" instead
+  11 | WARNING | [ ] PHP version not specified
+  11 | ERROR   | [ ] Missing @category tag in file comment
+  11 | ERROR   | [ ] Missing @package tag in file comment
+  11 | ERROR   | [ ] Missing @author tag in file comment
+  21 | ERROR   | [ ] Doc comment long description must start with a capital letter
+  22 | ERROR   | [ ] Missing @category tag in class comment
+  22 | ERROR   | [ ] Missing @package tag in class comment
+  22 | ERROR   | [ ] Missing @author tag in class comment
+  22 | ERROR   | [ ] Missing @license tag in class comment
+  ...
+
+```
+
+<!-- _footer: [GitHub PHP Code Sniffer](https://github.com/squizlabs/PHP_CodeSniffer) -->
+
+---
+
+## PHP Mess Detector
+Vérifie la présence de problèmes potentiels dans le code : potentiels bugs, code non optimisé, expressions trop compliquées, code non utilisé.
+
+##### Installation
+
+L'installation s'effectue sur le projet directement.
+
+```bash
+$ composer require --dev "phpmd/phpmd=@stable"
+```
+
+##### Configuration
+
+Configurable via un fichier `ruleset.xml`.
+[Documentation](https://phpmd.org/documentation/creating-a-ruleset.html)
+
+---
+
+##### Usage
+
+```bash
+$ ./vendor/bin/phpmd ./lib ansi codesize,unusedcode,naming
+FILE: ./lib/Configuration.php
+------------------------------------------------------------------
+ 107 | VIOLATION | The method __construct() has a Cyclomatic Complexity of 35. The configured cyclomatic complexity threshold is 10.
+ 107 | VIOLATION | The method __construct() has an NPath complexity of 22860. The configured NPath complexity threshold is 200.
+ 107 | VIOLATION | The method __construct() has 141 lines of code. Current threshold is set to 100. Avoid really long methods.
+
+
+FILE: ./lib/Controller.php
+---------------------------------------------------------------
+ 24  | VIOLATION | The class Controller has an overall complexity of 50 which is very high. The configured complexity threshold is 50.
+ 111 | VIOLATION | The method __construct() has a Cyclomatic Complexity of 10. The configured cyclomatic complexity threshold is 10.
+ 199 | VIOLATION | The method _create() has a Cyclomatic Complexity of 11. The configured cyclomatic complexity threshold is 10.
+
+
+FILE: ./lib/Data/Database.php
+------------------------------------------------------------------
+ 26  | VIOLATION | The class Database has an overall complexity of 122 which is very high. The configured complexity threshold is 50.
+ 60  | VIOLATION | The method __construct() has a Cyclomatic Complexity of 13. The configured cyclomatic complexity threshold is 10.
+ 143 | VIOLATION | The method create() has a Cyclomatic Complexity of 10. The configured cyclomatic complexity threshold is 10.
+...
+```
+
+<!-- _footer: [GitHub PHP Mess Detector](https://github.com/phpmd/phpmd) -->
+
+---
+
+<!-- _class: exercice-->
+
+# #1
+
+- Installez et testez ces 3 linters sur le projet
+- Configurer les différents linters avec les règles qui vous parraissent les plus intéressantes
+- Créez une nouvelle target dans le makefile de sorte qu'on puisse appellee ces 3 linters avec la commande `make lint`
+```makefile
+# ...
+lint:
+  # commandes de lint ici
+  # sur plusieurs lignes éventuellement
+```
+- Corriger 5+ erreurs différentes remontées par ces linters
+- N'oubliez pas de commit vos modifications sur GitHub
+
+---
+
+<!-- _class: lead-->
+
+# Automatisation
+
+---
+
+## PHP CS Fixer
+
+Comme PHP Code Sniffer mais propose de fix automatiquement tout ce qui peut être fixé automatiquement.
+
+
+##### Installation
+
+L'installation s'effectue sur le projet directement.
+
+```bash
+$ composer require --dev "friendsofphp/php-cs-fixer"
+```
+
+##### Configuration
+
+Configurable via un fichier `.php-cs-fixer.dist.php`.
+[Documentation](https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/blob/master/doc/config.rst#config-file)
+
+---
+
+##### Usage
+
+```bash
+$ ./vendor/friendsofphp/php-cs-fixer/php-cs-fixer fix lib
+Loaded config default.
+   1) lib/Configuration.php
+   2) lib/Controller.php
+   3) lib/Request.php
+   4) lib/Data/Filesystem.php
+   5) lib/Data/Database.php
+   6) lib/YourlsProxy.php
+   7) lib/I18n.php
+
+Fixed 7 of 23 files in 0.838 seconds, 16.000 MB memory used
+```
+
+Aussi disponible sous forme d'extension d'éditeur: https://github.com/PHP-CS-Fixer/PHP-CS-Fixer#editor-integration
+
+<!-- _footer: [GitHub PHP CS Fixer](https://github.com/PHP-CS-Fixer/PHP-CS-Fixer) -->
+
+---
+
+## Pre-commit hook
+
+Un pre-commit hook permet d'effectuer une action avant chaque commit.
+
+##### Configuration
+
+Configurable via un fichier bash `.git/hooks/`.
+
+Exemple:
+```bash
+#!/usr/bin/env bash
+
+# If any command fails, exit immediately with that command's exit status
+set -eo pipefail
+
+# Find all changed files for this commit
+# Compute the diff only once to save a small amount of time.
+CHANGED_FILES=$(git diff --name-only --cached --diff-filter=ACMR)
+# ...
+```
+
+<!-- _footer: [Documentation](https://githooks.com/) -->
+
+---
+
+```bash
+#!/usr/bin/env bash
+
+# If any command fails, exit immediately with that command's exit status
+set -eo pipefail
+
+# Find all changed files for this commit
+# Compute the diff only once to save a small amount of time.
+CHANGED_FILES=$(git diff --name-only --cached --diff-filter=ACMR)
+
+if [[ -n "$CHANGED_FILES" ]]
+then
+    # Run black against changed python files for this commit
+    black --check $CHANGED_FILES
+    echo "black passes all altered python sources."
+    # Run flake8 against changed python files for this commit
+    flake8 $CHANGED_FILES
+    echo "flake8 passed!"
+fi
+```
+
+---
+
+<!-- _class: exercice-->
+
+# #2
+
+- Installez un pre-commit hook qui:
+  - utilise PHP CS Fixer ou prettier pour fixer automatiquement le maximum d'erreurs
+  - ajoute ce que PHP CS Fixer a fixé au staging area
+  - utilise PHP Mess detector pour interdire le commit si il y a des erreurs
+- N'oubliez pas de commit vos modifications sur GitHub : adaptez la configuration de vos linters ou corrigez le code si nécessaire
+- Est-il possible de commit en ignorant le pre-commit hook ?
+
+---
+
+<!-- _class: exercice-->
+
+## Info complémentaires
+
+- PHP CS Fixer peut être appelé sur une liste de fichier 
+```bash
+./vendor/friendsofphp/php-cs-fixer/php-cs-fixer fix --config=.php-cs-fixer.php fichier1.php lib/autreFichier.php ...
+```
+Mais a besoin d'un fichier de configuration `.php-cs-fixer`. [Documentation](https://cs.symfony.com/doc/config.html)
+
+- PHPMD peut être appelé sur une liste de fichier
+```bash
+./vendor/bin/phpmd fichier1.php,lib/autreFichier.php ansi codesize,unusedcode,naming
+```
+Mais chaque fichier doit cette fois-ci être séparés par des virgules.
+
+---
+
+<!-- _class: exercice-->
+
+Pour transformer `fichier1.php lib/autreFichier.php` en `fichier1.php,lib/autreFichier.php`, on peut déclarer cette fonction
+```bash
+function join_by {
+  local d=${1-} f=${2-}
+  if shift 2; then
+    printf %s "$f" "${@/#/$d}"
+  fi
+}
+```
+
+Utilisée ainsi :
+
+```bash
+echo $(join_by , ${CHANGED_FILES})
+```
+
+
+---
+
+# Intégration Continue
+
+La CI (Continuous Integration) est un principe qui lance des outils de qualité de code sur chaque PR, et qui permet d'interdir de la merger dans main si les attentes ne sont pas respectées.
+
+Chez GitHub, ces tests de qualités sont généralement sous forme de **GitHub Actions**
+
+![center](./images/ci-checks.png)
+
+---
+
+<!-- _class: exercice-->
+
+# #3
+
+- Installez [une action GitHub de lint](https://github.com/marketplace/actions/lint-action) sur votre repository:l'action devra empêcher de merger des pull request si il y a des erreurs de lint
+- Puisqu'on veut systématiquement passer par le système de pull request pour profiter de l'action GitHub de lint, protéger la branche main pour que personne ne puisse y envoyer des commits directement. Trouvez l'option dans les settings de votre projet GitHub.
+
+---
+
+# Pour aller plus loin...
+
+- [prettier](https://prettier.io/) : un code formatter multilangage aux idées arrêtées
+- [pre-commit](https://pre-commit.com/) : un framework de pre-commit hooks
\ No newline at end of file
diff --git a/linters/exercice-2/.php-cs-fixer.php b/linters/exercice-2/.php-cs-fixer.php
new file mode 100644
index 0000000000000000000000000000000000000000..834219beec8c99fe306435c0f099241faf663d12
--- /dev/null
+++ b/linters/exercice-2/.php-cs-fixer.php
@@ -0,0 +1,12 @@
+<?php
+
+$finder = PhpCsFixer\Finder::create()
+    ->in(__DIR__)
+;
+
+$config = new PhpCsFixer\Config();
+return $config->setRules([
+        '@PSR12' => true,
+    ])
+    ->setFinder($finder)
+;
\ No newline at end of file
diff --git a/linters/exercice-2/pre-commit b/linters/exercice-2/pre-commit
new file mode 100755
index 0000000000000000000000000000000000000000..c872d06691859cbd15662cdb0d59deafd92d86ec
--- /dev/null
+++ b/linters/exercice-2/pre-commit
@@ -0,0 +1,24 @@
+#!/usr/bin/env bash
+
+# If any command fails, exit immediately with that command's exit status
+set -eo pipefail
+
+# Find all changed files for this commit
+# Compute the diff only once to save a small amount of time.
+CHANGED_FILES=$(git diff --name-only --cached --diff-filter=ACMR)
+
+function join_by {
+  local d=${1-} f=${2-}
+  if shift 2; then
+    printf %s "$f" "${@/#/$d}"
+  fi
+}
+
+if [[ -n "$CHANGED_FILES" ]]
+then
+    echo "Running phpcsfixer..."
+	./vendor/friendsofphp/php-cs-fixer/php-cs-fixer fix --config=.php-cs-fixer.php ${CHANGED_FILES}
+	git add ${CHANGED_FILES}
+    echo "Running phpmd..."
+    ./vendor/bin/phpmd $(join_by , ${CHANGED_FILES}) ansi codesize,unusedcode,naming
+fi
diff --git a/linters/images/background-home.png b/linters/images/background-home.png
new file mode 100755
index 0000000000000000000000000000000000000000..11e04bbfecefcf060754acafb21442911c071313
Binary files /dev/null and b/linters/images/background-home.png differ
diff --git a/linters/images/ci-checks.png b/linters/images/ci-checks.png
new file mode 100644
index 0000000000000000000000000000000000000000..f7768ba3481379928914c1c31fb04e7b97288e52
Binary files /dev/null and b/linters/images/ci-checks.png differ
diff --git a/linters/images/leader-board-homepage.png b/linters/images/leader-board-homepage.png
new file mode 100644
index 0000000000000000000000000000000000000000..46a6b5f952a0b47d69c2ba1f80dba42f4db86e2d
Binary files /dev/null and b/linters/images/leader-board-homepage.png differ
diff --git a/linters/images/logo.png b/linters/images/logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..b947af5793e83f9d0112d6be9973035fcb865821
Binary files /dev/null and b/linters/images/logo.png differ
diff --git a/theme/hero-background-exercice.jpg b/theme/hero-background-exercice.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..d7cf33a1edba1c927208caa65cf62f1a72f05385
Binary files /dev/null and b/theme/hero-background-exercice.jpg differ
diff --git a/theme/hero-background.jpg b/theme/hero-background.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..72ae612a6684e2d1fed0d1a6465f1a6163130a45
Binary files /dev/null and b/theme/hero-background.jpg differ
diff --git a/theme/univ-lorraine.css b/theme/univ-lorraine.css
new file mode 100644
index 0000000000000000000000000000000000000000..21676b5d9e6c688da3118fca3d4865270079f833
--- /dev/null
+++ b/theme/univ-lorraine.css
@@ -0,0 +1,43 @@
+/* @theme univ-lorraine */
+
+@import "gaia";
+:root {
+  background-image: url("../theme/hero-background.jpg");
+  font-size: 1.8rem;
+  background-size: cover;
+}
+
+section.lead {
+  font-size: 2rem;
+}
+
+blockquote {
+  display: inline-block;
+}
+
+section.exercice {
+  background-image: url("../theme/hero-background-exercice.jpg");
+}
+
+kbd {
+  display: inline-block;
+  margin: 0 0.1em;
+  padding: 0.1em 0.6em;
+  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Liberation Sans",
+    sans-serif;
+  font-size: 20px;
+  line-height: 1.5;
+  color: #232629;
+  text-shadow: 0 1px 0 white;
+  background-color: #e3e6e8;
+  border: 1px solid #9fa6ad;
+  border-radius: 3px;
+  box-shadow: 0 1px 1px hsl(210deg 8% 5% / 15%),
+    inset 0 1px 0 0 hsl(0deg 0% 100%);
+  overflow-wrap: break-word;
+}
+
+img[alt~="center"] {
+  display: block;
+  margin: 0 auto;
+}