Pipeline qualité & outillage
J'ai construit un pipeline de qualité complet qui couvre l'ensemble du cycle de vie du code : de l'analyse statique locale jusqu'au monitoring en production. Chaque outil de la chaîne a un rôle précis, et tous s'enchaînent pour garantir que rien ne passe entre les mailles du filet.
1. Vue d'ensemble du pipeline
Mon pipeline qualité suit le code depuis l'éditeur jusqu'à la production. Chaque étape ajoute un signal de confiance supplémentaire :
Code
Édition locale
SAST / Lint
Analyse statique
Tests
Unitaires + E2E
Quality Gates
5 gates séquentiels
CI/CD
Pipeline complet
Runtime Audit
Crawl applicatif
Observabilité
Logs, métriques, RUM
2. Analyse statique (local)
La première ligne de défense est locale. Avant même qu'un commit ne soit créé, j'applique une analyse statique stricte sur chaque projet :
cargo clippy
RustLinter Rust avec politique zéro warning. Chaque warning est traité comme une erreur grâce au flag -D warnings.
cargo clippy -- -D warnings ESLint + Biome
TypeScriptDouble linting en mode strict. ESLint pour les règles sémantiques, Biome pour le formatting et les diagnostics rapides.
npx eslint . --max-warnings 0 cargo fmt
RustFormatage automatique du code Rust. J'utilise --check en CI pour vérifier sans modifier.
cargo fmt --check Prettier
TypeScriptFormatage uniforme du code TypeScript, Vue, CSS. Configuration partagée entre tous les projets du lab.
npx prettier --check . 3. Quality Gates (granit-golem)
J'ai défini 5 gates séquentiels dans scripts/testing/quality-gates.ts. Chaque gate doit passer avant que le suivant ne s'exécute. Si un gate échoue, le pipeline s'arrête immédiatement :
Compilation + Clippy
0 warningsLe code doit compiler sans erreur ET passer clippy sans aucun warning. C'est le filtre le plus basique mais aussi le plus important.
Unit Tests
100% passTous les tests unitaires doivent passer. Aucune exception, aucun skip toléré, sauf les #[ignore] documentés.
Security Scanning
cargo-audit + npm auditScan des dépendances pour les vulnérabilités connues. Les CVE critiques et hautes sont bloquantes.
Coverage Check
baseline -5%La couverture ne doit pas baisser de plus de 5% par rapport à la baseline. Cela empêche les régressions progressives sans imposer un seuil absolu irréaliste.
TypeScript + ESLint
strict modeLe frontend passe le typecheck et le linting en mode strict. Pas de any non justifié, pas de warning ignoré.
// quality-gates.ts - 5 gates séquentiels
const gates = [
{ name: 'Compilation + Clippy', cmd: 'cargo build && cargo clippy -- -D warnings' },
{ name: 'Unit Tests', cmd: 'cargo test' },
{ name: 'Security', cmd: 'cargo audit && npm audit' },
{ name: 'Coverage', cmd: 'cargo tarpaulin --threshold 35' },
{ name: 'Frontend', cmd: 'npm run typecheck && npm run lint' },
];
for (const gate of gates) {
console.log(`\n--- Gate: ${gate.name} ---`);
const result = execSync(gate.cmd, { stdio: 'pipe' });
if (result.status !== 0) {
console.error(`FAILED: ${gate.name}`);
process.exit(1);
}
console.log(`PASSED: ${gate.name}`);
} 4. Security scanning (SAST)
La sécurité n'est pas une option, c'est une couche du pipeline. J'ai configuré un scanning SAST adapté à chaque projet :
granit-golem
Rust + Node- cargo-audit v0.22.1 - Vulnérabilités des crates Rust
- cargo-deny v0.19.0 - Licences, advisories, sources
- npm audit - Dépendances frontend, Nuxt
marble-minotaur
Node.js- npm audit - Niveau high, bloquant
- gitleaks - Scan de secrets, bloquant
iolite-ifrit
Cloud OS- trivy - Images conteneurs, HIGH/CRITICAL
- gitleaks - Scan de secrets, bloquant
Tests OWASP Top 10
Au-delà du scan de dépendances, j'ai implémenté des tests actifs OWASP dans security-owasp-tests.ts :
// security-owasp-tests.ts - Tests OWASP Top 10
const owaspChecks = [
{ name: 'HTTPS Enforcement', test: () => checkRedirectToHttps(url) },
{ name: 'Rate Limiting', test: () => floodEndpoint(url, 100) },
{ name: 'Security Headers', test: () => validateHeaders(url, [
'Strict-Transport-Security',
'Content-Security-Policy',
'X-Frame-Options',
'X-Content-Type-Options',
'Referrer-Policy',
])},
{ name: 'SQL Injection', test: () => testSqlInjection(url, payloads) },
{ name: 'XSS Sanitization', test: () => testXssPayloads(url, xssVectors) },
{ name: 'CSRF Protection', test: () => testCsrfToken(url) },
]; HTTPS Enforcement
Vérification de la redirection HTTP vers HTTPS sur tous les endpoints publics.
Rate Limiting
Test de flood sur les endpoints critiques : 100 requêtes en rafale, vérification du 429.
Security Headers
HSTS, CSP, X-Frame-Options, X-Content-Type-Options, Referrer-Policy.
Injection / XSS / CSRF
Payloads d'injection SQL, vecteurs XSS et vérification des tokens CSRF.
5. Mutation Testing
La couverture de code est un indicateur trompeur : 80% de couverture ne signifie pas que les tests sont bons. Pour mesurer la vraie qualité de mes tests, j'utilise le mutation testing avec cargo-mutants :
Mutation
L'outil modifie le code source : remplace un + par un -, un > par un <, supprime une condition...
Exécution
Les tests sont relancés sur le code muté. Si un test échoue, le mutant est "tué", c'est le bon scénario.
Analyse
Si le mutant survit, aucun test n'échoue, c'est un trou dans la couverture réelle. Il faut ajouter un test.
Sur granit-golem, j'atteins un kill rate de 70%+ sur les crates domaine. Chaque mutant survivant est analysé et donne lieu à un test supplémentaire.
// mutation-test.ts - cargo-mutants pour Rust
import { execSync } from 'child_process';
const KILL_RATE_TARGET = 70;
// Lancer les mutations sur les crates critiques
const result = execSync('cargo mutants --package monitoring-domain', {
encoding: 'utf-8',
});
// Parser le résultat
const match = result.match(/killed: (\d+).*total: (\d+)/);
const killRate = (parseInt(match[1]) / parseInt(match[2])) * 100;
if (killRate < KILL_RATE_TARGET) {
console.error(`Kill rate ${killRate}% < target ${KILL_RATE_TARGET}%`);
process.exit(1);
}
console.log(`Mutation kill rate: ${killRate}% (target: ${KILL_RATE_TARGET}%)`); 6. Marble Minotaur - Runtime Web Auditor
Marble Minotaur est mon auditeur web runtime. Il parcourt les applications en production via un crawl BFS (Breadth-First Search) et applique 7 auditeurs pluggables sur chaque page découverte :
SEO
Title, meta description, h1 unique, canonical URL, og:tags pour le partage social.
Accessibility
axe-core WCAG 2.1 AA complet, vérification ARIA, contraste couleurs, navigation clavier.
Performance
Core Web Vitals : LCP, CLS, TTFB. Mesure réelle via Playwright, pas synthétique.
Security Headers
HSTS, CSP, X-Frame-Options, Referrer-Policy. Vérification stricte sur chaque page.
Forms
Validation des champs, attributs autocomplete, sécurité de soumission, labels associés.
i18n
Détection des clés de traduction manquantes, attribut lang, cohérence linguistique.
Images
Sources cassées, alt text manquant, dimensions explicites, formats optimisés.
Scoring et quality gate
Chaque audit produit un score sur 100. Les déductions sont pondérées selon la gravité :
| Problème détecté | Déduction | Limite |
|---|---|---|
| Pages 404 | -35 | par page |
| Blank renders | -25 | par page |
| Erreurs JS | -8 | max -25 total |
| Security headers manquants | variable | pénalité pondérée |
# Lancer un audit Marble Minotaur en mode CI
npx tsx src/cli.ts https://mon-app.com \
--ci \
--ci-threshold 70 \
--output json
# Résultat :
# {
# "score": 82,
# "pages_crawled": 14,
# "auditors": {
# "seo": { "score": 95, "issues": 1 },
# "accessibility": { "score": 78, "issues": 4 },
# "performance": { "score": 88, "issues": 2 },
# "security_headers": { "score": 72, "issues": 3 },
# "forms": { "score": 90, "issues": 0 },
# "i18n": { "score": 85, "issues": 1 },
# "images": { "score": 92, "issues": 1 }
# }
# } 7. Basalt Beholder - Phase d'audit industrialisation
Avant de coder, j'audite. Chaque nouveau projet passe par une phase d'audit industrialisation avec Basalt Beholder : j'évalue la maturité du projet sur 17 volets, j'identifie les lacunes, et je priorise les chantiers. Cette phase est partiellement automatisée via 12 skills Claude Code et une base de connaissances de 187 questions.
Orchestration des audits
Le skill /audit-industrialisation orchestre les 8 audits domaine et produit un rapport consolidé avec scoring par volet :
Architecture
ADRs, API design, coupling, scalability
Security
TLS, auth, secrets, incident response
Testing
Strategy, coverage, flaky tests
Quality
Code quality, dependencies, data validation
Observability
Logging, metrics, tracing, alerting
CI/CD
Pipelines, métriques DORA, déploiement
Compliance
GDPR, data governance, FinOps
Performance Frontend
Rendering, JSC, DOM, memory
Modèle de maturité CMMI
Unmanaged
Aucun processus défini, résultats imprévisibles.
Initial
Processus ad hoc, succès dépendant des individus.
Managed
Processus documentés et reproductibles.
Defined
Standards organisationnels, processus mesurés.
Optimized
Amélioration continue basée sur les métriques.
# Lancer un audit complet via Claude Code skill
/audit-industrialisation
# Audits individuels
/audit-architecture # ADRs, API design, coupling, scalability
/audit-security # TLS, auth, secrets, incident response
/audit-testing # Strategy, coverage, flaky tests
/audit-quality # Code quality, dependencies, data validation
/audit-observability # Logging, metrics, tracing, alerting
/audit-ci-cd # Pipelines, métriques DORA, déploiement
/audit-compliance # GDPR, data governance, FinOps
/audit-performance-frontend # Rendering, JSC, DOM, memory 8. Crock - Code Quality Analyzer
Crock est mon analyseur de qualité de code. Il couvre 6 volets d'analyse, chacun note sur une échelle de maturité 0-4 :
AST Analysis
Complexité cyclomatique, index de maintenabilité, couverture de typage. Analyse l'arbre syntaxique abstrait pour détecter les fonctions trop complexes.
Git Forensics
Conventional commits, fichiers hotspot, modifiés fréquemment, concentration des connaissances, bus factor. Analyse l'historique git pour détecter les risques.
Debt Markers
Tracking des TODO, FIXME, HACK dans le code. Chaque marqueur est indexé avec son ancienneté et sa localisation pour prioriser le remboursement de dette.
Lint Integration
Agrégation des résultats ESLint, Clippy, Biome. Vue unifiée de tous les diagnostics statiques du projet.
Dependency Health
Âge des dépendances, vulnérabilités connues, dépendances non utilisées. Détection des risques de supply chain.
Test Quality
Ratio tests/code, couverture par module, temps d'exécution. Identification des zones sous-testées et des tests fragiles.
9. CI/CD Pipeline Integration
Mon pipeline GitLab CI est structuré en 4 stages. Les stages check et security tournent en parallèle quand c'est possible, et chaque stage est bloquant pour le suivant :
check
security
build
déploiement
# .gitlab-ci.yml - Stages du pipeline
stages:
- check
- security
- build
- deploy
check:
stage: check
parallel:
matrix:
- JOB: [cargo-test, clippy, typecheck, lint]
script:
- case $JOB in
cargo-test) cargo test --workspace ;;
clippy) cargo clippy -- -D warnings ;;
typecheck) cd frontend && npm run typecheck ;;
lint) cd frontend && npm run lint ;;
esac
security:
stage: security
script:
- cargo audit
- cargo deny check advisories
- cd frontend && npm audit --audit-level=high
- gitleaks detect --source . --verbose
- trivy image $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
build:
stage: build
script:
- cargo build --release
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
deploy:
stage: deploy
script:
- docker compose up -d
- ./scripts/smoke-test.sh
- curl -f https://app.example.com/health 10. Chaîne de signaux complète
Voici comment tous les outils s'enchaînent dans mon workflow quotidien, du premier keystroke jusqu'au monitoring en production :
Local (pre-commit)
CI/CD (GitLab)
Production
11. Résultats observés
Voici les résultats concrets de ce pipeline sur l'ensemble de mon lab :
Zéro rollback : pourquoi ?
Les 5 quality gates filtrent les problèmes avant le commit. La CI ajoute une couche de vérification en environnement propre. Et le monitoring Marble Minotaur détecte les régressions après déploiement. Chaque couche attrape ce que la précédente a manqué.
gitleaks en mode bloquant
J'ai configuré gitleaks pour bloquer le pipeline si un secret, API key, token, password, est détecté dans le code ou l'historique git. Résultat : aucun secret n'a jamais été commité sur les projets configurés avec cet outil.
Synthèse
Mon pipeline qualité n'est pas un idéal théorique, c'est le résultat de plusieurs mois d'itération sur des projets réels. Chaque outil a été ajouté en réponse à un problème concret, et chaque gate a prouvé sa valeur en attrapant des bugs qui seraient autrement arrivés en production.
Bloquant par défaut
Chaque signal est bloquant. Si quelque chose échoue, le code ne passe pas. Pas de "on verra plus tard".
Local d'abord
Le maximum de vérifications se fait en local, avant le push. La CI est un filet de sécurité, pas le premier barrage.
Mesurer la vraie qualité
La couverture est un proxy. Le mutation testing, le scoring Marble et les audits Beholder mesurent la qualité réelle.
Sécurité intégrée
La sécurité n'est pas un audit ponctuel, c'est une couche du pipeline. gitleaks, cargo-audit, trivy, OWASP, tout est automatisé.