Objectifs
- Automatiser les tâches répétitives et sujettes à erreur du processus de “release”.
- Lire un numéro de version depuis un fichier pour garantir une source de vérité unique.
- Générer automatiquement des notes de version (
CHANGELOG) à partir de l’historique Git. - Créer et pousser un tag Git annoté pour marquer la version.
Le Scénario
Le processus de release est souvent manuel : on met à jour un fichier de version, on compile un changelog en copiant-collant des messages de commit, on crée un tag, puis on pousse le tout. C’est lent et on oublie souvent une étape. Un script peut automatiser tout cela pour rendre le processus rapide, fiable et cohérent.
La Stratégie du script
- Lire la version depuis un fichier
VERSION(ex:1.2.3). - Vérifier que l’on est sur la branche
mainet que le dépôt est “propre”. - Trouver le dernier tag Git pour déterminer le point de départ du changelog.
- Générer les notes de version en listant les commits depuis ce dernier tag.
- Créer un commit de “release” qui met à jour le
CHANGELOG.md. - Créer un tag Git annoté
v1.2.3. - Pousser les commits et le tag vers le dépôt distant.
Le Script Complet
Voici un exemple de script de release. Il utilise des commandes Git avancées mais illustre bien la puissance de l’automatisation.
#!/usr/bin/env bash
# Mode strict
set -euo pipefail
# --- Documentation ---
# Description:
# Automatise le processus de release : mise à jour du changelog,
# commit de version, et création d'un tag Git.
#
# Usage:
# ./release.sh
# Le script lit la version dans le fichier 'VERSION'.
readonly SCRIPT_NAME="$(basename "$0")"
# --- Fonctions ---
die() {
echo >&2 "[ERREUR] $@"
exit 1
}
# --- Fonction Principale ---
main() {
# --- Validations ---
if ! git diff --quiet; then
die "Le répertoire de travail n'est pas propre. Veuillez commiter ou stasher vos changements."
fi
if [[ "$(git rev-parse --abbrev-ref HEAD)" != "main" ]]; then
die "Ce script doit être lancé depuis la branche 'main'."
fi
if [[ ! -f "VERSION" ]]; then
die "Le fichier 'VERSION' est manquant."
fi
# --- Logique Principale ---
local VERSION
VERSION=$(cat VERSION)
local TAG_NAME="v$VERSION"
echo "Préparation de la release : $TAG_NAME..."
if git rev-parse "$TAG_NAME" >/dev/null 2>&1; then
die "Le tag '$TAG_NAME' existe déjà."
fi
# --- Génération du Changelog ---
local LAST_TAG
# Trouve le tag le plus récent
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || git rev-list --max-parents=0 HEAD)
echo "Génération des notes de version depuis le tag '$LAST_TAG'..."
local CHANGELOG_HEADER="## $TAG_NAME ($(date +'%Y-%m-%d'))"
local GIT_LOG
GIT_LOG=$(git log "${LAST_TAG}..HEAD" --oneline --no-merges)
# On utilise un fichier temporaire pour construire le nouveau changelog
local TMP_CHANGELOG
TMP_CHANGELOG=$(mktemp)
{
echo "$CHANGELOG_HEADER"
echo ""
echo "$GIT_LOG"
echo ""
echo "---"
echo ""
cat CHANGELOG.md
} > "$TMP_CHANGELOG"
mv "$TMP_CHANGELOG" CHANGELOG.md
echo "Le CHANGELOG.md a été mis à jour. Veuillez le vérifier avant de continuer."
read -p "Appuyez sur Entrée pour commiter et tagger, ou Ctrl+C pour annuler."
# --- Commit et Tag ---
git add CHANGELOG.md
git commit -m "chore(release): préparer la release $TAG_NAME"
git tag -a "$TAG_NAME" -m "Release $TAG_NAME"
echo "Tag '$TAG_NAME' créé."
# --- Push ---
read -p "Pousser les changements et le tag vers 'origin' ? (o/N) " -n 1 -r
echo
if [[ $REPLY =~ ^[Oo]$ ]]; then
echo "Push en cours..."
git push origin main
git push origin "$TAG_NAME"
echo "Release terminée."
else
echo "Push annulé. N'oubliez pas de pousser manuellement : git push origin main && git push origin $TAG_NAME"
fi
}
# --- Point d'entrée ---
main "$@"
Bonnes Pratiques Mises en Œuvre
- Garde-fous : Le script refuse de s’exécuter si des changements sont en cours ou si on n’est pas sur la bonne branche.
- Source de vérité unique : La version est lue depuis un fichier
VERSION, ce qui évite les erreurs de saisie. - Automatisation du changelog : Générer le changelog à partir de Git incite à écrire des messages de commit clairs et utiles.
- Interaction utilisateur : Le script demande confirmation avant d’effectuer les actions irréversibles (commit, push).
- Tags annotés :
git tag -acrée un “vrai” objet tag avec un message et une date, ce qui est la bonne pratique pour les releases.
Pièges Évités
- Releaser sur la mauvaise branche : La vérification de la branche est une sécurité essentielle.
- Oublier de pusher les tags :
git pushne pousse pas les tags par défaut. Il fautgit push origin <nom_du_tag>ougit push --tags. - Changelog manuel fastidieux : L’automatisation rend le processus indolore.
Exercices
-
Mise en place du projet :
- Créez un nouveau dépôt Git (
git init). - Créez un fichier
VERSIONcontenant0.1.0. - Créez un fichier
CHANGELOG.mdvide. - Faites un premier commit.
- Créez un nouveau dépôt Git (
-
Simuler le développement :
- Créez un fichier
app.js. - Faites deux ou trois commits avec des messages clairs (ex: “feat: ajouter authentification”, “fix: corriger bug d’affichage”).
- Créez un fichier
-
Lancer la release :
- Copiez le script de cette leçon dans votre projet sous le nom
release.shet rendez-le exécutable. - Lancez
./release.sh. - Lorsque le script vous le demande, ouvrez
CHANGELOG.mddans un autre terminal pour vérifier son contenu. - Validez et laissez le script se terminer (vous pouvez choisir de ne pas pusher).
- Vérifiez avec
git logetgit tagque le commit de release et le tagv0.1.0ont bien été créés.
- Copiez le script de cette leçon dans votre projet sous le nom