Créer un tag de release¶
Vous êtes mainteneur·se de Kirexo et vous voulez déclencher une release : créer un tag Git qui enchaîne automatiquement le build des images Docker, le déploiement de la documentation sur GitLab Pages et la création de la release GitLab avec changelog. Cette recette explique les deux façons de le faire.
Prérequis¶
- Vous avez les droits Maintainer ou Owner sur le projet GitLab.
- La variable CI/CD
GITLAB_TOKENest configurée (cf. Variables CI/CD GitLab) — un Personal Access Token avec le scopewrite_repository(les project access tokens sont réservés à GitLab Premium/Ultimate). - Les images
kirexo-base,kirexo-devetkirexo-prodont déjà été buildées au moins une fois — sinon les jobsdocker:build-*sur tag échoueraient car il n'y a rien à mettre en cache (et la pipeline qualité, qui dépend de ces images, ne tournerait pas non plus). L'imagekirexo-docsne nécessite pas ce bootstrap : son jobdocker:build-docsestneeds: []et tourne automatiquement avantpagessur tag.
Pourquoi passer par une pipeline et pas par git tag en local
git push --tags fonctionnerait, mais ça impose d'avoir une clé SSH ou un PAT configurés sur la machine qui pousse, et ça ne marche pas depuis un environnement où le repo n'est pas cloné en écriture (ex. depuis Claude Code en mode bypassPermissions qui n'a pas la clé de la personne). La pipeline tag:create crée le tag côté serveur via l'API GitLab — l'auteur·rice de la release n'a besoin que de son accès UI ou de glab.
Méthode A — Depuis l'UI GitLab¶
- Aller sur Build → Pipelines → Run pipeline (bouton en haut à droite).
- Choisir la branche
main. - Ajouter une variable :
- Key :
CREATE_TAG - Value :
true - Type :
Variable(pasFile). - Cliquer sur Run pipeline.
La pipeline créée ne contient que le job tag:create (stage tag). Tous les autres jobs sont filtrés par leurs rules: — la pipeline CREATE_TAG=true est volontairement isolée pour ne pas dédoubler la pipeline qualité.
Garde-fou : une pipeline verte est exigée sur le dernier commit de main
Avant de créer le tag, tag:create vérifie qu'au moins une pipeline success existe pour le dernier commit de main ($CI_COMMIT_SHA) — typiquement la pipeline de validation jouée au merge. Si aucune pipeline verte n'est trouvée, le job échoue et le tag n'est pas créé. Le but : ne jamais figer une release sur un commit dont la CI est rouge ou encore en cours.
Pour outrepasser ce garde-fou dans un cas exceptionnel, ajouter une seconde variable FORCE_TAG à true (en plus de CREATE_TAG) :
| Key | Value |
|---|---|
CREATE_TAG |
true |
FORCE_TAG |
true |
Avec FORCE_TAG=true, le statut de pipeline n'est plus vérifié : le tag est créé inconditionnellement. À réserver aux situations où l'on sait que le commit est sain mais que la pipeline n'a pas (re)tourné.
Méthode B — Depuis le CLI avec glab¶
Le retour de glab affiche l'ID et l'URL de la pipeline créée — suivez-la via glab pipeline view <id> ou directement dans l'UI.
Pour outrepasser le garde-fou de pipeline verte (cf. Méthode A), ajouter --variables FORCE_TAG=true :
Ce que fait tag:create¶
Le job tourne sur alpine:3 avec GIT_STRATEGY: none (pas besoin de cloner le code — l'API agit côté serveur GitLab) et exécute :
- Garde-fou (sauf si
FORCE_TAG=true) : interrogeGET /projects/:id/pipelines?sha=$CI_COMMIT_SHA&status=successet refuse de taguer (exit 1) si aucune pipelinesuccessn'existe pour le dernier commit demain. Le contrôle est fail-safe : si l'appel API échoue (token invalide, réseau), le compteur retombe à0et le job bloque plutôt que de risquer une release non validée. - Calcule le nom du tag :
TAG_NAME=$(date -u +%Y%m%d%H%M)— formatYYYYMMDDHHMMen UTC. -
Appelle
POST /projects/:id/repository/tagsavec${GITLAB_TOKEN}: -
Affiche la réponse JSON via
jq '{name, target, message}'.
Le --fail de curl fait échouer le job si l'API renvoie un statut HTTP ≥ 400 — typiquement 403 Forbidden si GITLAB_TOKEN n'a pas le scope write_repository, ou 409 Conflict si un tag du même nom existe déjà (très peu probable avec le format YYYYMMDDHHMM).
Ce qui se déclenche ensuite¶
Dès que GitLab détecte le tag créé, il démarre automatiquement une nouvelle pipeline $CI_COMMIT_TAG. Cette pipeline ne rejoue ni les vérifications qualité ni les tests : ceux-ci ont déjà tourné sur le même SHA dans la pipeline main que tag:create a exigée verte (cf. Optimisation pipeline de tag). Seuls les jobs qui produisent un livrable ou dont le résultat dépend de l'instant T du tag s'exécutent :
| Stage | Job | Effet |
|---|---|---|
quality |
quality:composer-audit |
Filet de sécurité rejoué sur le SHA du tag — capture une CVE Composer éventuellement publiée entre le merge et le tag. Si rouge, la pipeline du tag échoue et les jobs docker:* / release:* ne tournent pas. |
docker |
docker:build-base, docker:build-dev, docker:build-prod |
Build + push automatique. kirexo-base et kirexo-dev reçoivent :php8.5 + :latest ; kirexo-prod reçoit en plus le tag de version immuable :$CI_COMMIT_TAG (cf. Déployer Kirexo en production). |
docker |
docker:build-docs, docker:build-supply-chain |
Build + push des images d'outillage CI consommées au stage suivant (mkdocs pour pages, cosign + syft pour docker:sign-prod et release:sbom). |
docker |
docker:sign-prod |
Signature keyless cosign des trois références poussées par docker:build-prod (cf. Supply chain et signatures). |
release |
pages |
Build de la documentation mkdocs en mode strict (via l'image kirexo-docs) et déploiement sur GitLab Pages. |
release |
release:sbom |
Génération du SBOM SPDX + CycloneDX de kirexo-prod:$CI_COMMIT_TAG. |
release |
release:create |
Création de la release GitLab avec changelog des commits depuis le tag précédent + attachement des SBOM en assets. |
maintenance |
container_scanning + security:container-issue |
Scan CVE de kirexo-prod:$CI_COMMIT_TAG fraîchement poussée — signal au moment de la release, pas H+24. Ouvre une issue uniquement si au moins une CVE Critical ou High est remontée (cf. Jobs container_scanning et security:container-issue). |
Le tout sans intervention manuelle supplémentaire. docker:build-docs étant dans le stage docker (avant release), l'image de build de la doc est toujours fraîche au moment où pages la consomme — aucun bootstrap manuel n'est nécessaire pour la doc (contrairement à kirexo-base / kirexo-dev, cf. prérequis).
Pourquoi la qualité ne rejoue pas
tag:create refuse de poser le tag si aucune pipeline success n'existe pour le commit ciblé. Le code du tag est donc, par construction, strictement le même SHA qu'une pipeline qualité verte. Rejouer cs-fix, phpstan, tests unitaires ou E2E donnerait exactement le même résultat — pure duplication de minutes runner. Seul quality:composer-audit est conservé sur tag, parce que la base de vulnérabilités évolue indépendamment du code et qu'une CVE peut être publiée entre le merge et le tag.
Vérifier qu'une release est partie¶
- La pipeline
CREATE_TAG=truedoit être verte. Si le jobtag:createéchoue avec403, vérifier le scopewrite_repositorydu token (cf. Variables CI/CD GitLab). - La pipeline
$CI_COMMIT_TAGapparaît dans la liste des pipelines avec le nom du tag (202605231742) — cliquer dessus pour suivre les jobs Docker et release. - La release apparaît dans Deploy → Releases avec le changelog généré.
- La doc est mise à jour sur
https://doc.kirexo.app/(cf. Configurer le domaine GitLab Pages). - Les images Docker sont visibles dans Deploy → Container Registry :
kirexo-baseetkirexo-devavec les tags:php8.5et:latest;kirexo-prodavec:php8.5,:latestet le tag de version:202605231742(le nom du tag Git) ;kirexo-docsavec le seul tag:latest.
Cas d'erreur¶
Le job tag:create échoue avec 401 Unauthorized¶
Le GITLAB_TOKEN est absent ou expiré. Régénérer le token (Settings → Access Tokens), mettre à jour la variable CI/CD (Settings → CI/CD → Variables) et relancer le job.
Le job tag:create échoue avec 403 Forbidden¶
Le token n'a pas le scope write_repository, ou son rôle est inférieur à Maintainer. Régénérer un token avec les bons droits.
Le job tag:create échoue sans appeler l'API des tags (garde-fou)¶
Le job s'arrête avant la création du tag parce qu'aucune pipeline success n'existe pour le dernier commit de main. Causes typiques : la pipeline de validation est encore en cours, a échoué, ou n'a jamais tourné sur ce commit. Attendre qu'une pipeline passe au vert sur main, puis relancer CREATE_TAG=true. En cas exceptionnel (commit que l'on sait sain mais sans pipeline rejouée), outrepasser avec FORCE_TAG=true (cf. Méthode A / Méthode B).
Pipeline $CI_COMMIT_TAG jamais déclenchée¶
Vérifier que le tag a bien été créé : glab repo view --web puis onglet Tags, ou directement via l'API. Si le tag existe mais aucune pipeline n'est partie, vérifier le workflow:rules dans .gitlab-ci.yml — la règle $CI_COMMIT_TAG doit y figurer.
Le job pages échoue en mode strict¶
mkdocs détecte un lien cassé, un snippet manquant ou un avertissement de plugin. Reproduire localement avec castor docs:build (qui passe les mêmes options) pour identifier la cause exacte avant de retagger.
Voir aussi¶
- Pipeline GitLab CI — listing complet des stages, jobs et déclencheurs.
- Variables CI/CD GitLab — détail de
GITLAB_TOKEN. - Configurer le domaine GitLab Pages — étape de configuration du DNS pour
doc.kirexo.app.