Aller au contenu
Infrastructure as Code medium

Versionner et publier un rôle Ansible : Git semver, Galaxy, Automation Hub

70 min de lecture

Logo Ansible

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é.

  • ComprendreAnsible 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.md qui 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.
  • Un rôle testé, idéalement avec Molecule.
  • Un dépôt Git, et un compte Galaxy si vous visez la publication publique.

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é.

Fenêtre de terminal
ansible-galaxy role init webserver
grep -i version webserver/meta/main.yml

La 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 successfully

La preuve inverse est plus parlante encore. Listez des rôles installés sans référence explicite :

Fenêtre de terminal
$ 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.

Fenêtre de terminal
# Après un premier v1.0.0 déjà publié, l'auteur retague le même numéro
git 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 successfully

Le 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.

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 ? »

Anatomie d'un numéro de version de rôle : MAJOR signale une rupture de compatibilité (1.0.0 vers 2.0.0), MINOR un ajout rétrocompatible (1.0.0 vers 1.1.0), PATCH une correction rétrocompatible (1.0.0 vers 1.0.1)

IncrémentCe qui le déclencheEffet chez le consommateur
MAJORVariable renommée ou supprimée, comportement par défaut modifiéDoit relire son code avant de monter de version
MINORNouvelle variable optionnelle, nouvelle plateforme supportéePeut monter sans rien changer
PATCHCorrection de bogue, optimisation internePeut 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 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.

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.

Fenêtre de terminal
# 1. Décrire ce qui change, avant tout le reste
vim CHANGELOG.md
# 2. Valider : les tests d'abord, le linter ensuite
molecule test
ansible-lint --profile production roles/webserver/
# 3. Enregistrer la préparation de version
git add CHANGELOG.md
git commit -m "release: v1.2.0"
# 4. Poser le tag annoté sur ce commit précis
git tag -a v1.2.0 -m "Release v1.2.0 : support multi-distribution"
# 5. Publier commits et tags
git push origin main --tags

Deux 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.

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.

Fenêtre de terminal
# Galaxy va lire le dépôt GitHub et indexer ses tags
ansible-galaxy role import stephrobert ansible-role-webserver

L'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 :

Fenêtre de terminal
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.

Fenêtre de terminal
ansible-galaxy collection build
ansible-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.

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.

.github/workflows/release.yml
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.

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.

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/*.yml

Sans ce document, une rupture correctement annoncée par un incrément MAJOR reste une rupture que chacun devra résoudre seul.

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.

SymptômeCauseSolution
(unknown version) dans role listRô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 versionTag déplacé après publicationNe jamais retaguer, publier un nouveau numéro
401 en intégration continue malgré --api-keyUn server_list est défini, l'option est ignoréePlacer le jeton dans la configuration du serveur
ANSIBLE_GALAXY_TOKEN sans effetCette variable n'existe pasUtiliser ANSIBLE_GALAXY_TOKEN_PATH, qui attend un chemin
publish refusé sur un rôleLa commande n'existe que pour les collectionsUtiliser ansible-galaxy role import
Rupture non signalée aux consommateursIncrément MINOR au lieu de MAJORToute variable renommée ou supprimée impose un MAJOR
  • Un rôle ne porte aucune version : ni meta/main.yml ni aucun autre fichier ne la contient. La référence Git du requirements.yml fait 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 import indexe un dépôt Git, collection publish téléverse une archive.
  • ANSIBLE_GALAXY_TOKEN n'existe pas. La variable reconnue est ANSIBLE_GALAXY_TOKEN_PATH, et elle attend un chemin de fichier.
  • 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.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn