
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.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- 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).
Le workflow .github/workflows/test.yml
Section intitulée « Le workflow .github/workflows/test.yml »---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: 1Décortication
Section intitulée « Décortication »on: — déclencheurs
Section intitulée « on: — déclencheurs »on: push: branches: [main, develop] pull_request: branches: [main] schedule: - cron: '0 6 * * 1' # lundi 6hpushsurmain/develop: re-test après merge.pull_requestsurmain: test avant merge.schedulehebdomadaire : détecte les régressions liées aux mises à jour upstream (nouvelles versions Ansible, nouvelles images Docker base).
permissions: {} — least-privilege
Section intitulée « permissions: {} — least-privilege »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).
Actions pinnées par SHA
Section intitulée « Actions pinnées par SHA »- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2Pas @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.
persist-credentials: false
Section intitulée « persist-credentials: false »- uses: actions/checkout@<SHA> with: persist-credentials: falsePar 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.
Matrice 2D — distros × versions
Section intitulée « Matrice 2D — distros × versions »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.
needs: lint
Section intitulée « needs: lint »molecule: needs: lintLe 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.
Structure du repo attendue
Section intitulée « Structure du repo attendue »repo-rôle/├── .github/│ └── workflows/│ └── test.yml ← ce fichier├── roles/│ └── webserver/│ ├── tasks/│ ├── defaults/│ └── meta/├── molecule/│ └── default/├── requirements.yml ← collections requises└── README.mdPratiquer dans le lab
Section intitulée « Pratiquer dans le lab »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.).
cd ~/Projets/ansible-training/labs/ci/github-actions/
cat .github/workflows/test.ymlpytest -v challenge/tests/ # 8 tests structurePièges courants
Section intitulée « Pièges courants »| Symptôme | Cause | Fix |
|---|---|---|
Error: Unable to resolve action | SHA invalide ou repo renommé | Mettre à jour le SHA après avoir vérifié le repo officiel |
| Tests passent locallement, ratent en CI | Différence Python/Ansible version | Aligner basepython tox avec python-version GHA |
molecule test lent (>20 min) | Pas de cache Docker layers | Utiliser actions/cache sur ~/.local |
secret manquant | Pas de secrets: configuré pour la publication | Aller dans repo Settings → Secrets and variables |
Permission denied sur l’API GitHub | permissions: {} trop restrictif | Ajouter contents: read ou pull-requests: write selon besoin |
À retenir
Section intitulée « À retenir »permissions: {}au top + redéclaration par job = least-privilege.- Actions pinnées par SHA +
persist-credentials: false= sécurité supply chain. needs: lintavant Molecule = fail-fast économie CI.- Matrice 2D distros × versions = couverture complète automatique.
schedule:hebdomadaire = détecte régressions upstream.