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