Qodana Feuille de chaleur
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
- [Qodana Webinars] (LINK_9)
- Pratiques exemplaires de qualité du code
- [Guides d'intégration] (LINK_9)