Aller au contenu

Qodana Feuille de chaleur

Copier toutes les commandes Générer PDF

Aperçu général

Qodana est la plateforme de qualité de code de JetBrains qui apporte les inspections de code intelligentes des IDE de JetBrains à votre pipeline CI/CD. Il fournit une analyse statique complète, une détection de vulnérabilité de sécurité et des mesures de qualité de code pour plusieurs langages de programmation avec une intégration profonde dans les flux de développement.

C'est pas vrai. Note: Niveau libre disponible avec limitations. Les régimes payés commencent à 0,50 $ par 1000 lignes de code par mois.

Commencer

Méthodes d'installation

# Docker (Recommended)
docker pull jetbrains/qodana-jvm
docker pull jetbrains/qodana-js
docker pull jetbrains/qodana-python
docker pull jetbrains/qodana-php
docker pull jetbrains/qodana-dotnet

# CLI Installation
# Linux/macOS
curl -fsSL https://jb.gg/qodana-cli/install | bash

# Windows (PowerShell)
iex "& { $(irm https://jb.gg/qodana-cli/install-ps1) }"

# Homebrew (macOS)
brew install jetbrains/utils/qodana

# Snap (Linux)
sudo snap install qodana

Démarrer rapidement

# Initialize Qodana in project
qodana init

# Run analysis with Docker
docker run --rm -it \
  -v $(pwd):/data/project/ \
  -v $(pwd)/qodana-results:/data/results/ \
  jetbrains/qodana-jvm

# Run with CLI
qodana scan --project-dir . --results-dir ./qodana-results
```_

### Configuration du projet
```yaml
# qodana.yaml configuration file
version: "1.0"
profile:
  name: qodana.recommended
include:
  - name: All
exclude:
  - name: "Unused import"
  - name: "Spelling"
projectJDK: "11"
bootstrap: |
  set -eu
  echo "Bootstrap script execution"
  ./gradlew build -x test
```_

## Appui linguistique

### JVM Langues (Java, Kotlin, Scala)
```bash
# Qodana JVM Linter
docker run --rm -it \
  -v $(pwd):/data/project/ \
  -v $(pwd)/qodana-results:/data/results/ \
  jetbrains/qodana-jvm

# Supported build tools:
# - Maven
# - Gradle
# - SBT
# - Ant

# Java-specific inspections:
# - Code style violations
# - Null pointer analysis
# - Resource leak detection
# - Performance issues
# - Security vulnerabilities

JavaScript/TypeScript

# Qodana JS Linter
docker run --rm -it \
  -v $(pwd):/data/project/ \
  -v $(pwd)/qodana-results:/data/results/ \
  jetbrains/qodana-js

# Supported frameworks:
# - React
# - Vue.js
# - Angular
# - Node.js
# - Express

# JS/TS inspections:
# - ESLint integration
# - TypeScript compiler checks
# - React-specific issues
# - Async/await problems
# - Performance optimizations

Python

# Qodana Python Linter
docker run --rm -it \
  -v $(pwd):/data/project/ \
  -v $(pwd)/qodana-results:/data/results/ \
  jetbrains/qodana-python

# Python features:
# - PEP 8 compliance
# - Type checking with mypy
# - Security vulnerability detection
# - Code complexity analysis
# - Import optimization

PHP

# Qodana PHP Linter
docker run --rm -it \
  -v $(pwd):/data/project/ \
  -v $(pwd)/qodana-results:/data/results/ \
  jetbrains/qodana-php

# PHP inspections:
# - PSR compliance
# - Security vulnerabilities
# - Performance issues
# - Type safety
# - Framework-specific checks

.NET (C#, VB.NET, F#)

# Qodana .NET Linter
docker run --rm -it \
  -v $(pwd):/data/project/ \
  -v $(pwd)/qodana-results:/data/results/ \
  jetbrains/qodana-dotnet

# .NET features:
# - Roslyn analyzer integration
# - Security rule checks
# - Performance optimizations
# - Code style enforcement
# - Framework compatibility

Configuration

Configuration de base

# qodana.yaml - Basic setup
version: "1.0"
profile:
  name: qodana.recommended
include:
  - name: All
exclude:
  - name: "Unused import"
  - name: "Spelling"
  - name: "Typo"

Configuration avancée

# qodana.yaml - Advanced setup
version: "1.0"
profile:
  name: qodana.recommended
  path: .qodana/profiles/custom.xml
include:
  - name: "Code style issues"
  - name: "Probable bugs"
  - name: "Performance"
exclude:
  - name: "Spelling"
  - name: "Unused import"
  - path: "src/test/**"
  - path: "**/*.generated.js"
projectJDK: "11"
bootstrap: |
  set -eu
  echo "Installing dependencies..."
  npm install
  ./gradlew build -x test
failThreshold: 0

Personnalisation du profil

<!-- .qodana/profiles/custom.xml -->
<profile version="1.0">
  <option name="myName" value="Custom Profile" />
  <inspection_tool class="UnusedDeclaration" enabled="true" level="WARNING" enabled_by_default="true" />
  <inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="true" />
  <inspection_tool class="JSUnusedLocalSymbols" enabled="true" level="WARNING" enabled_by_default="true" />
</profile>

Variables d'environnement

# Common environment variables
export QODANA_TOKEN="your-token-here"
export QODANA_PROJECT_ID="project-id"
export QODANA_BRANCH="main"
export QODANA_REVISION="HEAD"

# Docker environment variables
docker run --rm -it \
  -e QODANA_TOKEN=$QODANA_TOKEN \
  -e QODANA_PROJECT_ID=$QODANA_PROJECT_ID \
  -v $(pwd):/data/project/ \
  -v $(pwd)/qodana-results:/data/results/ \
  jetbrains/qodana-jvm

CLI Commandes

Commandes de base

# Initialize project
qodana init

# Scan project
qodana scan

# Scan with specific linter
qodana scan --linter jetbrains/qodana-jvm

# Scan with custom config
qodana scan --config ./custom-qodana.yaml

# Show scan results
qodana show

# View help
qodana --help
qodana scan --help

CLI avancé Utilisation

# Scan with custom parameters
qodana scan \
  --project-dir /path/to/project \
  --results-dir /path/to/results \
  --cache-dir /path/to/cache \
  --linter jetbrains/qodana-jvm \
  --config qodana.yaml \
  --property=idea.headless.enable.statistics=false

# Scan specific files/directories
qodana scan --include-paths "src/main/**,lib/**"
qodana scan --exclude-paths "src/test/**,**/*.generated.*"

# Set fail threshold
qodana scan --fail-threshold 10

# Generate SARIF report
qodana scan --sarif-report results.sarif

# Upload results to Qodana Cloud
qodana scan --upload-result

Gestion des résultats

# View results in browser
qodana show --port 8080

# Export results
qodana export --format json --output results.json
qodana export --format sarif --output results.sarif

# Compare results between branches
qodana diff --base main --target feature-branch

# Generate baseline
qodana scan --baseline qodana.sarif.json

Intégration CI/CD

Actions GitHub

# .github/workflows/qodana.yml
name: Qodana
on:
  workflow_dispatch:
  pull_request:
  push:
    branches:
      - main

jobs:
  qodana:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write
      checks: write
    steps:
      - uses: actions/checkout@v3
        with:
          ref: ${{ github.event.pull_request.head.sha }}
          fetch-depth: 0

      - name: 'Qodana Scan'
        uses: JetBrains/qodana-action@v2023.2
        with:
          args: --fail-threshold,0
        env:
          QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}

      - name: Upload SARIF file
        uses: github/codeql-action/upload-sarif@v2
        with:
          sarif_file: ${{ runner.temp }}/qodana/results/qodana.sarif.json

GitLab CI

# .gitlab-ci.yml
qodana:
  stage: test
  image: jetbrains/qodana-jvm:latest
  script:
    - qodana --results-dir $CI_PROJECT_DIR/qodana-results
  artifacts:
    reports:
      codequality: qodana-results/qodana.json
    paths:
      - qodana-results/
    expire_in: 1 week
  only:
    - merge_requests
    - main

Jenkins Pipeline

pipeline {
    agent any

    stages {
        stage('Checkout') {
            steps {
                checkout scm
            }
        }

        stage('Qodana Analysis') {
            steps {
                script {
                    docker.image('jetbrains/qodana-jvm:latest').inside {
                        sh '''
                            qodana --results-dir ./qodana-results \
                                   --fail-threshold 0 \
                                   --sarif-report qodana.sarif
                        '''
                    }
                }
            }
            post {
                always {
                    publishHTML([
                        allowMissing: false,
                        alwaysLinkToLastBuild: true,
                        keepAll: true,
                        reportDir: 'qodana-results',
                        reportFiles: 'report.html',
                        reportName: 'Qodana Report'
                    ])

                    recordIssues(
                        enabledForFailure: true,
                        tools: [sarif(pattern: 'qodana.sarif')]
                    )
                }
            }
        }
    }
}

Azure DevOps

# azure-pipelines.yml
trigger:
- main

pool:
  vmImage: 'ubuntu-latest'

steps:
- task: Docker@2
  displayName: 'Run Qodana Analysis'
  inputs:
    command: 'run'
    arguments: >
      --rm
      -v $(Build.SourcesDirectory):/data/project/
      -v $(Build.ArtifactStagingDirectory)/qodana-results:/data/results/
      jetbrains/qodana-jvm

- task: PublishBuildArtifacts@1
  displayName: 'Publish Qodana Results'
  inputs:
    pathToPublish: '$(Build.ArtifactStagingDirectory)/qodana-results'
    artifactName: 'qodana-results'

Portails et seuils de qualité

Configuration du seuil de défaillance

# Set fail threshold (number of problems)
qodana scan --fail-threshold 10

# Fail on any critical issues
qodana scan --fail-threshold 0 --severity critical

# Fail on new issues only
qodana scan --baseline qodana-baseline.sarif.json --fail-threshold 0

Profils des portes de qualité

# qodana.yaml with quality gates
version: "1.0"
profile:
  name: qodana.recommended
failThreshold: 5
include:
  - name: "Critical"
  - name: "High"
exclude:
  - name: "Low"
  - name: "Informational"

Règles de qualité personnalisées

<!-- Custom inspection profile -->
<profile version="1.0">
  <option name="myName" value="Strict Quality Gate" />

  <!-- Critical issues that should fail the build -->
  <inspection_tool class="NullPointerException" enabled="true" level="ERROR" />
  <inspection_tool class="SqlInjection" enabled="true" level="ERROR" />
  <inspection_tool class="XssVulnerability" enabled="true" level="ERROR" />

  <!-- High priority issues -->
  <inspection_tool class="UnusedDeclaration" enabled="true" level="WARNING" />
  <inspection_tool class="DuplicatedCode" enabled="true" level="WARNING" />

  <!-- Disabled for CI -->
  <inspection_tool class="SpellCheckingInspection" enabled="false" />
  <inspection_tool class="TodoComment" enabled="false" />
</profile>

Analyse de la sécurité

Détection de vulnérabilité à la sécurité

# Enable security inspections
qodana scan --include "Security"

# Focus on critical security issues
qodana scan \
  --include "SQL injection" \
  --include "XSS" \
  --include "Path traversal" \
  --include "Hardcoded credentials"

Problèmes de sécurité communs détectés

// SQL Injection Detection
// ❌ Vulnerable code
String query = "SELECT * FROM users WHERE id = " + userId;
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(query);

// ✅ Fixed code
String query = "SELECT * FROM users WHERE id = ?";
PreparedStatement stmt = connection.prepareStatement(query);
stmt.setString(1, userId);
ResultSet rs = stmt.executeQuery();

// Hardcoded Credentials Detection
// ❌ Vulnerable code
String password = "admin123";
String apiKey = "sk-1234567890abcdef";

// ✅ Fixed code
String password = System.getenv("DB_PASSWORD");
String apiKey = System.getenv("API_KEY");

Niveau de sécurité

# Create security baseline
qodana scan --include "Security" --baseline security-baseline.sarif.json

# Check only new security issues
qodana scan --baseline security-baseline.sarif.json --include "Security"

Analyse des résultats

Inspections de performance

# Focus on performance issues
qodana scan --include "Performance"

# Common performance issues detected:
# - Inefficient string concatenation
# - Resource leaks
# - Unnecessary object creation
# - Inefficient collections usage
# - Database query optimization

Exemples de performance

// String Concatenation Performance
// ❌ Inefficient
String result = "";
for (String item : items) {
    result += item + ", ";
}

// ✅ Efficient
StringBuilder sb = new StringBuilder();
for (String item : items) {
    sb.append(item).append(", ");
}
String result = sb.toString();

// Resource Leak Detection
// ❌ Resource leak
FileInputStream fis = new FileInputStream("file.txt");
// Missing close() call

// ✅ Proper resource management
try (FileInputStream fis = new FileInputStream("file.txt")) {
    // Use the stream
} // Automatically closed

Statistiques de qualité du code

Analyse de complexité

# Analyze code complexity
qodana scan --include "Complexity"

# Metrics collected:
# - Cyclomatic complexity
# - Cognitive complexity
# - Lines of code
# - Method length
# - Class size

Détection de la duplication

# Detect code duplication
qodana scan --include "Code duplication"

# Configure duplication thresholds in qodana.yaml:
version: "1.0"
profile:
  name: qodana.recommended
duplicates:
  minTokens: 50
  minLines: 10

Évaluation technique de la dette

// Technical Debt Examples

// ❌ High technical debt
function processData(data) {
    // TODO: Refactor this method
    if (data) {
        if (data.length > 0) {
            for (let i = 0; i < data.length; i++) {
                if (data[i].status === 'active') {
                    // Complex nested logic
                    if (data[i].type === 'premium') {
                        // More nesting...
                    }
                }
            }
        }
    }
}

// ✅ Refactored code
function processActiveData(data) {
    if (!data?.length) return;

    return data
        .filter(item => item.status === 'active')
        .map(item => processItem(item));
}

function processItem(item) {
    return item.type === 'premium' 
        ? processPremiumItem(item)
        : processStandardItem(item);
}

Rapports et visualisation

Rapports HTML

# Generate HTML report
qodana scan --show-report

# Custom report location
qodana scan --results-dir ./custom-results
qodana show --port 8080 --results-dir ./custom-results

Rapports SARIF

# Generate SARIF report
qodana scan --sarif-report results.sarif

# Upload to GitHub Security tab
# (automatically done with GitHub Actions integration)

# Convert SARIF to other formats
qodana export --format json --input results.sarif --output results.json

Modèles de rapports personnalisés

<!-- Custom HTML template -->
<!DOCTYPE html>
<html>
<head>
    <title>Custom Qodana Report</title>
    <style>
        .critical { color: red; font-weight: bold; }
        .high { color: orange; }
        .medium { color: yellow; }
        .low { color: green; }
    </style>
</head>
<body>
    <h1>Code Quality Report</h1>
    <div id="summary">
        <!-- Summary statistics -->
    </div>
    <div id="issues">
        <!-- Issue details -->
    </div>
</body>
</html>

Intégration IDE

Intégration IntelliJ IDEA

# Qodana plugin for IntelliJ IDEA
# 1. Install Qodana plugin from marketplace
# 2. Configure Qodana settings
# 3. Run analysis from IDE
# 4. View results in tool window

# Plugin features:
# - Run Qodana analysis locally
# - View results in IDE
# - Navigate to issues
# - Configure inspection profiles
# - Integration with VCS

Intégration du code VS

# Qodana extension for VS Code
# 1. Install Qodana extension
# 2. Configure workspace settings
# 3. Run analysis command
# 4. View results in problems panel

# Extension commands:
# - Qodana: Scan Project
# - Qodana: Show Results
# - Qodana: Configure
# - Qodana: Upload Results

Intégration de la ligne de commande

# IDE-like experience in terminal
qodana scan --ide-like

# Open results in default browser
qodana show --open

# Watch mode for development
qodana scan --watch --fail-threshold 0

Caractéristiques avancées

Gestion de base

# Create baseline from current state
qodana scan --baseline qodana-baseline.sarif.json

# Update baseline
qodana scan --update-baseline qodana-baseline.sarif.json

# Use baseline to check only new issues
qodana scan --baseline qodana-baseline.sarif.json --fail-threshold 0

Inspections sur mesure

// Custom inspection example
class CustomInspection : LocalInspectionTool() {
    override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
        return object : JavaElementVisitor() {
            override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
                super.visitMethodCallExpression(expression)

                if (isDeprecatedMethod(expression)) {
                    holder.registerProblem(
                        expression,
                        "Use of deprecated method",
                        ProblemHighlightType.WARNING
                    )
                }
            }
        }
    }

    private fun isDeprecatedMethod(expression: PsiMethodCallExpression): Boolean {
        // Custom logic to detect deprecated methods
        return false
    }
}

Conformité à la licence

# License detection and compliance
qodana scan --include "License"

# Configure allowed licenses
version: "1.0"
profile:
  name: qodana.recommended
licenseRules:
  allowed:
    - "MIT"
    - "Apache-2.0"
    - "BSD-3-Clause"
  prohibited:
    - "GPL-3.0"
    - "AGPL-3.0"

Dépannage

Questions communes

# Out of memory errors
docker run --rm -it \
  -m 4g \
  -v $(pwd):/data/project/ \
  -v $(pwd)/qodana-results:/data/results/ \
  jetbrains/qodana-jvm

# Permission issues
sudo chown -R $USER:$USER qodana-results/

# Network connectivity issues
docker run --rm -it \
  --network host \
  -v $(pwd):/data/project/ \
  -v $(pwd)/qodana-results:/data/results/ \
  jetbrains/qodana-jvm

Optimisation des performances

# Optimize for large projects
qodana scan \
  --cache-dir ./qodana-cache \
  --exclude-paths "node_modules/**,target/**,build/**" \
  --include "Critical,High"

# Parallel processing
docker run --rm -it \
  --cpus="4" \
  -m 8g \
  -v $(pwd):/data/project/ \
  -v $(pwd)/qodana-results:/data/results/ \
  jetbrains/qodana-jvm

Mode de débogage

# Enable debug logging
qodana scan --log-level debug

# Verbose output
qodana scan --verbose

# Save logs
qodana scan --log-file qodana.log

Meilleures pratiques

Gestion de la configuration

# Version control qodana.yaml
# - Keep configuration in repository
# - Use environment-specific configs
# - Document configuration changes
# - Review configuration in PRs

# Example structure:
.qodana/
├── qodana.yaml              # Main configuration
├── profiles/
│   ├── strict.xml          # Strict quality profile
│   └── relaxed.xml         # Relaxed profile for legacy code
├── baselines/
│   ├── main.sarif.json     # Main branch baseline
│   └── legacy.sarif.json   # Legacy code baseline
└── scripts/
    └── bootstrap.sh        # Setup script

Pratiques exemplaires de l'IC/DC

# Gradual adoption strategy:
# 1. Start with baseline to avoid failing builds
# 2. Gradually reduce fail threshold
# 3. Focus on critical and high-priority issues first
# 4. Regular baseline updates
# 5. Team training and adoption

# Performance considerations:
# - Use caching between builds
# - Exclude unnecessary files/directories
# - Run on appropriate hardware
# - Use incremental analysis when possible

Adoption par l'équipe

# Team onboarding:
# 1. Introduce Qodana gradually
# 2. Provide training on code quality
# 3. Set up IDE integration
# 4. Regular review of quality metrics
# 5. Celebrate improvements

# Quality culture:
# - Make quality metrics visible
# - Regular quality reviews
# - Code quality champions
# - Continuous improvement mindset

Ressources

Documentation

  • [Documentation Qodana] (LINK_9)
  • [Référence Qodana CLI] (LINK_9)
  • [Images en fonte] (LINK_9)

Communauté

  • [Communauté Qodana] (LINK_9)
  • [Répertoire GitHub] (LINK_9)
  • [Débordement de la pile] (LINK_9)

Formation