Le README est la porte d'entrée d'un dépôt : il doit permettre à une personne qui n'a jamais vu le projet de l'installer et d'obtenir un premier résultat sans rien deviner. Le CHANGELOG est son historique : une liste rédigée, version par version, de ce qui a changé pour les utilisateurs. Le seul moyen de savoir si un README tient sa promesse est de le tester comme un inconnu, dans un dossier vierge. Cette leçon le fait sur un petit projet, puis installe un CHANGELOG au format Keep a Changelog.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- À qui s'adresse un README, ce qu'il contient et ce qu'il laisse à d'autres documents.
- Comment tester un README et quels défauts l'exécution révèle.
- Le format Keep a Changelog 1.1.0 :
Unreleased, six types, dates, liens, et le lien avec le numéro de version. - Pourquoi un changelog n'est pas un export de
git log. - Comment un linter (outil qui vérifie le style d'un fichier) Markdown réagit à ce format.
Le projet fil rouge s'appelle healthcheck : un script Python, sans
dépendance, qui vérifie qu'une URL répond. C'est un exemple créé pour
cette leçon : l'adresse GitHub exemple-fictif n'existe pas, et aucun dépôt
n'est à cloner. Pour vous exercer, appliquez la méthode à votre propre
dépôt, ou recopiez dans un dossier vide les deux fichiers montrés
(README.md et CHANGELOG.md) : le script lui-même n'est pas reproduit.
À qui s'adresse un README et que contient-il ?
Section intitulée « À qui s'adresse un README et que contient-il ? »Le README est le premier fichier qu'une personne lit en arrivant sur un dépôt. Elle ne connaît ni le projet, ni son équipe, ni ses conventions : elle veut savoir à quoi il sert, si c'est pour elle, puis le faire tourner. Un README répond à ces trois questions, dans cet ordre.
Pour ne pas partir d'une page blanche, The Good Docs Project publie un gabarit de README (page du gabarit), personnalisable : on réordonne ou retire les sections inutiles. C'est un menu, pas une obligation.
| Section du gabarit | Question à laquelle elle répond |
|---|---|
| Project name, description | À quoi sert ce projet ? |
| Who this project is for | Est-ce pour moi ? |
| Project dependencies | De quoi ai-je besoin avant ? |
| Instructions : Install, Configure, Run, Troubleshoot | Comment l'installer, le régler, le lancer, le réparer ? |
| Contributing guidelines | Comment participer ? |
| Additional documentation | Où lire la suite ? |
| How to get help | Qui contacter en cas de blocage ? |
| Terms of use | Sous quelle licence ? |
Le gabarit prévoit aussi, en option, un logo avec des badges et une
table des matières. Pour healthcheck, projet minuscule, on retient la
description, le public, les prérequis, l'installation, le premier usage,
la configuration, le dépannage, l'aide et la licence.
Le README ne contient pas tout : référence complète des options, architecture, récit d'une décision de conception ou historique des versions n'y ont pas leur place. Il renvoie vers le document adapté : la documentation détaillée, une décision d'architecture (l'ADR, objet de la leçon suivante) ou le CHANGELOG. La leçon Choisir le bon document explique ce découpage et le piège du README fourre-tout.
Les conseils d'écriture du gabarit (décrire l'utilité avant les technologies, un verbe en tête de chaque instruction, des listes numérotées pour les étapes) rejoignent ceux de Écrire clair.
Comment tester un README comme un inconnu ?
Section intitulée « Comment tester un README comme un inconnu ? »Un README relu par son auteur paraît toujours complet : l'auteur sait déjà ce que le texte omet. Le geste central est donc de jouer le README à la lettre, comme le ferait un inconnu, dans un dossier vierge, sans rien corriger de tête. Chaque écart entre ce que dit le texte et ce qui se passe est un défaut du README, pas du lecteur.
Chaque étape suit la même boucle : une action, un résultat attendu écrit dans le README, une comparaison avec ce qu'on observe. Le schéma ci-dessous la résume : suivez la flèche épaisse tant que le résultat observé est égal à l'attendu, et sortez par la flèche fine au premier écart.
Que révèle le premier jet ?
Section intitulée « Que révèle le premier jet ? »Le premier jet de healthcheck tient en cinq sections : titre, une phrase,
prérequis (« Python », « git »), installation (git clone <url-du-dépôt> puis
cd healthcheck), utilisation (healthcheck.py http://localhost:8000) et
licence (« MIT »). Il paraît correct. Rejoué dans un dossier vierge, il
échoue de plusieurs façons. Chaque commande rend un code de sortie, un
nombre que le shell conserve après son exécution (0 pour un succès, autre
chose pour un échec), que l'on lit avec echo $?.
$ healthcheck.py http://localhost:8000healthcheck.py: command not found (code de sortie 127)$ python healthcheck.py http://localhost:8000OK 200 http://localhost:8000 (11 ms) (code de sortie 0)Premier échec : le script n'est pas dans le PATH, la liste des dossiers où le
shell cherche les commandes. Le code 127 signifie « commande introuvable ».
Il faut écrire python3 healthcheck.py ..., avec python3 et non python,
parce que certaines distributions, dont Debian et Ubuntu, ne fournissent pas
de commande python par défaut (la PEP 394
le prévoit ; sur Debian et Ubuntu, le paquet python-is-python3 la crée).
Le second résultat est pire : OK 200 s'affiche, donc tout semble marcher. Or
le README ne lançait rien sur le port 8000 : un autre service de la
machine y répondait déjà. Le lecteur croit son installation réussie alors
qu'il a testé le service d'un autre. Un exemple qui réussit par hasard est
pire qu'un exemple qui échoue. Le README doit fournir sa propre cible, sur un
port peu courant.
Les autres défauts relevés tiennent en une liste :
- Aucune sortie attendue : le lecteur ne peut pas reconnaître le succès.
- Un placeholder
<url-du-dépôt>: sans l'URL réelle, personne ne clone. - « Python » sans version ni commande pour vérifier qu'il est présent.
- Rien sur la configuration (le délai d'attente) ni sur les erreurs.
- « MIT » sans renvoi vers le fichier de licence, et aucun moyen de demander de l'aide.
- Aucun public cible : on ne sait pas à qui l'outil s'adresse.
Jouer l'URL sans schéma ajoute un cas limite : localhost:8765 produit
FAIL localhost:8765 (unknown url type: localhost). Le message cite
localhost et non l'URL entière, trompeur pour un débutant : il mérite une
ligne de dépannage.
À quoi ressemble la version corrigée ?
Section intitulée « À quoi ressemble la version corrigée ? »Voici le README final, rejoué à son tour dans un dossier vierge. Il ne cite
que la première ligne de --help : la ligne options: s'appelait
optional arguments: avant Python 3.10. Règle : n'afficher en sortie
attendue que la partie qui ne change pas d'une version à l'autre. L'URL de
clonage est fictive : dans votre README, mettez l'URL réelle du dépôt.
# healthcheck
**healthcheck** vérifie en une commande qu'une URL répond, et le dit par uncode de sortie que vos scripts peuvent lire.
Il s'adresse à toute personne qui veut surveiller un site ou une API depuis unterminal ou un script, sans installer d'outil de supervision.
## Prérequis
- **Python 3** (testé avec 3.12) : `python3 --version` doit afficher un numéro de version.- **git**, pour récupérer le dépôt.
Aucun paquet Python supplémentaire n'est nécessaire.
## Installation
1. Clonez le dépôt, puis entrez dans le dossier :
```bash git clone https://github.com/exemple-fictif/healthcheck.git cd healthcheck ```
2. Vérifiez que le script démarre :
```bash python3 healthcheck.py --help ```
Sortie attendue (début) :
```text usage: healthcheck [-h] [--timeout TIMEOUT] [--quiet] url ```
## Premier usage
Dans un second terminal, lancez un petit site local sur le port 8765 (le port8000 est souvent déjà pris) :
```bashpython3 -m http.server 8765 --bind 127.0.0.1```
Dans le premier terminal, vérifiez-le :
```bashpython3 healthcheck.py http://127.0.0.1:8765```
Sortie attendue (la durée varie) :
```textOK 200 http://127.0.0.1:8765 (5 ms)```
Le script rend aussi un **code de sortie**, que vous lisez avec `echo $?` justeaprès la commande :
| Code | Signification || --- | --- || `0` | L'URL répond avec un code HTTP 2xx ou 3xx || `1` | Réponse en erreur (4xx, 5xx) ou connexion impossible || `2` | Délai dépassé (timeout) |
## Configuration
Le délai maximal d'attente est de **5 secondes** par défaut. Deux façons de lechanger, la première l'emportant sur la seconde :
```bashpython3 healthcheck.py --timeout 2 http://127.0.0.1:8765HEALTHCHECK_TIMEOUT=2 python3 healthcheck.py http://127.0.0.1:8765```
L'option `--quiet` n'affiche rien : seul le code de sortie renseigne, ce quisuffit dans un script.
## Dépannage
| Symptôme | Cause probable | Solution || --- | --- | --- || `FAIL ... (Connection refused)` | Rien n'écoute sur ce port | Lancez le site de test, ou corrigez l'URL || `FAIL ... (unknown url type: ...)` | L'URL n'a pas de `http://` | Écrivez l'URL complète, schéma compris || `FAIL 404 ...` | Le serveur répond, mais pas sur ce chemin | Corrigez le chemin de l'URL || `TIMEOUT ...` | Le serveur met trop de temps à répondre | Augmentez `--timeout`, ou vérifiez le serveur |
## Obtenir de l'aide
Ouvrez une issue : <https://github.com/exemple-fictif/healthcheck/issues>.
## Licence
Distribué sous licence MIT, voir le fichier [LICENSE](LICENSE).Le parcours de l'inconnu y est celui que tout README devrait offrir : il découvre (titre et public), installe (prérequis, clone, vérification), obtient un premier usage avec un résultat attendu, configure, puis trouve de l'aide. Chaque section répond à une étape de ce parcours, et chaque commande est suivie de ce qu'il doit voir.
La session complète de ce README a été rejouée avec Python 3.12.13 et
git 2.43.0 : l'aide s'affiche, OK 200 sur le site de test, FAIL 404
sur un chemin absent, FAIL ... (Connection refused) serveur arrêté, et l'URL
sans schéma produit l'erreur décrite en dépannage. Seule la version 3.12 a
été testée : le README écrit « testé avec 3.12 » et n'affirme aucun minimum.
Comment tenir un CHANGELOG au format Keep a Changelog ?
Section intitulée « Comment tenir un CHANGELOG au format Keep a Changelog ? »Le CHANGELOG répond à une autre question que le README : « qu'est-ce qui a changé depuis la version que j'utilise ? ». Keep a Changelog (version 1.1.0, keepachangelog.com) le définit comme un fichier contenant « une liste sélectionnée (en anglais curated) et classée chronologiquement des changements notables de chaque version ». Son slogan : ne laissez pas vos amis déverser le journal git dans un changelog.
Quelle est la structure du fichier ?
Section intitulée « Quelle est la structure du fichier ? »Le fichier s'appelle CHANGELOG.md. La version la plus récente est en
premier, chaque version a son titre avec sa date au format
AAAA-MM-JJ (la page recommande ce format ISO, sans ambiguïté entre les
usages régionaux). En tête, une section Unreleased accumule les
changements pas encore publiés : on voit ce qui arrive, et à la publication on
déplace son contenu dans la nouvelle version.
Sous chaque version, les entrées sont groupées par six types :
| Type | Contenu |
|---|---|
Added | Nouvelles fonctionnalités |
Changed | Changements dans des fonctionnalités existantes |
Deprecated | Fonctionnalités bientôt retirées |
Removed | Fonctionnalités retirées |
Fixed | Corrections de bogues |
Security | Correctifs de vulnérabilités |
Une version n'affiche que les types qui ont des entrées : l'historique de la
page signale que les sections vides occupent de la place et font du bruit.
Une version retirée après publication se marque [YANKED] à la fin de son
titre.
À quoi ressemble le CHANGELOG de healthcheck ?
Section intitulée « À quoi ressemble le CHANGELOG de healthcheck ? »Voici le CHANGELOG du projet, avec deux versions publiées et un changement en
attente. En bas du fichier, les liens de comparaison transforment chaque
titre [0.2.0] en lien vers l'écart entre deux tags (une étiquette
nommée, comme v0.2.0, posée sur un commit pour marquer une version).
# Changelog
Tous les changements notables de ce projet sont consignés dans ce fichier.
Le format s'inspire de [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),et ce projet suit le [versionnage sémantique](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
- Option `--quiet` : n'affiche rien, seul le code de sortie renseigne.
## [0.2.0] - 2026-10-08
### Added
- Option `--timeout` et variable d'environnement `HEALTHCHECK_TIMEOUT` pour régler le délai maximal d'attente.
### Changed
- Le délai maximal par défaut passe de 3 à 5 secondes.
### Fixed
- Un délai dépassé affiche `TIMEOUT` et rend le code de sortie `2`, au lieu d'une trace d'erreur Python.
## [0.1.0] - 2026-10-02
### Added
- Vérification d'une URL : affiche le code HTTP et la durée de la réponse.- Code de sortie `0` si l'URL répond en 2xx ou 3xx, `1` sinon.- Délai maximal fixé à 3 secondes.
[Unreleased]: https://github.com/exemple-fictif/healthcheck/compare/v0.2.0...HEAD[0.2.0]: https://github.com/exemple-fictif/healthcheck/compare/v0.1.0...v0.2.0[0.1.0]: https://github.com/exemple-fictif/healthcheck/releases/tag/v0.1.0Les sections Deprecated, Removed et Security sont absentes : rien à y
mettre, donc aucune section vide. La première version pointe vers releases/tag/ parce qu'il n'existe
aucune version antérieure à comparer, comme dans le changelog de
keepachangelog.com. Ces liens sont fictifs, comme l'adresse du dépôt.
Une entrée n'est utile que si elle est vraie : chaque ligne de la
section 0.2.0 a été vérifiée par exécution. Avec un serveur qui accepte la
connexion et ne répond jamais, la version 0.1.0 affiche une trace d'erreur
Python (TimeoutError: timed out, code 1, environ 3 s), tandis que 0.2.0
affiche TIMEOUT http://127.0.0.1:8766 (> 5.0 s) avec le code 2 après environ
5 s. --timeout 1 ramène l'attente à 1 s, et l'option l'emporte sur la
variable d'environnement. Keep a Changelog met en garde : un changelog qui ne
mentionne qu'une partie des changements peut être « aussi dangereux que de ne
pas avoir de changelog ».
Pourquoi ne pas copier le journal git ?
Section intitulée « Pourquoi ne pas copier le journal git ? »Le dépôt de healthcheck compte cinq commits entre v0.1.0 et v0.2.0 :
$ git log --oneline v0.1.0..v0.2.055b5f7c chore(release): 0.2.0193b00c docs: document timeout configuration and exit codes92072ab fix: exit with code 2 on timeout instead of a traceback8e0dd15 refactor: raise default timeout from 3 to 5 secondse535b8f feat: add --timeout option and HEALTHCHECK_TIMEOUT variableLe CHANGELOG n'en retient que trois entrées. Le commit de release et celui
de documentation n'intéressent pas l'utilisateur. Le commit refactor devient
pourtant une entrée Changed, parce qu'il modifie un comportement visible : le
délai par défaut. Le préfixe d'un commit ne décide pas ; la curation est un
jugement humain sur ce que l'utilisateur observe. Keep a Changelog le dit
ainsi : un commit documente une étape de l'évolution du code, une entrée de
changelog documente la différence notable, souvent répartie sur plusieurs
commits, pour la communiquer clairement. Un export brut est « plein de bruit » :
commits de fusion, titres obscurs, changements de documentation.
Des outils génèrent un brouillon à partir de messages bien formés. Conventional Commits explique le format de ces messages et son lien avec les numéros de version, et Maintenir un projet Git compare les générateurs. Un brouillon généré se relit et se réécrit, comme n'importe quelle autre entrée.
Quel numéro de version choisir ?
Section intitulée « Quel numéro de version choisir ? »Keep a Changelog ne définit pas les numéros : il demande seulement d'indiquer si
l'on suit le versionnage sémantique (SemVer 2.0.0).
Dans cette spécification, un numéro MAJEUR.MINEUR.CORRECTIF s'incrémente
ainsi : MAJEUR pour un changement incompatible de l'API (l'interface que
les utilisateurs emploient, ici la ligne de commande), MINEUR pour
un ajout de fonctionnalité compatible, CORRECTIF pour une correction
compatible. Pour healthcheck, l'option --timeout ajoute une fonctionnalité,
d'où 0.1.0 vers 0.2.0. Le détail des tags est dans
Tags Git.
Dans quel ordre publier une version ?
Section intitulée « Dans quel ordre publier une version ? »L'ordre compte : on met à jour le CHANGELOG avant de poser le tag annoté, sinon la
version taguée ne décrit pas ses propres changements. Dans le dépôt de healthcheck, le
contenu de Unreleased est déplacé sous [0.2.0] - 2026-10-08 dans un commit de release
chore(release): 0.2.0, et le tag annoté v0.2.0 est posé sur ce commit.
Le geste de release est détaillé dans
Maintenir un projet Git.
Le schéma suivant suit la chaîne de gauche à droite ; le lien en pointillé
rappelle que les liens de comparaison du bas du fichier se mettent à jour avec
le commit de release.
Une différence mérite d'être connue : le README suit la branche principale,
le CHANGELOG suit les versions publiées. Sur main, le README de
healthcheck documente --quiet, alors que cette option, sous Unreleased,
n'est pas encore dans une version.
Ce format n'est pas réservé au code : la leçon Versionner ses modules Terraform le recommande pour des modules, et il convient aussi bien à un contenu versionné, une documentation ou une formation.
Pourquoi un linter Markdown proteste-t-il contre un bon CHANGELOG ?
Section intitulée « Pourquoi un linter Markdown proteste-t-il contre un bon CHANGELOG ? »Un linter Markdown comme markdownlint-cli2 applique des règles de style,
numérotées MDxxx. Sur la première rédaction du README et du CHANGELOG, avec la
configuration par défaut, markdownlint-cli2 0.23.3 (markdownlint 0.41.1) a rendu
16 erreurs. Dix venaient du séparateur de tableau |---|---| (règle
MD060), à écrire | --- | --- |. Les autres sont plus intéressantes.
- MD024 interdit deux titres identiques. Or Keep a Changelog répète
### Addeddans chaque version. Ce n'est pas le CHANGELOG qui est faux : on règle la règle pour n'interdire les doublons que sous un même parent. - MD013 limite les lignes à 80 colonnes, ce que les tableaux dépassent. On l'exclut pour les tableaux.
La configuration, dans .markdownlint-cli2.jsonc à la racine du dépôt :
{ "config": { "MD024": { "siblings_only": true }, "MD013": { "tables": false } }}Avec elle, la commande ci-dessous (qui télécharge l'outil via npx et exige
Node.js) rend « 0 issues » sur les deux fichiers.
npx --yes markdownlint-cli2@0.23.3 README.md CHANGELOG.mdBrancher ce contrôle dans la CI, pour qu'il bloque une pull request, relève du niveau suivant de la formation. Retenez ici le principe : face à un linter, on configure l'outil, on ne déforme pas le format recommandé.
Exercice : que manque-t-il à ce README ?
Section intitulée « Exercice : que manque-t-il à ce README ? »Voici le README d'un autre petit projet, resumeur, un script qui compte les
lignes d'un fichier. Sans l'exécuter, listez au moins six défauts qu'un inconnu
rencontrerait, puis comparez avec le corrigé.
# resumeur
Compte des lignes.
## Installation
Installez les dépendances et lancez le script.
## Utilisation
resumeur.py fichier.txt
## Licence
Voir le dépôt.Pour chercher : relisez chaque section en vous demandant « que fait un inconnu exactement, et que voit-il ensuite ? ».
Corrigé
- Pas de description utile : « Compte des lignes » ne dit ni pourquoi l'utiliser, ni pour qui.
- Aucun prérequis : quel langage, quelle version, quels outils ?
- « Installez les dépendances » sans commande : lesquelles, comment ? Aucune URL de clonage non plus.
- Commande non exécutable telle quelle :
resumeur.pyn'est pas dans lePATH(code 127), il fautpython3 resumeur.py fichier.txtou./resumeur.py, et dire laquelle. - Fichier d'entrée absent :
fichier.txtn'existe pas dans un dossier vierge. Le README doit fournir un exemple ou le créer. - Aucune sortie attendue : le lecteur ne sait pas reconnaître le succès.
- Aucun dépannage ni aide : pas d'erreur courante, pas de lien d'issue.
- Licence invisible : « Voir le dépôt » ne désigne aucun fichier.
Les points 3 à 6 se trouvent en jouant le README dans un dossier vierge ; les points 1, 2, 7 et 8 se voient en le comparant au gabarit.
À retenir
Section intitulée « À retenir »- Le README est une porte d'entrée : à quoi ça sert, est-ce pour moi, comment le faire tourner. Le reste est renvoyé vers d'autres documents.
- Le gabarit de The Good Docs Project est un menu : on garde les sections utiles au projet.
- On teste un README en le jouant à la lettre dans un dossier vierge :
commande introuvable,
pythoncontrepython3, exemple qui réussit par hasard, sortie attendue absente, placeholder d'URL. - Chaque étape donne sa sortie attendue, limitée à la partie stable d'une version à l'autre.
- Un CHANGELOG Keep a Changelog :
Unreleaseden haut, version la plus récente d'abord, dateAAAA-MM-JJ, six types, sections vides omises,[YANKED]pour une version retirée, liens de comparaison en bas. - Un changelog est rédigé, pas exporté : une entrée décrit un changement observable, la curation reste un jugement humain.
- On met à jour le CHANGELOG avant le tag.
- Un linter se configure (MD024, MD013) plutôt que de déformer le format.
Contrôle de connaissances
Validez vos connaissances avec ce quiz interactif
Informations
- Le chronomètre démarre au clic sur Démarrer
- Questions à choix multiples, vrai/faux et réponses courtes
- Vous pouvez naviguer entre les questions
- Les résultats détaillés sont affichés à la fin
Lance le quiz et démarre le chronomètre
Vérification
(0/0)Score par domaine
Un domaine regroupe plusieurs guides et reçoit plusieurs questions : son score est plus fiable qu'un score par thème, qui porte souvent sur une seule question.
Bilan
Points forts
Aucun sujet réussi à 80 % sur au moins deux questions pour l’instant.
Points faibles
Aucun sujet sous le seuil de réussite.
À faire ensuite
Des indices pour retenter votre chance ?
Continuer le cours : Architecture Decision Records (ADR) : tracer vos choix
Nouveau quiz complet avec des questions aléatoires
Retravailler uniquement les questions ratées
Retour à la liste des certifications