Module — Releases & CI/CD
Pipeline GitLab + @spektrum/release-util pour la SemVer + génération de changelog. Deux flavours de release : staging et prod, avec des tags d'image disjoints.
Cette page complète
RELEASING.mdà la racine du repo. Pour la procédure stepwise détaillée et les variables CI requises, voir ce fichier. Cette page donne le « pourquoi » et le mapping avec le reste du knowledge base.
Flow général
feature MR ──merge──► master ──cut release──► release/X.Y.Z MR ──merge──► master ──publish CI firesDeux releases possibles :
| Type | Branche release | Tag git | Tags Docker pushés |
|---|---|---|---|
| Staging | release/X.Y.Z-staging.N | X.Y.Z-staging.N | :X.Y.Z-staging.N + :latest-staging |
| Prod | release/X.Y.Z | X.Y.Z | :X.Y.Z + :latest |
Promouvoir :latest ne touche pas :latest-staging, et vice-versa.
Cutter une release
Deux chemins équivalents :
Depuis GitLab (sans setup local)
- Pipeline
master→ clic manuel surtrigger-release-stagingoutrigger-release-prod. - Le job exécute
npx @spektrum/release-util release --env <staging|prod>qui :- Incrémente SemVer en fonction des commits conventional commits.
- Régénère
CHANGELOG.md. - Crée le commit
chore(release): X.Y.Z[-staging.N]. - Push la branche
release/X.Y.Z[-staging.N]. - Ouvre une MR vers
master.
- Review + merge.
- Pipeline trunk sur
masterdétecte le subject du commit de release → firepublish-stagingoupublish-prod.
Depuis un poste dev
npx @spektrum/release-util release --env staging
# ou
npx @spektrum/release-util release --env prodMême résultat : branche + MR.
Ce que fait publish-staging / publish-prod
Tous deux étendent .publish-base dans .gitlab-ci.yml. Pipeline :
git remote set-url --push origin "https://gitlab-ci-token:${RELEASE_TOKEN}@…"— utilise le token de release (write_repository + api) plutôt queCI_JOB_TOKEN.eval $(npx @spektrum/release-util tag)— exporteRELEASE_VERSION,RELEASE_ENV, etc., crée + push l'annotated git tag (X.Y.ZouX.Y.Z-staging.N).docker buildavec :--build-arg VERSION_TAG=${RELEASE_VERSION}→ exposé sur/.--build-arg BUILD_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ")→ idem.
docker tag+docker push:- Tag versionné
:X.Y.Zou:X.Y.Z-staging.N. - Tag flottant
:latestou:latest-staging.
- Tag versionné
npx @spektrum/release-util badges --out badges— génèrestaging.svgetprod.svg(artefact CI, expirenever).
Variable CI obligatoire
| Variable | Scope | Pourquoi |
|---|---|---|
RELEASE_TOKEN | write_repository + api | Push de la branche/tag de release sur un protected ref + création de MR via l'API GitLab |
Doit être Protected + Masked. CI_JOB_TOKEN ne suffit pas (pas de push protected, pas d'API MR).
Settings GitLab projet
- Default branch :
master. Doit matchertrunkBranchdans.release-it.json. - Merge method (Settings → Merge requests) : Merge commit ou Fast-forward.
- Squash on merge : désactivé pour les MR
release/*. Squasher réécrit le subjectchore(release):→ la regex depublish-*ne match plus → pas de publish.
Mapping conventional commits → bump SemVer
@release-it/conventional-changelog avec preset conventionalcommits (cf. .release-it.json) :
| Commit | Bump SemVer |
|---|---|
feat: … | minor |
fix: … | patch |
chore: …, docs: …, ci: | pas de bump |
feat!: … ou BREAKING CHANGE: dans le footer | major |
Conventions du repo
- Conventional commits sur
master. - Pas de fast-forward direct sur
master(toujours via MR). release-it(@release-it/conventional-changelog) régénèreCHANGELOG.mdà chaque release. Ne pas l'éditer à la main — il est dérivé.- Les commits
chore(release): X.Y.Zsont émis automatiquement et matchés par les regexes du CI. Ne pas modifier le format sans mettre à jour les rules dans.gitlab-ci.yml(sectionspublish-staging.rulesetpublish-prod.rules).
Tester localement avant cut
# Voir la prochaine version qui serait calculée
npx @spektrum/release-util release --env staging --dry-run
# ou
npx @spektrum/release-util release --env prod --dry-run(Vérifier la sortie ; ne fait rien côté git.)
Procédure de rollback
Image
Re-déployer l'image avec un tag immuable précédent : :X.Y.Z ou :X.Y.Z-staging.N. Les tags flottants :latest / :latest-staging sont des pointeurs mobiles, à éviter pour un rollback ciblé.
# Côté serveur prod
docker pull registry.internal.spektrum-suisse.ch/buchsearch:3.1.0
# Modifier le compose pour pointer ce tag
# docker compose up -dTag git
@spektrum/release-util push des tags annotés. Pour rollback un tag git mal envoyé (cas rare) :
git tag -d 3.2.0
git push origin :refs/tags/3.2.0 # delete remoteAttention : si le pipeline publish-* est déjà passé, l'image est déjà en registry — la suppression du tag git n'enlève pas l'image.
DB
yoyo n'a pas de rollback automatique sur ce projet (cf. modules/migrations.md). Restaurer depuis backup si une migration cassée est appliquée en prod.
Pannes courantes
| Symptôme | Cause typique |
|---|---|
publish-staging / publish-prod ne tourne pas après merge de la MR release | Squash on merge activé → subject du commit réécrit → la regex rules: ne match plus. Désactiver squash, re-cut. |
eval $(... tag) plante avec "could not push to protected ref" | RELEASE_TOKEN manquant, ou scope insuffisant (write_repository), ou git remote set-url --push mal formé. |
trigger-release-* plante en créant la MR | RELEASE_TOKEN manque le scope api. |
Endpoint / affiche encore l'ancienne version après release | --build-arg VERSION_TAG=... pas passé, OU le déploiement pull encore le digest précédent (cache). Forcer un pull. |
publish-staging ET publish-prod tournent sur le même pipeline trunk | Ne devrait pas arriver (regexes disjointes). Si oui, vérifier que le subject de commit ne match qu'une seule forme. |
Suivi des releases
- Tags git : visibles sur GitLab (Settings → Tags).
- Images Docker :
registry.internal.spektrum-suisse.ch→ repobuchsearch. - Changelog :
CHANGELOG.mdà la racine. - Badges : artefacts du job
publish-*→badges/staging.svgetbadges/prod.svg. Inclus dans le README typiquement.
Workflow recommandé pour les modifs de schéma
Quand une PR contient une migration (migrations/*.sql) :
- Merge sur
master(la migration est appliquée sur la DB de test en CI). - Cut une release staging.
- Déployer staging → la migration tourne sur la DB staging au boot via
entrypoint.sh. - Tester quelques jours sur staging.
- Cut une release prod → idem en prod.
Pour les migrations destructives (DROP COLUMN, etc.), prévoir une migration en deux temps : (1) ajouter le nouveau, (2) après une release qui consomme le nouveau, supprimer l'ancien. Évite les reverts en urgence.

