Comment intégrer l’analyse de code statique dans les pipelines CI/CD ?

Comment intégrer l’analyse de code statique dans les pipelines CI/CD ?

IN-COM Le 11 juin 2026

Chaque ligne de code déployée en production a été validée par une personne qui la croyait correcte. L'analyse statique de code est le système automatisé qui vérifie cette conviction, non pas en exécutant le code, mais en analysant sa structure, en traçant ses flux de données et en le comparant aux vulnérabilités, bogues et violations de qualité connus. La question n'est pas de savoir s'il faut l'exécuter, mais à quel moment du processus, avec quel outil, quels seuils appliquer et comment obtenir un retour d'information suffisamment rapide pour que les développeurs en tiennent compte au lieu de l'ignorer.

La différence entre une analyse statique réduite à une simple formalité et une analyse statique utilisée comme véritable contrôle qualité réside dans sa configuration. Un scanner qui s'exécute et génère un rapport que personne ne lit n'est qu'un leurre. Un contrôle qualité qui fait échouer une compilation lors de l'apparition de nouvelles vulnérabilités critiques, bloque une fusion lorsque la couverture descend en dessous du seuil requis et fournit des informations précises sur les fichiers et les lignes dans l'interface de revue des demandes de fusion est un système dont le comportement s'adapte instantanément aux décisions prises.

À quelle étape du processus exécuter l'analyse statique

L'analyse statique doit être exécutée à plusieurs endroits, chacun ayant une finalité différente. L'exécuter à un seul endroit crée des angles morts ; l'exécuter partout de manière uniforme engendre des processus lents que les développeurs doivent contourner.

Étape du pipelineQue courirBudget de latenceInteret
Pré-engagement (local)Linters rapides uniquement (ESLint, Clippy, rustfmt)Sous 5 secondesRéglez les problèmes évidents avant qu'ils n'atteignent le dépôt
Demande de fusionAnalyse complète du code + SAST + analyse incrémentale SonarQubeMoins de 3 minutesFusion de blocs sur de nouveaux problèmes critiques
construction de la branche principaleAnalyse complète incluant la couverture, les doublons et la dette techniqueMoins de 10 minutesSuivre les tendances de qualité, mettre à jour les tableaux de bord
Programmé chaque soirAnalyses approfondies, audit des dépendances, contrôles de conformitéPas de budgetIdentifier les problèmes de construction lente et les risques liés à la chaîne d'approvisionnement

L'étape la plus importante est la demande de fusion.L'analyse exécutée lors d'un envoi vers la branche principale intervient après la décision de fusion. L'analyse exécutée lors d'une demande de fusion et qui ajoute des commentaires intégrés avec un contexte précis de fichier et de ligne intervient lorsque le développeur travaille encore sur le code et que le coût de correction est minimal.

L'exécution d'analyses lourdes avant chaque sauvegarde nuit à l'expérience de développement. Seuls les linters rapides, s'exécutant en moins de 5 secondes, ont leur place. Tout le reste relève de l'intégration continue.

Actions GitHub : Configuration de travail complète

GitHub Actions est la plateforme d'intégration continue la plus utilisée. Le flux de travail suivant exécute un pipeline de qualité en plusieurs étapes : vérification du formatage, analyse statique du code, compilation, analyse de sécurité SAST et validation par SonarCloud.

yaml

# .github/workflows/quality.yml
name: Code Quality

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main, develop]

jobs:
  # ── Layer 1: Fast checks (under 60 seconds) ─────────────────────────────
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          node-version: "20"
          cache: "npm"

      - run: npm ci

      - name: Lint (fail on warnings)
        run: npx eslint src/ --max-warnings 0

      - name: Format check
        run: npx prettier --check src/

      - name: TypeScript type check
        run: npx tsc --noEmit

  # ── Layer 2: Security SAST (Semgrep) ────────────────────────────────────
  sast:
    runs-on: ubuntu-latest
    needs: lint
    steps:
      - uses: actions/checkout@v4

      - name: Semgrep SAST scan
        uses: semgrep/semgrep-action@v1
        with:
          config: p/javascript p/nodejs p/owasp-top-ten
        env:
          SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }}

  # ── Layer 3: SonarCloud quality gate ────────────────────────────────────
  sonar:
    runs-on: ubuntu-latest
    needs: lint
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0  # full history required for blame data

      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          node-version: "20"
          cache: "npm"

      - run: npm ci

      - name: Run tests with coverage
        run: npm test -- --coverage --coverageReporters=lcov

      - name: SonarCloud scan
        uses: SonarSource/sonarcloud-github-action@master
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

propriétés

# sonar-project.properties
sonar.projectKey=my-org_my-project
sonar.organization=my-org
sonar.sources=src
sonar.tests=tests
sonar.javascript.lcov.reportPaths=coverage/lcov.info
sonar.coverage.exclusions=**/*.test.js,**/*.spec.js

Principales décisions de configuration dans ce flux de travail :

  • --max-warnings 0 Sur ESLint : tout avertissement est considéré comme un échec de compilation. Les équipes qui autorisent les avertissements les accumulent jusqu’à ce que plus personne ne les lise.
  • fetch-depth: 0 Lors du paiement : SonarCloud a besoin de l’historique Git complet pour attribuer la responsabilité des problèmes introduits et calculer correctement les métriques du nouveau code.
  • Semgrep s'exécute après l'analyse statique du code, en parallèle avec Sonar : l'analyse de sécurité et l'analyse de la qualité sont des préoccupations indépendantes ; leur exécution en parallèle réduit le temps total du processus.
  • Tests exécutés avec lcov Sortie de couverture : SonarCloud utilise ces données pour afficher la couverture par fichier et appliquer des seuils de couverture dans le contrôle qualité.

GitLab CI/CD : Pipeline de qualité avec portes de qualité

yaml

# .gitlab-ci.yml
stages:
  - lint
  - test
  - analyze
  - security

variables:
  SONAR_HOST_URL: "https://sonarcloud.io"

lint:
  stage: lint
  image: node:20
  cache:
    paths: [node_modules/]
  script:
    - npm ci
    - npx eslint src/ --max-warnings 0
    - npx prettier --check src/
    - npx tsc --noEmit
  rules:
    - if: $CI_MERGE_REQUEST_IID
    - if: $CI_COMMIT_BRANCH == "main"

test:
  stage: test
  image: node:20
  script:
    - npm ci
    - npm test -- --coverage --coverageReporters=lcov cobertura
  coverage: '/Lines\s*:\s*(\d+\.?\d*)%/'
  artifacts:
    reports:
      coverage_report:
        coverage_format: cobertura
        path: coverage/cobertura-coverage.xml

sonarcloud:
  stage: analyze
  image:
    name: sonarsource/sonar-scanner-cli:latest
    entrypoint: [""]
  variables:
    SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar"
    GIT_DEPTH: "0"
  cache:
    key: "${CI_JOB_NAME}"
    paths: [.sonar/cache]
  script:
    - sonar-scanner
  rules:
    - if: $CI_MERGE_REQUEST_IID
    - if: $CI_COMMIT_BRANCH == "main"

semgrep:
  stage: security
  image: returntocorp/semgrep:latest
  script:
    - semgrep scan --config=p/owasp-top-ten --config=p/javascript
      --sarif --output=semgrep.sarif src/
  artifacts:
    reports:
      sast: semgrep.sarif
  rules:
    - if: $CI_MERGE_REQUEST_IID
    - if: $CI_COMMIT_BRANCH == "main"

Le artifacts: reports: sast: Ce bloc intègre directement les résultats SARIF de Semgrep dans le tableau de bord de sécurité de GitLab, où les résultats apparaissent dans le rapport de sécurité de la demande de fusion plutôt que sous forme de journal CI brut.

Jenkins : Pipeline déclaratif avec SonarQube

groovy

// Jenkinsfile
pipeline {
    agent any

    tools {
        nodejs "NodeJS-20"
    }

    environment {
        SONAR_TOKEN = credentials('sonar-token')
    }

    stages {
        stage('Lint') {
            steps {
                sh 'npm ci'
                sh 'npx eslint src/ --max-warnings 0'
                sh 'npx tsc --noEmit'
            }
        }

        stage('Test') {
            steps {
                sh 'npm test -- --coverage --coverageReporters=lcov'
            }
            post {
                always {
                    publishHTML([
                        allowMissing: false,
                        reportDir: 'coverage/lcov-report',
                        reportFiles: 'index.html',
                        reportName: 'Coverage Report'
                    ])
                }
            }
        }

        stage('SonarQube Analysis') {
            steps {
                withSonarQubeEnv('SonarQube') {
                    sh '''
                        npx sonar-scanner \
                          -Dsonar.projectKey=my-project \
                          -Dsonar.sources=src \
                          -Dsonar.javascript.lcov.reportPaths=coverage/lcov.info
                    '''
                }
            }
        }

        stage('Quality Gate') {
            steps {
                timeout(time: 5, unit: 'MINUTES') {
                    waitForQualityGate abortPipeline: true
                }
            }
        }
    }

    post {
        failure {
            emailext(
                subject: "Quality Gate FAILED: ${env.JOB_NAME} #${env.BUILD_NUMBER}",
                body: "Build failed quality gate. Review: ${env.BUILD_URL}",
                to: "${env.CHANGE_AUTHOR_EMAIL}"
            )
        }
    }
}

waitForQualityGate abortPipeline: true Cette ligne est cruciale. Elle interroge SonarQube jusqu'à la fin de l'analyse et interrompt la compilation si le critère de qualité n'est pas atteint. Sans elle, le pipeline se termine alors que l'analyse est toujours en cours et le résultat du critère de qualité n'est jamais appliqué.

Configurer des critères de qualité que les équipes respectent réellement.

Un contrôle qualité qui échoue à chaque validation en raison de seuils trop restrictifs est désactivé. À l'inverse, un contrôle qui ne présente jamais d'échec, car ses seuils sont trop permissifs, est inutile. L'objectif est de disposer d'un contrôle adapté au profil de risque réel du projet.

Configuration initiale recommandée pour un nouveau contrôle qualité SonarQube :

MétriqueÉtatSeuil de porte
Nouveaux bugsSupérieure à0
Nouvelles vulnérabilitésSupérieure à0
Nouveaux points d'accès à la sécurité examinésMoins que100 %
Nouvelle couverture de codeMoins que80 %
Nouvelles lignes dupliquéesSupérieure à3%
Nouvelles odeurs de codeSupérieure à10

Appliquez ces seuils à nouveau code uniquement (La période « nouveau code » dans SonarQube). N'appliquez pas ces méthodes à l'intégralité du code d'un projet existant : l'échec systématique des compilations dû à la dette technique accumulée sur cinq ans pousse les équipes à désactiver complètement le contrôle. L'approche « nouveau code » permet de limiter les dégâts pendant que la dette existante est traitée séparément.

Augmenter les seuils au fil du temps. Commencez par des seuils prudents, puis ajustez-les chaque trimestre à mesure que l'équipe résorbe son arriéré. Un seuil validé aujourd'hui avec une couverture de 75 % peut être porté à 80 % une fois que le niveau de référence est nettement supérieur. Un ajustement progressif est plus durable que la recherche de la perfection immédiate.

Gestion des performances d'analyse statique dans les grands ensembles de code

La raison la plus fréquente pour laquelle les équipes désactivent ou contournent l'analyse statique dans l'intégration continue est qu'elle ralentit considérablement les pipelines. Un contrôle qualité de 15 minutes à chaque modification d'une branche de fonctionnalité perturbe le flux de développement. Plusieurs stratégies permettent d'accélérer l'analyse :

Analyse incrémentale (nouveau code uniquement). SonarQube et la plupart des outils d'analyse statique d'entreprise permettent d'analyser uniquement les fichiers modifiés dans une demande d'extraction, et non l'intégralité du code source. Configurer sonar.pullrequest.base, sonar.pullrequest.branch et sonar.pullrequest.key Paramètres permettant l'analyse incrémentale spécifique aux demandes de tirage. L'analyse complète est toujours effectuée lors de la fusion dans la branche principale ; l'analyse des demandes de tirage s'effectue en moins de 2 minutes sur la plupart des bases de code.

Mise en cache. La partie la plus coûteuse de nombreuses analyses statiques consiste à télécharger l'outil et ses définitions de règles. Il est donc important de mettre en cache le fichier binaire du scanner, la base de données de règles et toutes les dépendances résolues entre les exécutions.

yaml

# GitHub Actions: cache SonarCloud scanner
- name: Cache SonarCloud packages
  uses: actions/cache@v4
  with:
    path: ~/.sonar/cache
    key: ${{ runner.os }}-sonar
    restore-keys: ${{ runner.os }}-sonar

Parallélisme. L'analyse statique du code, l'analyse de sécurité et le contrôle qualité sont des opérations indépendantes. Il est préférable de les exécuter en parallèle plutôt que séquentiellement. La durée totale du pipeline est déterminée par la tâche la plus lente, et non par la somme des durées de toutes les tâches.

Activation sélective des outils. Il n'est pas nécessaire d'exécuter tous les outils sur chaque branche. Les analyses de sécurité complètes et les contrôles de conformité peuvent être exécutés sur les demandes d'extraction et la branche principale, tandis que les branches de pré-fusion n'exécutent que des analyses rapides. Utilisez les filtres de branche dans la configuration d'intégration continue pour appliquer différents profils d'analyse.

Analyse statique dans les pipelines axés sur la sécurité : SAST et analyse des dépendances

Les pipelines axés sur la sécurité ajoutent deux couches au-delà de l'analyse de qualité standard : le SAST (Static Application Security Testing) pour les vulnérabilités du code applicatif et l'analyse des dépendances pour les CVE connues dans les bibliothèques tierces.

Outils SAST Semgrep, CodeQL, Snyk Code et Checkmarx analysent la manière dont les données non fiables circulent dans le code applicatif pour atteindre les opérations sensibles. Ils détectent les injections SQL, les attaques XSS, les injections de commandes, les désérialisations non sécurisées et les identifiants codés en dur, autant de vulnérabilités que les outils d'analyse statique de données classiques ne peuvent pas repérer.

yaml

# GitHub Actions: CodeQL analysis for deep vulnerability detection
- name: Initialize CodeQL
  uses: github/codeql-action/init@v3
  with:
    languages: javascript-typescript

- name: Perform CodeQL Analysis
  uses: github/codeql-action/analyze@v3
  with:
    category: "/language:javascript-typescript"

Analyse des dépendances chèques package.json, pom.xml, requirements.txt, et des fichiers manifestes équivalents contre les bases de données de vulnérabilités :

yaml

# Dependency audit in the pipeline
- name: Dependency audit
  run: |
    npm audit --audit-level=high
    # Fail if high or critical vulnerabilities are found

Le modèle de sécurité multicouche applique une analyse SAST rapide basée sur des modèles (Semgrep) à chaque demande de tirage pour un retour immédiat aux développeurs, et une analyse SAST sémantique approfondie (CodeQL) planifiée pour une couverture exhaustive. L'analyse des dépendances est exécutée à chaque compilation, car de nouvelles vulnérabilités CVE sont publiées quotidiennement.

Erreurs d'intégration courantes et comment les éviter

Exécution de l'analyse uniquement sur la branche principale. L'intérêt de l'analyse statique réside dans la détection des problèmes avant la fusion, et non après. Une analyse exécutée uniquement après la fusion sert de rapport, et non de contrôle.

Mettre en place des contrôles de qualité pour signaler plutôt que pour signaler un échec. Un avertissement qui ne bloque pas le processus est une notification que les développeurs apprennent à ignorer. Des mécanismes qui ne dysfonctionnent pas ne favorisent pas une culture de la qualité.

Ne pas exclure les fichiers de test des seuils de couverture. Les tests effectués sur du code testant d'autres tests produisent des taux de couverture artificiellement élevés. Pour obtenir des mesures précises de la couverture du code en production, il est nécessaire d'exclure les répertoires de tests des calculs de couverture.

Ignorer le retard d'analyse des bases de code existantes. Lancer SonarQube pour la première fois sur un code source existant d'un million de lignes et se retrouver avec 40 000 problèmes est démotivant et contre-productif. Privilégiez l'approche de référence pour le nouveau code : définissez une date de début pour le « nouveau code », appliquez les contrôles uniquement au code écrit après cette date et traitez le backlog de problèmes existant comme un programme distinct de réduction de la dette technique.

Ne pas câbler les résultats se retrouve dans les commentaires des demandes de fusion. Les résultats d'analyse publiés sur un tableau de bord distinct que les développeurs doivent consulter sont ignorés. Les résultats d'analyse publiés sous forme de commentaires directement sur les lignes concernées, dans l'interface de révision des demandes d'extraction, sont pris en compte. Configurer sonar.pullrequest.* Paramètres pour l'intégration GitHub, GitLab ou Bitbucket afin que les résultats apparaissent là où la revue de code a lieu.

Comment SMART TS XL S'intègre aux pipelines CI/CD

La plupart des outils d'analyse statique des pipelines CI/CD analysent un langage à la fois. ESLint analyse JavaScript. SonarQube analyse Java, Python, JavaScript et C#. Aucun d'entre eux n'analyse COBOL, JCL, RPG, ni les dépendances interlangages qui relient un programme batch mainframe au microservice Java qui consomme sa sortie, lequel est ensuite connecté à l'interface JavaScript qui l'affiche.

SMART TS XL s'intègre aux pipelines CI/CD en tant que couche d'analyse statique multilingue couvrant simultanément tous les langages de l'environnement d'entreprise. Lorsqu'un service Java est modifié, SMART TS XL's analyse d’impact Avant le déploiement d'une modification, le système analyse le graphe de dépendances afin d'identifier les programmes COBOL, les schémas de base de données et les services en aval concernés. Lorsqu'un copybook COBOL est modifié, il identifie tous les programmes de l'ensemble du portefeuille d'applications qui incluent ce copybook et qui nécessitent une validation.

Cette conscience des dépendances interlangagières est la capacité qui rend SMART TS XLL'intégration CI/CD de SonarQube est différente de l'ajout d'un langage supplémentaire. Il ne s'agit pas seulement d'analyser le code du fichier modifié, mais aussi de comprendre l'impact de cette modification sur le reste du système. C'est l'analyse architecturale qui détermine la véritable portée d'une modification avant sa mise en œuvre.

Pour les équipes de développement d'entreprise opérant sur des piles technologiques anciennes et modernes, SMART TS XL's Intégration DevOps Cette fonctionnalité intègre l'analyse structurelle au flux de travail de revue du pipeline, offrant ainsi une visibilité architecturale que les outils spécifiques à un langage ne peuvent fournir. Il en résulte des contrôles qualité qui appliquent les normes non seulement au sein d'un langage, mais à l'échelle du système entier, garantissant qu'une modification apportée à un composant n'entraîne pas de défaillances inattendues dans les composants qui en dépendent.

L'analyse statique en tant que citoyen permanent du pipeline

Les équipes qui maîtrisent l'analyse statique l'intègrent à leur processus de test de la même manière : non pas comme une simple étape à franchir, mais comme une pratique continue, intégrée à chaque commit. L'analyse est exécutée à chaque pull request. Les résultats des contrôles qualité sont disponibles en même temps que les revues de code. Les seuils d'exigence sont affinés à mesure que le code s'améliore. De nouvelles catégories d'analyse sont ajoutées au fur et à mesure que l'équipe gagne en maturité en matière de sécurité et de qualité.

Les modèles de configuration de pipeline présentés dans cet article ne sont que des points de départ. Les outils, seuils et conditions de validation spécifiques doivent être adaptés à la pile technologique du projet, au profil de risque et à la maturité de l'équipe. Le principe, en revanche, doit rester constant : une analyse qui ne bloque pas les fusions ne modifie pas le comportement, or c'est précisément le comportement que les programmes d'assurance qualité du code cherchent à changer.