SonarQube Analysis
SonarQube Code Quality Static Analysis CI/CD Quality Gate Bug Vulnerability Code Smell Coverage Duplication Technical Debt Batch Processing Pipeline Dashboard
| Tool | Analysis Type | Languages | CI/CD | เหมาะกับ |
|---|---|---|---|---|
| SonarQube | SAST + Quality | 30+ | ทุก CI | Enterprise |
| SonarCloud | SAST + Quality | 30+ | Cloud CI | Open Source |
| CodeClimate | Quality + Coverage | 10+ | GitHub | Startups |
| Semgrep | SAST | 20+ | ทุก CI | Security |
| ESLint/Pylint | Linting | 1 each | ทุก CI | Single Language |
SonarQube Setup
# === SonarQube Setup & Configuration ===
# Docker Compose — SonarQube Server
# version: '3.8'
# services:
# sonarqube:
# image: sonarqube:lts-community
# ports:
# - "9000:9000"
# environment:
# - SONAR_JDBC_URL=jdbc:postgresql://db:5432/sonar
# - SONAR_JDBC_USERNAME=sonar
# - SONAR_JDBC_PASSWORD=sonar
# volumes:
# - sonarqube_data:/opt/sonarqube/data
# - sonarqube_logs:/opt/sonarqube/logs
# - sonarqube_extensions:/opt/sonarqube/extensions
# depends_on:
# - db
# db:
# image: postgres:16
# environment:
# - POSTGRES_USER=sonar
# - POSTGRES_PASSWORD=sonar
# - POSTGRES_DB=sonar
# volumes:
# - postgresql_data:/var/lib/postgresql/data
# sonar-project.properties
# sonar.projectKey=my-app
# sonar.projectName=My Application
# sonar.projectVersion=1.0
# sonar.sources=src
# sonar.tests=tests
# sonar.language=py
# sonar.python.coverage.reportPaths=coverage.xml
# sonar.python.xunit.reportPath=test-results.xml
# sonar.exclusions=**/node_modules/**,**/venv/**,**/*.test.py
# sonar.coverage.exclusions=**/tests/**,**/migrations/**
# GitHub Actions — SonarQube Analysis
# name: SonarQube Analysis
# on:
# push:
# branches: [main, develop]
# pull_request:
# types: [opened, synchronize, reopened]
# jobs:
# sonarqube:
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v4
# with:
# fetch-depth: 0
# - name: Run tests with coverage
# run: |
# pip install pytest pytest-cov
# pytest --cov=src --cov-report=xml
# - name: SonarQube Scan
# uses: SonarSource/sonarqube-scan-action@master
# env:
# SONAR_TOKEN: }
# SONAR_HOST_URL: }
# - name: Quality Gate Check
# uses: SonarSource/sonarqube-quality-gate-action@master
# env:
# SONAR_TOKEN: }
from dataclasses import dataclass
@dataclass
class QualityMetric:
metric: str
current: str
threshold: str
status: str
trend: str
metrics = [
QualityMetric("Bugs", "3", "0 (new code)", "Warning", "↓ from 8"),
QualityMetric("Vulnerabilities", "1", "0 (new code)", "Warning", "↓ from 5"),
QualityMetric("Code Smells", "45", "<10 (new code)", "OK", "↓ from 120"),
QualityMetric("Coverage", "78%", ">80%", "Warning", "↑ from 65%"),
QualityMetric("Duplications", "2.1%", "<3%", "OK", "↓ from 5.2%"),
QualityMetric("Technical Debt", "4d", "<5d", "OK", "↓ from 12d"),
]
print("=== SonarQube Dashboard ===")
for m in metrics:
print(f" [{m.status}] {m.metric}: {m.current} (Threshold: {m.threshold})")
print(f" Trend: {m.trend}")
Batch Processing
# === Batch SonarQube Analysis ===
# Batch Scanner Script
# #!/bin/bash
# # scan_all_projects.sh
# SONAR_URL="http://sonarqube:9000"
# SONAR_TOKEN="squ_xxxxxxxxxxxx"
#
# PROJECTS=(
# "api-service:services/api"
# "web-frontend:services/web"
# "worker:services/worker"
# "shared-lib:libs/shared"
# "auth-service:services/auth"
# )
#
# for project in ""; do
# IFS=':' read -r key path <<< "$project"
# echo "Scanning $key..."
# sonar-scanner \
# -Dsonar.projectKey="$key" \
# -Dsonar.sources="$path/src" \
# -Dsonar.host.url="$SONAR_URL" \
# -Dsonar.token="$SONAR_TOKEN" \
# -Dsonar.python.coverage.reportPaths="$path/coverage.xml"
# echo "$key scan complete"
# done
# Python — SonarQube API for Batch Report
# import requests
# import json
#
# SONAR_URL = "http://sonarqube:9000"
# SONAR_TOKEN = "squ_xxxxxxxxxxxx"
#
# def get_project_status(project_key):
# url = f"{SONAR_URL}/api/qualitygates/project_status"
# response = requests.get(url, params={"projectKey": project_key},
# auth=(SONAR_TOKEN, ""))
# return response.json()
#
# def get_project_measures(project_key):
# metrics = "bugs,vulnerabilities,code_smells,coverage,duplicated_lines_density"
# url = f"{SONAR_URL}/api/measures/component"
# response = requests.get(url,
# params={"component": project_key, "metricKeys": metrics},
# auth=(SONAR_TOKEN, ""))
# return response.json()
#
# projects = ["api-service", "web-frontend", "worker", "shared-lib", "auth-service"]
# for project in projects:
# status = get_project_status(project)
# measures = get_project_measures(project)
# gate_status = status['projectStatus']['status']
# print(f"{project}: Quality Gate = {gate_status}")
@dataclass
class ProjectStatus:
project: str
gate_status: str
bugs: int
vulns: int
smells: int
coverage: float
duplication: float
projects = [
ProjectStatus("api-service", "OK", 0, 0, 12, 85.3, 1.8),
ProjectStatus("web-frontend", "OK", 1, 0, 25, 72.1, 3.2),
ProjectStatus("worker", "OK", 0, 0, 8, 90.5, 0.5),
ProjectStatus("shared-lib", "OK", 0, 0, 3, 95.2, 0.2),
ProjectStatus("auth-service", "WARN", 2, 1, 15, 68.4, 2.1),
]
print("\n=== Batch Analysis Report ===")
for p in projects:
print(f" [{p.gate_status}] {p.project}")
print(f" Bugs: {p.bugs} | Vulns: {p.vulns} | Smells: {p.smells}")
print(f" Coverage: {p.coverage}% | Duplication: {p.duplication}%")
Quality Gate
# === Quality Gate Configuration ===
# Quality Gate Conditions
# New Code (default period: previous version)
# - Coverage on New Code >= 80%
# - Duplicated Lines on New Code <= 3%
# - Maintainability Rating on New Code = A
# - Reliability Rating on New Code = A
# - Security Rating on New Code = A
# - Security Hotspots Reviewed >= 100%
# Custom Quality Gate via API
# curl -X POST "$SONAR_URL/api/qualitygates/create" \
# -H "Authorization: Bearer $TOKEN" \
# -d "name=Strict-Gate"
#
# curl -X POST "$SONAR_URL/api/qualitygates/create_condition" \
# -H "Authorization: Bearer $TOKEN" \
# -d "gateName=Strict-Gate&metric=new_coverage&op=LT&error=85"
# Webhook — Notify on Quality Gate change
# curl -X POST "$SONAR_URL/api/webhooks/create" \
# -H "Authorization: Bearer $TOKEN" \
# -d "name=slack-notify&url=https://hooks.slack.com/services/..."
@dataclass
class GateCondition:
metric: str
operator: str
threshold: str
scope: str
rationale: str
conditions = [
GateCondition("Coverage", ">=", "80%", "New Code", "ต้องมี Test Coverage เพียงพอ"),
GateCondition("Duplications", "<=", "3%", "New Code", "ไม่ Copy Paste Code"),
GateCondition("Bugs", "=", "0", "New Code", "ไม่มี Bug ใน Code ใหม่"),
GateCondition("Vulnerabilities", "=", "0", "New Code", "ไม่มีช่องโหว่ Security"),
GateCondition("Code Smells", "<=", "10", "New Code", "Maintainability ดี"),
GateCondition("Security Hotspots", "Reviewed", "100%", "New Code", "ตรวจทุก Hotspot"),
]
print("Quality Gate Conditions:")
for c in conditions:
print(f" [{c.metric}] {c.operator} {c.threshold} ({c.scope})")
print(f" Rationale: {c.rationale}")
# Batch Processing Schedule
schedule = {
"PR Analysis": "ทุก Pull Request (Trigger on push)",
"Branch Analysis": "ทุก Push to main/develop",
"Nightly Full Scan": "ทุกคืน 02:00 (Cron) ทุก Project",
"Weekly Report": "ทุกจันทร์ 08:00 สรุปรวม",
"Monthly Trend": "ทุกเดือน Technical Debt Trend",
}
print(f"\n\nAnalysis Schedule:")
for name, desc in schedule.items():
print(f" [{name}]: {desc}")
เคล็ดลับ
- PR Gate: บังคับ Quality Gate ทุก PR ไม่ให้ Merge ถ้าไม่ผ่าน
- New Code: เน้น New Code Period ไม่ต้องแก้ Legacy ทั้งหมด
- Coverage: ตั้งเป้า 80%+ Coverage สำหรับ Code ใหม่
- Batch: สแกนทุก Project ทุกคืน สร้าง Report รวม
- Webhook: ตั้ง Webhook แจ้ง Slack เมื่อ Gate ไม่ผ่าน
การนำไปใช้งานจริงในองค์กร
สำหรับองค์กรขนาดกลางถึงใหญ่ แนะนำให้ใช้หลัก Three-Tier Architecture คือ Core Layer ที่เป็นแกนกลางของระบบ Distribution Layer ที่ทำหน้าที่กระจาย Traffic และ Access Layer ที่เชื่อมต่อกับผู้ใช้โดยตรง การแบ่ง Layer ชัดเจนช่วยให้การ Troubleshoot ง่ายขึ้นและสามารถ Scale ระบบได้ตามความต้องการ
เรื่อง Network Security ก็สำคัญไม่แพ้กัน ควรติดตั้ง Next-Generation Firewall ที่สามารถ Deep Packet Inspection ได้ ใช้ Network Segmentation แยก VLAN สำหรับแต่ละแผนก ติดตั้ง IDS/IPS เพื่อตรวจจับการโจมตี และทำ Regular Security Audit อย่างน้อยปีละ 2 ครั้ง
เปรียบเทียบข้อดีและข้อเสีย
จากตารางเปรียบเทียบจะเห็นว่าข้อดีมีมากกว่าข้อเสียอย่างชัดเจน โดยเฉพาะในแง่ของประสิทธิภาพและความสามารถในการ Scale สำหรับข้อเสียส่วนใหญ่สามารถแก้ไขได้ด้วยการเรียนรู้อย่างเป็นระบบและวางแผนทรัพยากรให้เหมาะสม
SonarQube คืออะไร
Open Source Code Quality Static Analysis Bug Vulnerability Code Smell Coverage Duplication 30+ ภาษา Quality Gate Dashboard CI/CD Pipeline Technical Debt
Quality Gate คืออะไร
เกณฑ์ Code ผ่านมาตรฐาน Coverage 80% Bugs 0 Vulnerabilities 0 Smells 10 Duplication 3% CI/CD Fail ไม่ Deploy ตั้งค่าได้
ตั้งค่า SonarQube กับ CI/CD อย่างไร
Docker Server SonarScanner sonar-project.properties Pipeline Push PR Dashboard PR Decoration GitHub GitLab Quality Gate Merge
Batch Processing Pipeline วิเคราะห์อย่างไร
Script สแกนหลาย Project API ดึงผลลัพธ์ Report รวม Webhook แจ้งเตือน Schedule สแกนทุกคืน PR Analysis Aggregate Metrics Dashboard
สรุป
SonarQube Analysis Batch Processing Pipeline Code Quality Static Analysis CI/CD Quality Gate Bug Vulnerability Coverage Dashboard Technical Debt Webhook Report
