Jak integruji analýzu statického kódu do kanálů CI/CD?

Jak integruji analýzu statického kódu do kanálů CI/CD?

IN-COM 11. června, 2026

Každý řádek kódu, který se dostane do produkčního prostředí, byl commitován někým, kdo věřil, že je správný. Statická analýza kódu je automatizovaný systém, který kontroluje, zda je toto přesvědčení správné, nikoli spuštěním kódu, ale čtením jeho struktury, sledováním jeho datových toků a porovnáváním se známými vzorci zranitelností, chyb a porušení kvality. Otázkou není, zda kód spustit, ale kde v produktovém procesu ho spustit, který nástroj spustit, jaké prahové hodnoty vynutit a jak udržet zpětnou vazbu dostatečně rychlou, aby na ni vývojáři skutečně reagovali, a ne ji ignorovali.

Rozdíl mezi statickou analýzou jako aktivitou s checkboxem a statickou analýzou jako skutečnou kvalitativní bránou spočívá v konfiguraci. Skener, který běží a vytváří zprávu, kterou nikdo nečte, je divadlo. Kvalitativní brána, která selže při sestavení, když se objeví nové kritické zranitelnosti, zablokuje sloučení, když pokrytí klesne pod prahovou hodnotu, a zobrazí přesnou zpětnou vazbu k souborům a řádkům v rozhraní pro kontrolu pull requestů, je systém, který mění chování v okamžiku, kdy jsou učiněna rozhodnutí.

Kde v kanálu spustit statickou analýzu

Statická analýza by měla probíhat na více místech, z nichž každé slouží jinému účelu. Její spuštění pouze na jednom místě vytváří slepá místa; její spuštění všude rovnoměrně vytváří pomalé kanály, které vývojáři obcházejí.

Fáze potrubíCo běžetLatenční rozpočetÚčel
Předběžné potvrzení (lokální)Pouze rychlé linters (ESLint, Clippy, rustfmt)Do 5 sekundZastavte zjevné problémy dříve, než se dostanou do repozitáře
Žádost o natažení / žádost o sloučeníKompletní linting + SAST + inkrementální skenování SonarQubeMéně než 3 minutySloučení bloků u nových kritických problémů
Sestavení hlavní pobočkyKompletní analýza včetně pokrytí, duplikace, technického dluhuMéně než 10 minutySledování trendů kvality, aktualizace dashboardů
Naplánováno každou nocHloubkové skenování, audit závislostí, kontroly shody s předpisyŽádný rozpočetZachycení problémů s pomalou výstavbou a rizik dodavatelského řetězce

Nejcennější fází je pull request.Analýza, která běží na push to main, dorazí až po rozhodnutí o sloučení. Analýza, která běží na pull requestu a vkládá inline komentáře s přesným kontextem souboru a řádku, dorazí, když je vývojář stále v kódu a náklady na opravu jsou nejnižší.

Spouštění náročné analýzy před každým uložením ničí zkušenosti vývojářů. Rychlé lintery, které se dokončí za méně než 5 sekund, patří tam. Všechno ostatní patří do CI.

Akce GitHubu: Dokončení funkční konfigurace

GitHub Actions je nejpoužívanější platforma pro CI. Následující pracovní postup spouští vrstvený kanál pro kontrolu kvality: kontrola formátování, linting, sestavení, bezpečnostní kontrola SAST a kontrola kvality 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 }}

vlastnosti

# 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

Klíčová konfigurační rozhodnutí v tomto pracovním postupu:

  • --max-warnings 0 Na ESLintu: jakékoli varování je selhání sestavení. Týmy, které povolují varování, je hromadí, dokud si je nikdo nepřečte.
  • fetch-depth: 0 při platbě: SonarCloud potřebuje kompletní historii gitu, aby mohl správně přiřadit vinu zavedeným problémům a vypočítat metriky nového kódu.
  • Semgrep běží po lint paralelně se Sonarem: bezpečnost a skenování kvality jsou nezávislé záležitosti; jejich paralelní spuštění zkracuje celkový čas zpracování.
  • Testy probíhají s lcov výstup pokrytí: SonarCloud toto načte, aby zobrazil pokrytí pro každý soubor a vynutil prahové hodnoty pokrytí v bráně kvality.

GitLab CI/CD: Procesor kvality s branami kvality

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"

Jedno artifacts: reports: sast: Blok integruje výstup SARIF ze Semgrepu přímo do bezpečnostního panelu GitLabu, kde se zjištění zobrazují v bezpečnostní zprávě o merge requestu, nikoli jako nezpracovaný výstup CI logu.

Jenkins: Deklarativní kanál se SonarQube

prima

// 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 je kritický řádek. Dotazuje SonarQube, dokud není analýza dokončena, a sestavení selže, pokud není splněna kritéria kvality. Bez toho se pipeline dokončí, zatímco analýza stále běží, a výsledek kritéria kvality se nikdy nevymáhá.

Konfigurace bran kvality, které týmy skutečně respektují

Brána kvality, která selže při každém potvrzení, protože prahové hodnoty jsou nastaveny příliš agresivně, se deaktivuje. Brána, která nikdy neselže, protože prahové hodnoty jsou příliš tolerantní, neposkytuje žádnou hodnotu. Cílem je brána kalibrovaná na skutečný rizikový profil projektu.

Doporučená počáteční konfigurace pro novou bránu kvality SonarQube:

metrickýStavPráh
Nové chybyVětší než0
Nové zranitelnostiVětší než0
Nová bezpečnostní hotspoty zkontroloványMéně než100%
Nové pokrytí kóduMéně než80%
Nové duplicitní řádkyVětší než3%
Nový kód voníVětší než10

Použijte tyto prahové hodnoty na pouze nový kód (období „nového kódu“ v SonarQube). Nepoužívejte je na celou kódovou základnu staršího projektu, protože selhání každého sestavení kvůli technickému dluhu nahromaděnému za pět let způsobí, že týmy bránu zcela deaktivují. Přístup s novým kódem vám umožňuje zastavit krvácení, zatímco stávající dluh se řeší samostatně.

Prahové hodnoty rohatky v průběhu času. Začněte s konzervativními prahovými hodnotami a poté je každé čtvrtletí zpřísňujte, jakmile tým vyřídí nahromaděné zásoby. Hodnota, která dnes projde s pokrytím 75 %, může být aktualizována na 80 %, jakmile je základní hodnota pohodlně nad touto hranicí. Postupné zpřísňování je udržitelnější než skok k dokonalosti.

Zvládání výkonu statické analýzy ve velkých kódových databázích

Nejčastějším důvodem, proč týmy v CI deaktivují nebo obcházejí statickou analýzu, je to, že příliš zpomaluje vývojové procesy. Patnáctiminutová kontrola kvality při každém odeslání do větve funkcí brzdí tok vývojářů. Několik strategií udržuje analýzu rychlou:

Inkrementální analýza (pouze nový kód). SonarQube a většina podnikových nástrojů pro statickou analýzu podporují analýzu pouze změněných souborů v žádosti o změnu, nikoli celé kódové základny. sonar.pullrequest.base, sonar.pullrequest.branch, a sonar.pullrequest.key parametry pro povolení inkrementálního skenování specifického pro PR. Úplná analýza stále běží při sloučení do hlavního složky; skenování PR probíhá na většině kódových základen za méně než 2 minuty.

Ukládání do mezipaměti. Nejdražší částí mnoha běhů statické analýzy je stažení nástroje a jeho definic pravidel. Mezi jednotlivými běhy ukládejte do mezipaměti binární soubor skeneru, databázi pravidel a všechny vyřešené závislosti:

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

Rovnoběžnost. Linting, bezpečnostní skenování a analýza Quality Gate jsou nezávislé záležitosti. Spouštějte je paralelně, nikoli postupně. Celkový čas zpracování v kanálu je určen nejpomalejší úlohou, nikoli součtem všech úloh.

Selektivní aktivace nástroje. Ne každý nástroj musí běžet na každé větvi. Úplné bezpečnostní skenování a kontroly shody s předpisy lze spustit na žádostech o změnu nastavení a hlavních větvích, zatímco větve před sloučením běží pouze na rychlých linterech. Pro použití různých analytických profilů použijte filtry větví v konfiguraci CI.

Statická analýza v bezpečnostních kanálech: SAST a skenování závislostí

Bezpečnostně zaměřené kanály přidávají nad rámec standardní analýzy kvality dvě vrstvy: SAST (Static Application Security Testing) pro zranitelnosti kódu aplikací a skenování závislostí pro známé CVE v knihovnách třetích stran.

Nástroje SAST (Semgrep, CodeQL, Snyk Code, Checkmarx) analyzují, jak nedůvěryhodná data proudí aplikačním kódem a dosahují citlivých operací. Nacházejí SQL injection, XSS, injection příkazů, nezabezpečenou deserializaci a pevně zakódované přihlašovací údaje, které standardní lintery nedokážou detekovat.

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"

Skenování závislostí Kontroly package.json, pom.xml, requirements.txta ekvivalentní soubory manifestu proti databázím zranitelností:

yaml

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

Vrstvený model zabezpečení umisťuje na každý PR rychlý SAST založený na vzorcích (Semgrep) pro okamžitou zpětnou vazbu od vývojářů a hluboký sémantický SAST (CodeQL) podle plánu pro důkladné pokrytí. Skenování závislostí probíhá u každého sestavení, protože nové CVE jsou publikovány denně.

Časté chyby v integraci a jak se jim vyhnout

Spuštění analýzy pouze na hlavní větvi. Hodnota statické analýzy spočívá v zachycení problémů před jejich sloučením, nikoli po něm. Analýza, která se spouští až po sloučení, slouží jako report, nikoli jako brána.

Nastavení kvalitativních bran pro varování, nikoli pro selhání. Varování, které neblokuje proces, je oznámení, které se vývojáři naučí ignorovat. Brány, které neselžou, nebudují kulturu kvality.

Nevylučování testovacích souborů z prahových hodnot pokrytí. Testování kódu testováním jiného testovacího kódu vytváří nadsazená čísla pokrytí. Vyloučte testovací adresáře z výpočtů pokrytí, abyste získali přesná měření pokrytí produkčního kódu.

Ignorování nevyřízených analýz u starších kódových bází. Zapnutí SonarQube poprvé na milionu řádků staré kódové základny a získání 40 000 problémů je demotivující a kontraproduktivní. Použijte přístup základní úrovně nového kódu: definujte datum zahájení „nového kódu“, aplikujte brány pouze na kód napsaný po tomto datu a zacházejte se stávajícím nevyřízeným seznamem problémů jako se samostatným programem na snižování technického dluhu.

Nezapojování výsledků do komentářů v žádostech o změnu obsahu (pull request) Výsledky analýzy zveřejněné na samostatném dashboardu, který musí vývojáři navštívit, jsou ignorovány. Řeší se výsledky analýzy zveřejněné jako vložené komentáře na konkrétních řádcích, které způsobily problémy, v rozhraní pro kontrolu žádostí o změny. Konfigurace sonar.pullrequest.* parametry pro integraci s GitHubem, GitLabem nebo Bitbucketem, aby se nálezy zobrazovaly tam, kde probíhá kontrola kódu.

Jak SMART TS XL Integruje se s CI/CD Pipelines

Většina nástrojů pro statickou analýzu v CI/CD pipelinech vidí vždy jen jeden jazyk. ESLint vidí JavaScript. SonarQube vidí Javu, Python, JavaScript a C#. Žádný z nich nevidí COBOL, JCL, RPG ani závislosti mezi jazyky, které propojují dávkový program na mainframe s mikroslužbou Java, která spotřebovává její výstup a která se připojuje k frontendu JavaScriptu, který jej zobrazuje.

SMART TS XL integruje se do CI/CD pipelines jako vrstva statické analýzy napříč jazyky, která pokrývá všechny jazyky v podnikovém prostředí současně. Když je služba Java upravena, SMART TS XLJe analýza dopadu Sleduje graf závislostí, aby identifikoval, které programy v COBOLu, schémata databází a následné služby jsou touto změnou ovlivněny, a to ještě před jejím nasazením. Při úpravě COBOL copybooku identifikuje všechny programy v celém portfoliu aplikací, které daný copybook obsahují a které by vyžadovaly ověření.

Toto uvědomění si mezijazyčných závislostí je schopností, která umožňuje SMART TS XLIntegrace CI/CD se liší od přidání dalšího jazyka do SonarQube. Nejde jen o analýzu kódu v změněném souboru. Jde o pochopení toho, co dalšího v systému tato změna ovlivní, což je architektonická analýza, která určuje skutečný rozsah změny před jejím provedením.

Pro týmy podnikového vývoje pracující napříč staršími i moderními platformami, SMART TS XLJe Integrace DevOps Tato funkce integruje tuto strukturální analýzu do pracovního postupu kontroly pipeline a poskytuje architektonický přehled, který jazykově specifické nástroje nemohou poskytnout. Výsledkem jsou kritéria kvality, která vynucují standardy nejen v rámci jazykových hranic, ale v celém systému, a zajišťují, že změna v jakékoli komponentě nezpůsobí neočekávané selhání v komponentách, které jsou na ní závislé.

Statická analýza jako stálý občan potrubí

Týmy, které zvládnou statickou analýzu správně, k ní přistupují stejně jako k testování: ne jako k fázi, kterou je třeba projít, ale jako k průběžné praxi zabudované do každého commitu. Analýza běží u každého pull requestu. Výsledky Quality Gate se zobrazují v rámci kontroly kódu. Prahové hodnoty se zpřísňují s tím, jak se kódová základna zlepšuje. S rostoucí vyspělostí týmu v oblasti zabezpečení a kvality se přidávají nové kategorie analýzy.

Šablony konfigurace kanálu v tomto článku slouží jako výchozí body. Konkrétní nástroje, prahové hodnoty a podmínky brán by měly být kalibrovány podle jazykového stacku projektu, rizikového profilu a vyspělosti týmu. Co by se nemělo měnit, je princip: analýza, která neomezuje slučování, nemění chování a chování je to, co se programy pro kvalitu kódu snaží změnit.