SonarQube
DevOpsツール
SonarQube
概要
SonarQubeは、継続的なコード品質管理プラットフォームです。静的解析により、バグ、脆弱性、コードスメルを検出し、技術的負債の可視化と品質ゲートによる自動品質チェックを提供。30以上のプログラミング言語をサポートし、AI生成コードの品質保証機能も搭載。企業レベルのコード品質管理とセキュリティ強化を実現する、DevOpsパイプラインに統合可能な業界標準ツールです。
詳細
SonarQube(ソナーキューブ)は、SonarSourceが開発する企業向けコード品質管理プラットフォームで、2007年のリリース以来、静的コード解析の業界標準として確立されています。2025年版のSonarQube Server 2025.3では、AI Code Assurance機能が追加され、AI生成コードの自動レビューと品質チェックを実現しています。
主要な特徴
- 包括的な静的解析: 30以上の言語・フレームワーク・IaCプラットフォームサポート
- AI Code Assurance: AI生成コードの自動品質保証とセキュリティチェック
- セキュリティ強化: 包括的シークレット検出とセキュリティ脆弱性解析
- 品質ゲート: 品質基準を満たさないコードの本番環境デプロイ防止
- 技術的負債管理: コード負債の可視化と改善優先順位付け
- CI/CD統合: GitHub Actions、GitLab CI/CD、Azure Pipelines等との統合
- IDE統合: リアルタイムコードレビューによる開発時品質チェック
- コンプライアンス対応: NIST SSDF、OWASP、CWE、STIG、CASA等の標準準拠
- マルチデプロイメント: オンプレミス、クラウド、Docker、Kubernetes対応
コード品質指標(バグ、脆弱性、コードスメル、重複、カバレッジ、複雑度)を統合的に管理し、継続的品質改善を支援します。
メリット・デメリット
メリット
- エンタープライズレベルの包括的コード品質管理を一元化
- AI生成コードの品質保証により現代的な開発環境に対応
- 30以上の言語対応で多言語プロジェクトの統一的品質管理
- 品質ゲートによる自動的な品質基準強制で本番品質を保証
- 技術的負債の可視化により計画的なリファクタリング実現
- CI/CD統合によりDevOpsパイプラインでの自動品質チェック
- セキュリティ脆弱性とシークレット検出でセキュリティ強化
- コンプライアンス対応により規制要件を満たす品質管理
- IDE統合により開発時のリアルタイム品質フィードバック
- 豊富なメトリクスとレポートにより品質改善の数値的根拠提供
デメリット
- エンタープライズ機能の商用ライセンス費用(大規模組織では高額)
- 初期設定の複雑さと学習コストの高さ
- 大規模プロジェクトでの解析時間の長さ
- サーバーリソース要件の高さ(CPU、メモリ、ストレージ)
- Community Editionでの機能制限(ブランチ解析、セキュリティ機能等)
- ルール調整とカスタマイズの複雑性
- レガシーコードへの適用時の大量警告による運用負荷
- 開発チームへの品質文化浸透に時間が必要
- 過度な品質強制による開発速度低下リスク
参考ページ
- SonarQube公式サイト
- SonarQube公式ドキュメント
- SonarQube GitHub リポジトリ
- SonarQube Community
- SonarLint IDE拡張
- SonarCloud(クラウド版)
書き方の例
インストールとセットアップ
Docker Compose設定
# docker-compose.yml
version: "3.8"
services:
sonarqube:
image: sonarqube:10.8.1-community
container_name: sonarqube
depends_on:
- sonarqube-db
environment:
SONAR_JDBC_URL: jdbc:postgresql://sonarqube-db:5432/sonar
SONAR_JDBC_USERNAME: sonar
SONAR_JDBC_PASSWORD: sonar
volumes:
- sonarqube_data:/opt/sonarqube/data
- sonarqube_extensions:/opt/sonarqube/extensions
- sonarqube_logs:/opt/sonarqube/logs
ports:
- "9000:9000"
ulimits:
nofile:
soft: 65536
hard: 65536
nproc: 4096
sonarqube-db:
image: postgres:16-alpine
container_name: sonarqube-db
environment:
POSTGRES_USER: sonar
POSTGRES_PASSWORD: sonar
POSTGRES_DB: sonar
volumes:
- postgresql_data:/var/lib/postgresql/data
volumes:
sonarqube_data:
sonarqube_extensions:
sonarqube_logs:
postgresql_data:
起動とアクセス
# Docker Composeでの起動
docker-compose up -d
# ログ確認
docker-compose logs -f sonarqube
# アクセス確認
curl http://localhost:9000/api/system/health
# 初期アクセス
# URL: http://localhost:9000
# 初期ログイン: admin / admin
# 初回ログイン時にパスワード変更が必要
プロジェクト解析設定
sonar-project.properties設定
# sonar-project.properties - 基本設定
sonar.projectKey=my-project
sonar.projectName=My Project
sonar.projectVersion=1.0
sonar.sourceEncoding=UTF-8
# ソースコード設定
sonar.sources=src
sonar.tests=tests
sonar.exclusions=**/node_modules/**,**/dist/**,**/*.min.js
sonar.test.exclusions=**/node_modules/**
# JavaScript/TypeScript設定
sonar.javascript.lcov.reportPaths=coverage/lcov.info
sonar.typescript.lcov.reportPaths=coverage/lcov.info
# Java設定
sonar.java.source=17
sonar.java.target=17
sonar.java.binaries=target/classes
sonar.java.test.binaries=target/test-classes
sonar.junit.reportPaths=target/surefire-reports
# Python設定
sonar.python.coverage.reportPaths=coverage.xml
sonar.python.xunit.reportPaths=test-results.xml
# C#設定
sonar.cs.nunit.reportsPaths=TestResults/*.xml
sonar.cs.opencover.reportsPaths=TestResults/coverage.opencover.xml
# カバレッジしきい値
sonar.coverage.exclusions=**/*test*/**,**/migrations/**
SonarScannerを使った解析実行
JavaScript/TypeScript プロジェクト
# SonarScannerインストール
npm install -g sonar-scanner
# package.json設定
npm pkg set scripts.sonar="sonar-scanner"
# 解析実行
sonar-scanner \
-Dsonar.projectKey=my-js-project \
-Dsonar.sources=src \
-Dsonar.host.url=http://localhost:9000 \
-Dsonar.token=your_token_here
# カバレッジ付き解析
npm run test -- --coverage
sonar-scanner \
-Dsonar.projectKey=my-js-project \
-Dsonar.sources=src \
-Dsonar.tests=src \
-Dsonar.test.inclusions=**/*.test.ts,**/*.spec.ts \
-Dsonar.javascript.lcov.reportPaths=coverage/lcov.info \
-Dsonar.host.url=http://localhost:9000 \
-Dsonar.token=your_token_here
Maven(Java)プロジェクト
<!-- pom.xml -->
<properties>
<sonar.host.url>http://localhost:9000</sonar.host.url>
<sonar.token>your_token_here</sonar.token>
<sonar.coverage.exclusions>
**/test/**,
**/target/**
</sonar.coverage.exclusions>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>4.0.0.4121</version>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.12</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
# Maven解析実行
mvn clean compile test jacoco:report sonar:sonar
# 特定品質ゲート確認
mvn sonar:sonar -Dsonar.qualitygate.wait=true
.NET プロジェクト
# .NET SonarScannerインストール
dotnet tool install --global dotnet-sonarscanner
# 解析開始
dotnet sonarscanner begin \
/k:"my-dotnet-project" \
/d:sonar.host.url="http://localhost:9000" \
/d:sonar.token="your_token_here" \
/d:sonar.cs.opencover.reportsPaths="TestResults/coverage.opencover.xml"
# ビルドとテスト
dotnet build
dotnet test --collect:"XPlat Code Coverage" -- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=opencover
# 解析終了
dotnet sonarscanner end /d:sonar.token="your_token_here"
CI/CD統合例
GitHub Actions
# .github/workflows/sonarqube.yml
name: SonarQube Analysis
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
sonarqube:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0 # Shallow clones should be disabled
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests with coverage
run: npm run test -- --coverage --watchAll=false
- name: SonarQube Scan
uses: sonarqube-quality-gate-action@master
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
with:
projectBaseDir: .
args: >
-Dsonar.projectKey=${{ github.repository }}
-Dsonar.sources=src
-Dsonar.tests=src
-Dsonar.test.inclusions=**/*.test.ts,**/*.spec.ts
-Dsonar.javascript.lcov.reportPaths=coverage/lcov.info
- name: Quality Gate Check
uses: sonarqube-quality-gate-action@master
timeout-minutes: 5
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
GitLab CI/CD
# .gitlab-ci.yml
variables:
SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar"
GIT_DEPTH: "0"
cache:
key: "${CI_JOB_NAME}"
paths:
- .sonar/cache
stages:
- test
- quality
test:
stage: test
image: node:20-alpine
before_script:
- npm ci
script:
- npm run test -- --coverage --watchAll=false
artifacts:
reports:
coverage_report:
coverage_format: cobertura
path: coverage/cobertura-coverage.xml
paths:
- coverage/
expire_in: 1 day
sonarqube-check:
stage: quality
image:
name: sonarsource/sonar-scanner-cli:latest
entrypoint: [""]
dependencies:
- test
script:
- sonar-scanner
-Dsonar.projectKey=${CI_PROJECT_NAME}
-Dsonar.sources=src
-Dsonar.tests=src
-Dsonar.test.inclusions=**/*.test.ts,**/*.spec.ts
-Dsonar.javascript.lcov.reportPaths=coverage/lcov.info
-Dsonar.host.url=${SONAR_HOST_URL}
-Dsonar.token=${SONAR_TOKEN}
-Dsonar.qualitygate.wait=true
only:
- main
- develop
- merge_requests
品質ゲート設定
カスタム品質ゲート設定例
{
"name": "Strict Quality Gate",
"conditions": [
{
"metric": "new_coverage",
"operation": "LT",
"threshold": "80",
"periodIndex": "1"
},
{
"metric": "new_duplicated_lines_density",
"operation": "GT",
"threshold": "3",
"periodIndex": "1"
},
{
"metric": "new_maintainability_rating",
"operation": "GT",
"threshold": "1",
"periodIndex": "1"
},
{
"metric": "new_reliability_rating",
"operation": "GT",
"threshold": "1",
"periodIndex": "1"
},
{
"metric": "new_security_rating",
"operation": "GT",
"threshold": "1",
"periodIndex": "1"
},
{
"metric": "new_security_hotspots_reviewed",
"operation": "LT",
"threshold": "100",
"periodIndex": "1"
}
]
}
プロジェクト固有設定とルールカスタマイズ
Quality Profile作成
# SonarQube Web APIを使用したQuality Profile操作
# 新しいQuality Profile作成
curl -X POST \
"${SONAR_HOST_URL}/api/qualityprofiles/create" \
-H "Authorization: Bearer ${SONAR_TOKEN}" \
-d "language=js" \
-d "name=MyCompany TypeScript Rules"
# ルール追加
curl -X POST \
"${SONAR_HOST_URL}/api/qualityprofiles/activate_rule" \
-H "Authorization: Bearer ${SONAR_TOKEN}" \
-d "key=MyCompany_TypeScript_Rules" \
-d "rule=typescript:S1066" \
-d "severity=MAJOR"
# ルール設定変更
curl -X POST \
"${SONAR_HOST_URL}/api/qualityprofiles/activate_rule" \
-H "Authorization: Bearer ${SONAR_TOKEN}" \
-d "key=MyCompany_TypeScript_Rules" \
-d "rule=typescript:S3776" \
-d "severity=CRITICAL" \
-d "params=threshold=15"
レポートとメトリクス活用
SonarQube Web API活用
# プロジェクト品質メトリクス取得
curl -H "Authorization: Bearer ${SONAR_TOKEN}" \
"${SONAR_HOST_URL}/api/measures/component?component=${PROJECT_KEY}&metricKeys=coverage,duplicated_lines_density,bugs,vulnerabilities,code_smells,sqale_rating,reliability_rating,security_rating"
# 品質ゲート状態確認
curl -H "Authorization: Bearer ${SONAR_TOKEN}" \
"${SONAR_HOST_URL}/api/qualitygates/project_status?projectKey=${PROJECT_KEY}"
# 問題一覧取得
curl -H "Authorization: Bearer ${SONAR_TOKEN}" \
"${SONAR_HOST_URL}/api/issues/search?componentKeys=${PROJECT_KEY}&types=BUG,VULNERABILITY,CODE_SMELL"
カスタムダッシュボード用データ取得
# Python例:SonarQube metrics collector
import requests
import json
class SonarQubeCollector:
def __init__(self, host_url, token):
self.host_url = host_url
self.headers = {"Authorization": f"Bearer {token}"}
def get_project_metrics(self, project_key):
"""プロジェクトメトリクス取得"""
metrics = [
'coverage', 'duplicated_lines_density', 'bugs',
'vulnerabilities', 'code_smells', 'sqale_rating',
'reliability_rating', 'security_rating', 'sqale_index'
]
url = f"{self.host_url}/api/measures/component"
params = {
'component': project_key,
'metricKeys': ','.join(metrics)
}
response = requests.get(url, headers=self.headers, params=params)
return response.json()
def get_quality_gate_status(self, project_key):
"""品質ゲート状態取得"""
url = f"{self.host_url}/api/qualitygates/project_status"
params = {'projectKey': project_key}
response = requests.get(url, headers=self.headers, params=params)
return response.json()
def get_issues_summary(self, project_key):
"""問題集計取得"""
url = f"{self.host_url}/api/issues/search"
params = {
'componentKeys': project_key,
'facets': 'types,severities,rules',
'ps': 1 # 件数は不要
}
response = requests.get(url, headers=self.headers, params=params)
return response.json()
# 使用例
collector = SonarQubeCollector('http://localhost:9000', 'your_token')
metrics = collector.get_project_metrics('my-project')
quality_gate = collector.get_quality_gate_status('my-project')
セキュリティとコンプライアンス設定
セキュリティホットスポット管理
# セキュリティホットスポット一覧取得
curl -H "Authorization: Bearer ${SONAR_TOKEN}" \
"${SONAR_HOST_URL}/api/hotspots/search?projectKey=${PROJECT_KEY}"
# ホットスポット詳細取得
curl -H "Authorization: Bearer ${SONAR_TOKEN}" \
"${SONAR_HOST_URL}/api/hotspots/show?hotspot=${HOTSPOT_KEY}"
# ホットスポット状態更新(確認済み)
curl -X POST \
-H "Authorization: Bearer ${SONAR_TOKEN}" \
"${SONAR_HOST_URL}/api/hotspots/change_status" \
-d "hotspot=${HOTSPOT_KEY}" \
-d "status=REVIEWED" \
-d "resolution=SAFE"
コンプライアンスレポート設定
# compliance-check.yml - コンプライアンスチェック自動化
name: Compliance Check
on:
schedule:
- cron: '0 2 * * 1' # 毎週月曜日午前2時
workflow_dispatch:
jobs:
compliance:
runs-on: ubuntu-latest
steps:
- name: Generate Compliance Report
run: |
# OWASP Top 10チェック
curl -H "Authorization: Bearer ${{ secrets.SONAR_TOKEN }}" \
"${{ secrets.SONAR_HOST_URL }}/api/measures/component?component=${{ github.repository }}&metricKeys=security_rating,security_hotspots,vulnerabilities" \
> security-report.json
# CWEカテゴリ別脆弱性集計
curl -H "Authorization: Bearer ${{ secrets.SONAR_TOKEN }}" \
"${{ secrets.SONAR_HOST_URL }}/api/issues/search?componentKeys=${{ github.repository }}&types=VULNERABILITY&facets=cwe" \
> cwe-report.json
# レポート生成(Python scriptなど)
python generate-compliance-report.py
- name: Upload Compliance Report
uses: actions/upload-artifact@v4
with:
name: compliance-report
path: compliance-report.pdf