Aller au contenu
Infrastructure as Code medium

CI/CD GitHub Actions pour rôle Ansible : workflow complet 2026

8 min de lecture

Logo Ansible

Un workflow GitHub Actions complet pour un rôle Ansible 2026 : lint en fail-fast → matrice Molecule (Rocky 9, AlmaLinux 10, Debian 12 × ansible-core 2.17, 2.18). Actions pinnées par SHA, permissions minimales (least-privilege), persist-credentials: false.

  • Structure d’un workflow .github/workflows/test.yml.
  • Configurer un job lint en fail-fast (avant Molecule).
  • Définir une matrice multi-dimensions : distros × versions Ansible.
  • Sécuriser le workflow (SHA pinning, permissions minimales).
  • Déclencheurs : push, pull_request, schedule (re-test périodique).
---
name: Test webserver role
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
schedule:
- cron: '0 6 * * 1' # lundi 6h — re-test contre dernières versions
permissions: {} # ← deny-by-default au top
jobs:
lint:
name: Lint (ansible-lint + yamllint)
runs-on: ubuntu-24.04
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- name: Setup Python
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
with:
python-version: '3.12'
- name: Install lint tools
run: pip install ansible-lint==25.* yamllint
- name: Run yamllint
run: yamllint roles/
- name: Run ansible-lint (profile production)
run: ansible-lint --profile=production roles/
molecule:
name: Molecule (${{ matrix.distro }} / ansible-core ${{ matrix.ansible }})
runs-on: ubuntu-24.04
needs: lint # ← lint doit passer en premier
permissions:
contents: read
strategy:
fail-fast: false
matrix:
distro:
- rockylinux9
- alma10
- ubuntu2404
ansible:
- 2.17
- 2.18
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- name: Setup Python
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
with:
python-version: '3.12'
- name: Install Molecule + plugins
run: |
pip install \
"ansible-core==${{ matrix.ansible }}.*" \
"molecule>=26.0" \
"molecule-plugins[podman]>=25.0" \
"ansible-lint==25.*"
- name: Install Ansible collections
run: ansible-galaxy collection install -r requirements.yml
- name: Run molecule test
run: molecule test
env:
MOLECULE_DISTRO: ${{ matrix.distro }}
PY_COLORS: 1
ANSIBLE_FORCE_COLOR: 1
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
schedule:
- cron: '0 6 * * 1' # lundi 6h
  • push sur main/develop : re-test après merge.
  • pull_request sur main : test avant merge.
  • schedule hebdomadaire : détecte les régressions liées aux mises à jour upstream (nouvelles versions Ansible, nouvelles images Docker base).
permissions: {}

Deny-by-default au top du workflow. Chaque job redéclare ses permissions explicitement (contents: read pour les jobs qui n’écrivent rien).

Pourquoi : si une dependency malicieuse s’exécute, elle ne peut pas push sur le repo, créer des releases, ou taguer. Mandatory en 2026 (recommandation Red Hat / GitHub Security).

- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

Pas @v4 ni @main. Le SHA40 du commit garantit que vous exécutez exactement ce code, pas une version bumpée silencieusement.

Pourquoi : actions/checkout@v4 est un tag mutable — quelqu’un avec accès au repo peut le re-pointer. Le SHA est immutable.

- uses: actions/checkout@<SHA>
with:
persist-credentials: false

Par défaut, actions/checkout persiste un token GitHub dans le runner pour des operations Git ultérieures. Si une action malicieuse tourne après, elle peut utiliser ce token pour push.

persist-credentials: false = pas de token persisté. Mandatory dès qu’on lance des deps non-officielles.

strategy:
fail-fast: false
matrix:
distro: [rockylinux9, alma10, ubuntu2404]
ansible: [2.17, 2.18]

3 distros × 2 versions = 6 jobs en parallèle. Si un job échoue, les 5 autres continuent (fail-fast: false) — vous voyez toutes les régressions, pas juste la première.

molecule:
needs: lint

Le job molecule attend que lint passe. Sans cela, des heures de Molecule peuvent tourner pour découvrir un simple problème de lint à la fin. Fail-fast = économie CI minute.

repo-rôle/
├── .github/
│ └── workflows/
│ └── test.yml ← ce fichier
├── roles/
│ └── webserver/
│ ├── tasks/
│ ├── defaults/
│ └── meta/
├── molecule/
│ └── default/
├── requirements.yml ← collections requises
└── README.md

Cette page a un lab d’accompagnement : labs/ci/github-actions/ dans stephrobert/ansible-training.

Le lab fournit .github/workflows/test.yml complet + requirements.yml. 8 tests structure validés (jobs, matrix, SHA pinning, permissions, etc.).

Fenêtre de terminal
cd ~/Projets/ansible-training/labs/ci/github-actions/
cat .github/workflows/test.yml
pytest -v challenge/tests/ # 8 tests structure
SymptômeCauseFix
Error: Unable to resolve actionSHA invalide ou repo renomméMettre à jour le SHA après avoir vérifié le repo officiel
Tests passent locallement, ratent en CIDifférence Python/Ansible versionAligner basepython tox avec python-version GHA
molecule test lent (>20 min)Pas de cache Docker layersUtiliser actions/cache sur ~/.local
secret manquantPas de secrets: configuré pour la publicationAller dans repo Settings → Secrets and variables
Permission denied sur l’API GitHubpermissions: {} trop restrictifAjouter contents: read ou pull-requests: write selon besoin
  • permissions: {} au top + redéclaration par job = least-privilege.
  • Actions pinnées par SHA + persist-credentials: false = sécurité supply chain.
  • needs: lint avant Molecule = fail-fast économie CI.
  • Matrice 2D distros × versions = couverture complète automatique.
  • schedule: hebdomadaire = détecte régressions upstream.

Ce site vous est utile ?

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

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn