
Publier un rôle, c'est promettre à d'autres équipes qu'une version donnée se comportera toujours de la même façon. Cette page explique d'où vient réellement le numéro de version d'un rôle, ce que cette mécanique garantit et ce qu'elle ne garantit pas, puis déroule la publication sur Galaxy et sur un Automation Hub privé.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Comprendre où Ansible lit la version d'un rôle, et pourquoi ce n'est pas là où on le croit.
- Choisir le bon incrément de version selon la nature du changement.
- Rédiger un
CHANGELOG.mdqui sert vraiment à ses lecteurs. - Publier un rôle, puis une collection, en sachant ce qui distingue les deux mécaniques.
- Automatiser la publication au moment du tag.
Prérequis
Section intitulée « Prérequis »- Un rôle testé, idéalement avec Molecule.
- Un dépôt Git, et un compte Galaxy si vous visez la publication publique.
D'où vient la version d'un rôle
Section intitulée « D'où vient la version d'un rôle »Voici le point qui surprend la plupart des gens : un rôle ne contient aucune information de version. Ni dans meta/main.yml, ni ailleurs. La commande d'initialisation ne crée aucun champ pour cela, et vous pouvez le vérifier sur un rôle fraîchement généré.
ansible-galaxy role init webservergrep -i version webserver/meta/main.ymlLa seule sortie concerne min_ansible_version, qui déclare la version d'Ansible requise, pas celle du rôle.
La version vient donc d'ailleurs : c'est la référence Git que le consommateur écrit dans son requirements.yml, et qu'ansible-galaxy transmet telle quelle à Git.
---roles: - src: https://github.com/stephrobert/ansible-role-webserver scm: git name: webserver version: v1.0.0 # un tag, une branche ou un SHA de commitÀ l'installation, Ansible affiche la référence utilisée, et la retient :
- monrole (v1.0.0) was installed successfullyLa preuve inverse est plus parlante encore. Listez des rôles installés sans référence explicite :
$ ansible-galaxy role list- stephrobert.users, (unknown version)- mesure.webcontent, (unknown version)(unknown version) : faute de référence Git, Ansible n'a aucun moyen de savoir ce qu'il a installé. Le rôle lui-même ne le lui dit pas.
Ce qu'un tag garantit, et ce qu'il ne garantit pas
Section intitulée « Ce qu'un tag garantit, et ce qu'il ne garantit pas »Puisque la version est une référence Git, sa fiabilité est celle de Git. Or un tag Git se déplace. Rien n'empêche un auteur de retaguer v1.0.0 sur un autre commit, et le résultat mérite d'être vu.
# Après un premier v1.0.0 déjà publié, l'auteur retague le même numérogit tag -f -a v1.0.0 -m "même numéro, autre code"Le consommateur qui réinstalle la même version reçoit alors un contenu différent :
- monrole (v1.0.0) was installed successfullyLe numéro n'a pas bougé, le code si. Trois conséquences pratiques en découlent.
Ne retaguez jamais une version publiée. Un correctif justifie un nouveau numéro, jamais la réécriture d'un ancien : c'est le seul moyen pour vos consommateurs de se fier au numéro qu'ils épinglent.
Épinglez par SHA quand l'enjeu le justifie. Un commit est immuable, un tag non. Sur une chaîne de production sensible, version: 3f2a1b... vaut mieux qu'un tag.
Un rôle interne mérite les mêmes égards qu'un rôle public : vos collègues sont des consommateurs comme les autres.
Choisir le bon incrément
Section intitulée « Choisir le bon incrément »Le versionnage sémantique répond à une question simple du point de vue du consommateur : « est-ce que je peux mettre à jour sans relire mon code ? »
| Incrément | Ce qui le déclenche | Effet chez le consommateur |
|---|---|---|
| MAJOR | Variable renommée ou supprimée, comportement par défaut modifié | Doit relire son code avant de monter de version |
| MINOR | Nouvelle variable optionnelle, nouvelle plateforme supportée | Peut monter sans rien changer |
| PATCH | Correction de bogue, optimisation interne | Peut monter les yeux fermés |
Le critère décisif est donc l'interface publique du rôle, c'est-à-dire ses variables de defaults/ et le comportement qu'elles produisent. Refactoriser tasks/main.yml sans toucher à cette interface reste un PATCH, même si le fichier change entièrement.
Le fichier CHANGELOG.md
Section intitulée « Le fichier CHANGELOG.md »Le CHANGELOG répond à la question que se pose un consommateur devant une nouvelle version : « qu'est-ce que ça change pour moi ». Le format Keep a Changelog structure cette réponse.
# Changelog du rôle webserver
## [2.0.0] - 2026-04-26
### Changed- `webserver_port` renommée en `webserver_listen_port` (rupture)
### Added- Support Debian via `vars/<os_family>.yml`
### Fixed- Le handler de rechargement se déclenchait deux fois
## [1.1.0] - 2026-03-15
### Added- Variable `webserver_worker_processes`Les sections utilisables sont Added, Changed, Deprecated, Removed, Fixed et Security, toutes facultatives. Écrivez chaque entrée du point de vue de celui qui consomme le rôle, pas de celui qui l'écrit : « variable renommée » lui parle, « refactoring du template » non.
Le geste de release, pas à pas
Section intitulée « Le geste de release, pas à pas »Une publication se déroule toujours dans le même ordre, et cet ordre a une raison : on ne tague que du code déjà validé, car le tag est ce que les autres consommeront.
# 1. Décrire ce qui change, avant tout le restevim CHANGELOG.md
# 2. Valider : les tests d'abord, le linter ensuitemolecule testansible-lint --profile production roles/webserver/
# 3. Enregistrer la préparation de versiongit add CHANGELOG.mdgit commit -m "release: v1.2.0"
# 4. Poser le tag annoté sur ce commit précisgit tag -a v1.2.0 -m "Release v1.2.0 : support multi-distribution"
# 5. Publier commits et tagsgit push origin main --tagsDeux détails de cette séquence méritent une explication.
Le tag est annoté (-a), c'est-à-dire qu'il porte un auteur, une date et un message, là où un tag simple n'est qu'un pointeur anonyme. Pour une version publiée, cette traçabilité est le minimum.
Le nom du tag porte un préfixe v, comme v1.2.0. Cette convention est quasi universelle et facilite le filtrage, comme le montrent les règles de déclenchement d'intégration continue plus bas, qui s'appuient dessus.
Publier un rôle, publier une collection
Section intitulée « Publier un rôle, publier une collection »Les deux objets ne se publient pas du tout de la même façon, et confondre les deux est la source d'erreur la plus fréquente.
Un rôle n'est jamais téléversé. Galaxy se contente d'indexer votre dépôt Git : il lit les tags et présente le rôle dans son catalogue, le code restant chez vous. La commande correspondante est import, et non publish, qui n'existe pas pour un rôle.
# Galaxy va lire le dépôt GitHub et indexer ses tagsansible-galaxy role import stephrobert ansible-role-webserverL'intégration peut aussi être automatisée depuis l'interface de Galaxy, ou en ligne de commande, pour que chaque nouveau tag soit indexé sans intervention :
ansible-galaxy role setup github stephrobert ansible-role-webserver <secret>Une collection, elle, est une archive que vous construisez puis téléversez. C'est là que publish intervient.
ansible-galaxy collection buildansible-galaxy collection publish stephrobert-networking-1.0.0.tar.gz --token "$GALAXY_TOKEN"Notez que l'option historique --api-key existe toujours comme alias de --token.
Automatiser la publication
Section intitulée « Automatiser la publication »Le tag devient alors le seul geste manuel, la chaîne d'intégration s'occupant du reste. Voici la forme GitHub Actions, déclenchée par le motif de tag posé à l'étape précédente.
name: Publier sur Galaxy
on: push: tags: ['v*.*.*'] # ne se déclenche que sur un tag de version
jobs: release: runs-on: ubuntu-24.04 permissions: contents: read steps: - uses: actions/checkout@<SHA> with: persist-credentials: false
- name: Construire et publier la collection run: | ansible-galaxy collection build ansible-galaxy collection publish ./*.tar.gz --token "$GALAXY_TOKEN" env: GALAXY_TOKEN: ${{ secrets.GALAXY_TOKEN }}L'équivalent GitLab repose sur la même idée, le déclenchement se lisant dans la règle plutôt que dans un événement.
release: stage: release rules: - if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/ script: - ansible-galaxy collection build - ansible-galaxy collection publish ./*.tar.gz --token "$GALAXY_TOKEN"Dans les deux cas, le jeton vit dans les secrets de la forge, jamais dans le dépôt.
Publier en interne avec Automation Hub
Section intitulée « Publier en interne avec Automation Hub »Les entreprises qui ne souhaitent pas exposer leur code utilisent un Automation Hub privé, déclaré comme serveur Galaxy dans ansible.cfg.
[galaxy]server_list = corporate_hub
[galaxy_server.corporate_hub]url = https://hub.corp.example.com/api/automation-hub/token = <jeton>Cette configuration apporte trois choses : le code reste interne, une équipe sécurité peut valider chaque contenu avant publication, et le hub sert de miroir de Galaxy public pour les environnements sans accès Internet.
Après la publication
Section intitulée « Après la publication »Le tag poussé, il reste trois gestes qui font la différence entre un rôle qu'on ose adopter et un rôle qu'on subit.
Le README.md doit refléter la version publiée. Une variable ajoutée sans documentation n'existe pas pour vos consommateurs, et une variable renommée sans mise à jour du README les envoie droit dans le mur. C'est la première page que lit quelqu'un qui découvre votre rôle.
Les notes de version de la forge reprennent la section correspondante du CHANGELOG. Sur GitHub, elles se créent depuis le tag, dans « Releases ». Ce doublon apparent a son utilité : c'est ce que voient les personnes qui suivent le dépôt sans cloner.
Un guide de migration accompagne toute version majeure. Il ne remplace pas le CHANGELOG, il en tire les conséquences pratiques, avec la manipulation exacte à effectuer.
# Guide de migration
## De la 1.x vers la 2.0
### Variable renommée
`webserver_port` devient `webserver_listen_port`.
Correction sur l'ensemble de vos playbooks :
sed -i 's/webserver_port/webserver_listen_port/g' playbooks/*.ymlSans ce document, une rupture correctement annoncée par un incrément MAJOR reste une rupture que chacun devra résoudre seul.
Mettre en pratique
Section intitulée « Mettre en pratique »Le versionnage d'un rôle se juge sur les traces qu'il laisse, pas sur les intentions annoncées. Le lab vous fait appliquer le semver à un rôle existant, tenir son CHANGELOG.md sur trois versions, poser un tag Git annoté et dérouler le workflow de publication jusqu'à son automatisation. Les tests contrôlent la structure produite : incrément cohérent avec la rupture d'interface, entrées de journal datées, référence Git en place.
Pièges courants
Section intitulée « Pièges courants »| Symptôme | Cause | Solution |
|---|---|---|
(unknown version) dans role list | Rôle installé sans référence Git | Épingler une version: dans requirements.yml |
| Deux machines reçoivent un code différent pour la même version | Tag déplacé après publication | Ne jamais retaguer, publier un nouveau numéro |
401 en intégration continue malgré --api-key | Un server_list est défini, l'option est ignorée | Placer le jeton dans la configuration du serveur |
ANSIBLE_GALAXY_TOKEN sans effet | Cette variable n'existe pas | Utiliser ANSIBLE_GALAXY_TOKEN_PATH, qui attend un chemin |
publish refusé sur un rôle | La commande n'existe que pour les collections | Utiliser ansible-galaxy role import |
| Rupture non signalée aux consommateurs | Incrément MINOR au lieu de MAJOR | Toute variable renommée ou supprimée impose un MAJOR |
À retenir
Section intitulée « À retenir »- Un rôle ne porte aucune version : ni
meta/main.ymlni aucun autre fichier ne la contient. La référence Git durequirements.ymlfait foi. - Un tag Git se déplace, donc un même numéro peut livrer deux codes différents. Ne retaguez jamais une version publiée, et épinglez par SHA quand l'enjeu le justifie.
- L'incrément se décide sur l'interface publique du rôle, c'est-à-dire ses variables, pas sur le volume de code modifié.
- Un rôle s'importe, une collection se publie :
role importindexe un dépôt Git,collection publishtéléverse une archive. ANSIBLE_GALAXY_TOKENn'existe pas. La variable reconnue estANSIBLE_GALAXY_TOKEN_PATH, et elle attend un chemin de fichier.
Pour aller plus loin
Section intitulée « Pour aller plus loin »- Exécution en CI/CD : le pipeline complet qui construit, scanne, signe et publie, en prolongement de la release manuelle.
- Construire un EE custom : distribuer non plus un rôle seul, mais l'environnement d'exécution qui va avec.
- HashiCorp Vault / OpenBao : sortir le jeton Galaxy du dépôt et des variables d'environnement du poste.