
Une collection en production se teste sur plusieurs versions d'ansible-core et de Python pour garantir la compatibilité descendante. Le pattern 2026 : GitHub Actions avec une matrice ansible-core × python, exécutant ansible-test sanity --docker + ansible-test units + ansible-lint --strict dans un Docker conforme. Avec SHA pinning des actions, permissions: {} au global, persist-credentials: false sur checkout.
Cette page fournit les deux pipelines équivalents (GitHub Actions + GitLab CI), durcis selon les pratiques 2026 (zizmor compliant), prêts à copier-coller dans votre repo de collection.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Workflow GitHub Actions complet pour collection Ansible.
- Matrice
ansible-core stable-2.18 × stable-2.19 × devel × Python 3.11 × 3.12. ansible-test sanity --dockerdans la CI.ansible-test units --dockersur les modules Python.ansible-lint --strict --profile production.- SHA pinning des actions (zizmor compliant).
- Équivalent GitLab CI avec
parallel:matrix.
Prérequis
Section intitulée « Prérequis »- Avoir une collection custom (cf Créer une collection).
- Compte GitHub ou GitLab.
Workflow GitHub Actions complet
Section intitulée « Workflow GitHub Actions complet »name: Ansible teston: push: branches: [main] pull_request:
permissions: {} # ← global = aucune
jobs: sanity: name: sanity (${{ matrix.ansible }} / py${{ matrix.python }}) runs-on: ubuntu-24.04 permissions: contents: read strategy: fail-fast: false # ← continue même si une combo échoue matrix: ansible: - stable-2.18 - stable-2.19 - devel python: - "3.11" - "3.12" steps: - name: Checkout uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: path: ansible_collections/student/webapp persist-credentials: false # ← bloque token Git
- name: Setup Python uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: "${{ matrix.python }}"
- name: Install ansible-core ${{ matrix.ansible }} run: | pip install "https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz"
- name: ansible-test sanity --docker working-directory: ansible_collections/student/webapp run: | ansible-test sanity --docker default -v --color
units: name: units (${{ matrix.ansible }} / py${{ matrix.python }}) runs-on: ubuntu-24.04 permissions: contents: read strategy: fail-fast: false matrix: ansible: [stable-2.18, devel] python: ["3.11", "3.12"] steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: path: ansible_collections/student/webapp persist-credentials: false
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: "${{ matrix.python }}"
- run: | pip install "https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz"
- name: ansible-test units --docker working-directory: ansible_collections/student/webapp run: | ansible-test units --docker default -v --color --python ${{ matrix.python }}
lint: name: ansible-lint runs-on: ubuntu-24.04 permissions: contents: read steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: path: ansible_collections/student/webapp persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: { python-version: "3.12" }
- run: pip install ansible-lint==25.5.0 ansible-core==2.18.1
- name: ansible-lint --strict --profile production working-directory: ansible_collections/student/webapp run: ansible-lint --strict --profile productionBonnes pratiques 2026 visibles
Section intitulée « Bonnes pratiques 2026 visibles »| Pattern | Pourquoi |
|---|---|
permissions: {} au workflow | Aucune permission par défaut sur le GITHUB_TOKEN. Élargies par job au strict nécessaire. |
persist-credentials: false | Bloque l'usage du token Git après checkout (évite l'exfiltration via une étape compromise). |
uses: <owner>/<repo>@<SHA40> | Protège contre tag mutation attacks (un attaquant qui repush v4.2.2). |
fail-fast: false | Continue même si une combo échoue → on voit lesquelles passent. |
path: ansible_collections/student/webapp | Ansible-test exige cette arborescence pour fonctionner. |
Pipeline GitLab CI équivalent
Section intitulée « Pipeline GitLab CI équivalent »stages: - lint - sanity - units
variables: ANSIBLE_VERSIONS: "stable-2.18 stable-2.19 devel" PYTHON_VERSIONS: "3.11 3.12"
.collection_setup: &collection_setup before_script: - pip install "https://github.com/ansible/ansible/archive/${ANSIBLE_VERSION}.tar.gz" - mkdir -p ansible_collections/student/webapp - shopt -s extglob && cp -r !(ansible_collections) ansible_collections/student/webapp/ - cd ansible_collections/student/webapp
ansible-lint: stage: lint image: python:3.12@sha256:7ad6d21a25a94b2c00e685e82c2fd298de814353d9ee0e3f7f2cd4fca063df60 script: - pip install ansible-lint==25.5.0 ansible-core==2.18.1 - ansible-lint --strict --profile production
sanity: stage: sanity image: python:${PYTHON_VERSION} parallel: matrix: - PYTHON_VERSION: ["3.11", "3.12"] ANSIBLE_VERSION: ["stable-2.18", "stable-2.19", "devel"] <<: *collection_setup script: - ansible-test sanity --docker default -v --color
units: stage: units image: python:${PYTHON_VERSION} parallel: matrix: - PYTHON_VERSION: ["3.11", "3.12"] ANSIBLE_VERSION: ["stable-2.18", "devel"] <<: *collection_setup script: - ansible-test units --docker default -v --color --python ${PYTHON_VERSION}🔍 Observation : parallel:matrix GitLab CI donne le même effet que la matrice GitHub Actions. <<: *collection_setup factorise le before_script partagé. Résultat fonctionnellement équivalent.
Linter le workflow avec zizmor
Section intitulée « Linter le workflow avec zizmor »zizmor .github/workflows/ansible-test.ymlDétecte automatiquement :
- Actions non pinnées par SHA.
permissions:trop larges.- Variables d'env exposées sans escape.
- Absence de
persist-credentials: false. - Templates
${{ ... }}injectables.
🔍 Observation : zizmor est l'outil de référence 2026 pour auditer les workflows GitHub. À ajouter en pre-commit hook pour bloquer les régressions de sécurité supply-chain.
Pour aller plus loin, coverage
Section intitulée « Pour aller plus loin, coverage »- name: ansible-test units --coverage run: | ansible-test units --docker default --coverage ansible-test coverage html ansible-test coverage --requirements xmlCombiner avec coverage --coverage-check pour bloquer la CI si la couverture chute sous un seuil :
ansible-test coverage check --requirements xml || exit 1Mettre en pratique
Section intitulée « Mettre en pratique »Un pipeline de collection se juge à ce qu'il refuse de laisser passer. Ce lab vous fait croiser les versions d'ansible-core et de Python dans une matrice, lancer ansible-test sanity et ansible-test units en conteneur, puis épingler chaque action par son SHA de commit. La correction relit le workflow produit et échoue si une action reste sur un tag mobile ou si la matrice se réduit à une seule version.
À retenir
Section intitulée « À retenir »- Matrice ansible-core × Python = 4-6 combinaisons typiques en CI.
- SHA pinning des actions GitHub (40 caractères hex), zizmor compliant.
permissions: {}au global,persist-credentials: falsesur checkout.ansible-test sanity --docker default= validation FQCN + doc + types.ansible-test units --docker= pytest sur les modules Python.ansible-lint --strict --profile production= qualité maximale.- Zizmor lint des workflows en pre-commit hook.