Aller au contenu
Infrastructure as Code medium

Steampunk Spotter (5.12+) : analyse Ansible cloud, lint étendu, recommandations

40 min de lecture

logo Steampunk Spotter

Steampunk Spotter est un analyseur statique Ansible cloud développé par XLAB Steampunk (Slovénie) qui complète ansible-lint avec des règles que ce dernier n'a pas : compatibilité multi-versions Ansible, détection de modules dépréciés/renommés/déplacés entre collections, scoring de qualité, et récriture automatique d'anti-patterns courants. Le service est freemium (compte gratuit pour usage individuel, plans payants pour équipes/CI). Cette page documente la version 5.12.0 d'avril 2026, testée sur AlmaLinux 10.

  • Installer Spotter via pipx et l'authentifier (token vs user/password).
  • Scanner un playbook, un rôle ou une collection, interpréter les résultats (HINT / WARNING / ERROR).
  • Choisir le bon --display-level et --profile selon le contexte (dev / pre-merge / CI bloquante).
  • Réécrire automatiquement certains anti-patterns avec --rewrite.
  • Intégrer Spotter dans une CI GitHub Actions ou GitLab CI.
  • Comparer Spotter à ansible-lint, quand préférer lequel.
ÉlémentVérification
Python 3.10+python3 --version
pipx installépipx --version
Compte Spotter (gratuit)app.spotter.steampunk.si
Connectivité Internet sortante vers api.spotter.steampunk.sicurl -I https://api.spotter.steampunk.si/

Spotter s'installe comme un paquet Python, mais la CLI seule ne sert à rien : l'analyse est réalisée côté serveur, chaque scan part vers api.spotter.steampunk.si et exige donc un compte et un token. Ces deux étapes sont indissociables, autant les enchaîner. Le token conditionne aussi le quota mensuel consommé.

pipx isole l'outil dans son propre environnement virtuel, ce qui évite les conflits de dépendances avec vos autres paquets Python.

Fenêtre de terminal
pipx install steampunk-spotter
spotter --version
# 5.12.0

L'install crée un binaire ~/.local/bin/spotter qui pointe vers le venv pipx isolé. Pas de pollution Python globale, mises à jour atomiques avec pipx upgrade steampunk-spotter.

Rendez-vous sur app.spotter.steampunk.si/register, créez un compte gratuit (validation email obligatoire). Le plan Community suffit pour un usage individuel : 100 scans/mois, 1 organisation, accès à la majorité des règles.

Les trois voies aboutissent au même résultat, un token transmis à chaque scan, mais elles n'exposent pas ce token de la même façon : le login interactif l'écrit sur disque, la variable d'environnement le garde en mémoire du processus, le flag CLI le laisse dans l'historique du shell et dans la liste des processus.

Fenêtre de terminal
# Méthode 1 : login interactif (génère un token côté serveur, le stocke localement)
spotter login
# → Username/Password ou Token
# Méthode 2 : variable d'environnement (recommandée pour CI/CD)
export SPOTTER_TOKEN="eyJhbGc..."
spotter scan playbook.yml
# Méthode 3 : flag CLI (debug ponctuel uniquement, jamais en production)
spotter scan -t "eyJhbGc..." playbook.yml

Récupérer un token : interface web → My SettingsAPI TokensNew Token. Donnez un nom explicite (ci-github, laptop-bob) pour pouvoir révoquer ciblé plus tard.

spotter scan est la commande centrale de l'outil : elle envoie le contenu YAML au service, reçoit la liste des problèmes et affiche un statut global qui sert de code de sortie en CI. Les options qui suivent ne changent pas la nature de l'analyse, elles filtrent ce qui est affiché, ciblent une version d'Ansible ou déclenchent la correction automatique. Toutes se combinent entre elles.

Sans option, Spotter analyse le fichier avec le profil par défaut et affiche les trois niveaux de résultats.

Fenêtre de terminal
spotter scan playbook.yml

Sortie typique (texte coloré, niveaux HINT / WARNING / ERROR avec liens vers la doc) :

Check results:
playbook.yml:5:7: WARNING: [W1100] Use of with_items is discouraged. Consider using loop instead.
playbook.yml:5:7: HINT: [H1900] (rewritable) Required collection community.general is missing from requirements.yml.
Scan summary:
Spotter took 1.888 s to scan your input.
It resulted in 0 error(s), 1 warning(s) and 1 hint(s).
Can rewrite 1 file(s) with 1 change(s).
Overall status: WARNING

Chaque ligne suit le format <fichier>:<ligne>:<col>: <niveau>: [<id>] <message>. Les ID (W1100, H1900, E1300) sont stables et permettent de skip/enforce ciblé.

La commande accepte plusieurs chemins, fichiers comme répertoires, et ne compte qu'un seul scan dans votre quota. Scanner le répertoire projet entier plutôt qu'un fichier isolé évite aussi les faux positifs sur les collections manquantes, car Spotter voit alors le requirements.yml.

Fenêtre de terminal
# Plusieurs rôles ou collections d'un coup
spotter scan path/to/role1 path/to/role2 path/to/collection/
# Un répertoire entier (tous les .yml détectés)
spotter scan ansible-project/

--display-level fixe le seuil d'affichage : tout ce qui est en dessous disparaît de la sortie. C'est le réglage qui décide de la sévérité de votre porte de qualité, à choisir selon le contexte plutôt qu'une fois pour toutes.

Fenêtre de terminal
# N'afficher que les ERROR (mode strict pour CI bloquante)
spotter scan --display-level error playbook.yml
# Afficher WARNING + ERROR (skip les hints en pre-merge)
spotter scan --display-level warning playbook.yml

Les 3 niveaux :

  • HINT, suggestion (ex: pinning manquant, optimisation possible).
  • WARNING, pratique discutable (ex: with_items legacy, state: latest).
  • ERROR, bug ou faille (ex: module inexistant, paramètre obsolète, secret en clair).

Là où --display-level filtre l'affichage, --profile change le jeu de règles appliqué. Le profil security concentre l'analyse sur les secrets en clair, no_log, les droits sudo et la supply chain ; full active tous les contrôles et produit une sortie beaucoup plus longue.

Fenêtre de terminal
# Profil par défaut (équilibré)
spotter scan playbook.yml
# Profil sécurité (focus secrets, sudoers, no_log, supply chain)
spotter scan --profile security playbook.yml
# Profil complet (tous les checks, peut être verbeux)
spotter scan --profile full playbook.yml

Par défaut, Spotter détecte la version d'ansible-core présente sur la machine et raisonne avec. Sur un runner CI qui n'a pas Ansible installé, cette détection échoue : il faut alors imposer la version cible, sans quoi les règles de compatibilité ne s'appliquent pas.

Fenêtre de terminal
# Scanner contre Ansible 2.18 (pour valider compatibilité descendante)
spotter scan -a 2.18 playbook.yml
# Désactiver la détection auto (utile en CI sur runner sans Ansible)
spotter scan --no-ansible-version playbook.yml

L'option -a [2.0, 2.19] est puissante : Spotter détecte alors les modules/options qui n'existent pas encore dans cette version mineure. Idéal pour des collections publiées qui doivent supporter requires_ansible: ">=2.18".

Les identifiants de règles affichés dans la sortie (W1100, H1900, E1300) servent à désactiver ou forcer un contrôle précis, sans toucher au profil global. C'est la porte de sortie quand une règle ne s'applique pas à votre contexte, et c'est aussi la porte d'entrée de la dette silencieuse.

Fenêtre de terminal
# Désactiver des checks par ID (à justifier en commentaire YAML !)
spotter scan --skip-checks E1300,H1900 playbook.yml
# Forcer des checks même si désactivés par défaut
spotter scan --enforce-checks E001,W400 playbook.yml

Anti-pattern : skip systématique sans documenter le pourquoi. Préférer un commentaire # noqa: E1300 : légitime parce que ... à côté de la ligne fautive.

--rewrite modifie vos fichiers sur place, sans sauvegarde préalable. Ne lancez cette option que sur un dépôt propre, où git vous permet de relire et d'annuler chaque modification.

Fenêtre de terminal
spotter scan --rewrite playbook.yml

Spotter applique les fixes pour les checks marqués (rewritable) dans la sortie. Exemples typiques :

  • with_itemsloop:
  • Modules legacy renommés (yum:ansible.builtin.dnf:)
  • FQCN incomplets (copy:ansible.builtin.copy:)
  • Ajout de community.general dans requirements.yml quand un module y appartient

Toujours git diff après --rewrite pour valider, l'auto-correction n'est jamais 100 % infaillible.

Pour un projet partagé, créer un fichier de config réutilisable :

Fenêtre de terminal
spotter config set ./spotter.yml
spotter config get # affiche la config active
spotter config clear # remet à zéro

Format spotter.yml (équivalent JSON disponible) :

ansible_version: "2.18"
display_level: warning
profile: security
skip_checks:
- event: W003
fqcn: ansible.builtin.uri
enforce_checks:
- event: E005
fqcn: community.crypto.x509_certificate

Avec ce fichier versionné dans le repo, toute l'équipe scanne avec les mêmes règles sans devoir mémoriser les flags CLI.

En CI, deux contraintes s'ajoutent au scan local : le token doit venir d'un gestionnaire de secrets et jamais du fichier de workflow, et le runner n'a généralement pas ansible-core installé, ce qui casse la détection automatique de version. Les deux exemples ci-dessous traitent ces points, et exportent en plus le résultat dans un format consommable par la plateforme.

Ce job installe Spotter, scanne le playbook avec le profil sécurité et publie un rapport SARIF que GitHub Code Scanning affiche directement en commentaire de la pull request.

# .github/workflows/ci.yml : extrait Spotter
name: CI
on: [push, pull_request]
permissions: {}
jobs:
spotter-scan:
runs-on: ubuntu-24.04
permissions:
contents: read
security-events: write # requis par upload-sarif
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: '3.12'
- name: Install Spotter
run: pipx install steampunk-spotter
- name: Scan
env:
SPOTTER_TOKEN: ${{ secrets.SPOTTER_TOKEN }}
run: |
spotter scan \
--origin ci \
--display-level warning \
--profile security \
--sarif spotter.sarif \
playbook.yml
- uses: github/codeql-action/upload-sarif@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3
if: always()
with:
sarif_file: spotter.sarif

Bonnes pratiques CI :

  • --origin ci, Spotter taggue le scan comme provenant de CI (utile pour le filtrage côté UI).
  • --sarif, export au format SARIF que GitHub Code Scanning consomme nativement (alertes inline sur la PR).
  • Token via GitHub Secrets, jamais en clair dans le workflow.
  • Pinning par SHA des actions (zizmor compliant).

Côté GitLab, le token passe par une variable masquée du projet, ce qui l'empêche d'apparaître dans les logs de job. La restriction only: merge_requests réserve le scan aux propositions de fusion, pour ne pas consommer le quota mensuel à chaque commit poussé.

# .gitlab-ci.yml : extrait
spotter-scan:
stage: lint
image: python:3.12-slim@sha256:57cd7c3a7a273101a6485ba99423ee568157882804b1124b4dd04266317710de
variables:
SPOTTER_TOKEN: $SPOTTER_TOKEN_MASKED # variable masquée GitLab
script:
- pip install steampunk-spotter
- spotter scan --origin ci --display-level warning playbook.yml
only:
- merge_requests

Les deux outils ne s'opposent pas sur la qualité de l'analyse mais sur le modèle d'exécution : ansible-lint tourne entièrement sur votre machine, Spotter envoie le code à un service tiers pour bénéficier d'une base de connaissances tenue à jour côté serveur. Lisez le tableau en gardant cette ligne de fracture en tête, car elle décide souvent à elle seule : sur du code propriétaire soumis à une clause de confidentialité, la colonne Confidentialité tranche le débat avant toutes les autres.

Critèreansible-lintSpotter
ModèleCLI local pureCloud (token requis)
CoûtGratuit, open-sourceFreemium
Règles~100 règles (profile production)~300+ règles
Multi-version AnsiblePas natifNatif (-a 2.18)
Modules renommés/déplacésLimitéExcellent (BD à jour côté serveur)
Scoring qualitéNonOui (note globale par scan)
Auto-fix--fix (basique)--rewrite (étendu)
Historique scansNon (chaque run isolé)Oui (UI web)
Intégration GitHub Code ScanningVia pluginsNatif (SARIF)
ConfidentialitéLocal 100 %Code envoyé au cloud

Stratégie recommandée 2026 :

  1. ansible-lint --profile production dans la CI bloquante, base mandatory, gratuit, local.
  2. Spotter en scan pre-merge sur des PR significatives, détecte ce qu'ansible-lint laisse passer.
  3. Spotter --rewrite ponctuellement pour migration de masse (ex: collection renommée upstream).

La plupart des blocages rencontrés avec Spotter ne viennent pas de vos playbooks mais de son modèle cloud : authentification absente, quota épuisé, latence réseau, ou périmètre de scan trop étroit pour que le service voie le requirements.yml. Le tableau donne le symptôme exact tel qu'il s'affiche, sa cause et le correctif.

SymptômeCauseFix
Error: you are not logged in!Pas de token configuréspotter login ou export SPOTTER_TOKEN=...
Scan lent (>10 s) sur petit playbookLatence cloudPréférer ansible-lint en dev, Spotter en CI/pre-merge
Quota mensuel atteintPlan Community = 100 scans/moisUpgrade ou réserver Spotter aux scans CI
Faux positifs H1900 collection missingrequirements.yml pas dans le path scannéScanner le dossier projet plutôt qu'un fichier isolé
ansible_version non détectéPas de ansible-core sur le runner CIForcer avec -a 2.18
  • Spotter v5.12+ : analyseur Ansible cloud freemium, complète ansible-lint (multi-version, modules renommés, scoring).
  • Installation pipx non négociable, pas de pollution Python globale.
  • Token via env var/secret manager uniquement, jamais en clair.
  • --profile security pour focus sécurité, --rewrite pour migration assistée.
  • Stratégie 2026 : ansible-lint en CI bloquante (gratuit, local) + Spotter en pre-merge (détection avancée).
  • Conscience cloud : Spotter envoie votre code à un service tiers, peser sur du code propriétaire.
  • SAST : analyser le code source : Le cadre général de l'analyse statique, dont Spotter est la déclinaison Ansible.
  • MegaLinter : Un seul passage CI pour tous les linters d'un dépôt qui mélange Ansible, YAML et scripts.

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