SKILL.md
唯讀
名稱
quarkus-verification
描述
Quarkus 專案的完整驗證流程:包含建置、靜態程式碼分析、涵蓋率測試、資安掃描、原生編譯(Native Compilation),以及在發布或送出 PR 前的程式碼變更審查。
Quarkus 驗證流程 (Quarkus Verification Loop)
建議在建立 PR 前、完成重大變更後,以及正式部署前執行。
啟用時機
- 為 Quarkus 服務建立 Pull Request 前
- 進行重大重構或升級套件相依性後
- 部署至 Staging 或 Production 環境前的最後驗證
- 執行完整的「建置 → Linter 檢查 → 測試 → 資安掃描 → 原生編譯」流水線
- 確認測試涵蓋率達到指定門檻(80%+)
- 驗證原生映像檔(Native Image)的相容性
Phase 1: Build(建置)
# Maven
mvn clean verify -DskipTests
# Gradle
./gradlew clean assemble -x test
若建置失敗,請立即停止並修復編譯錯誤。
Phase 2: Static Analysis(靜態分析)
Checkstyle、PMD、SpotBugs (Maven)
mvn checkstyle:check pmd:check spotbugs:check
SonarQube(若已配置)
mvn sonar:sonar \
-Dsonar.projectKey=my-quarkus-project \
-Dsonar.host.url=http://localhost:9000 \
-Dsonar.login=${SONAR_TOKEN}
常見待修復問題
- 未使用的 import 或變數
- 複雜度過高的 Method(高循環複雜度)
- 潛在的 Null 指標解引用(Null pointer dereferences)
- SpotBugs 標記的資安疑慮
Phase 3: Tests + Coverage(測試與涵蓋率)
# 執行所有測試
mvn clean test
# 產生涵蓋率報告
mvn jacoco:report
# 強制要求涵蓋率門檻 (80%)
mvn jacoco:check
# 或使用 Gradle
./gradlew test jacocoTestReport jacocoTestCoverageVerification
測試類別
單元測試 (Unit Tests)
使用 Mock 模擬相依物件以測試服務邏輯:
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock UserRepository userRepository;
@InjectMocks UserService userService;
@Test
void createUser_validInput_returnsUser() {
var dto = new CreateUserDto("Alice", "alice@example.com");
// Panache 的 persist() 回傳值為 void — 請使用 doNothing + verify
doNothing().when(userRepository).persist(any(User.class));
User result = userService.create(dto);
assertThat(result.name).isEqualTo("Alice");
verify(userRepository).persist(any(User.class));
}
}
整合測試 (Integration Tests)
搭配真實資料庫進行測試(Testcontainers):
@QuarkusTest
@QuarkusTestResource(PostgresTestResource.class)
class UserRepositoryIntegrationTest {
@Inject
UserRepository userRepository;
@Test
@Transactional
void findByEmail_existingUser_returnsUser() {
User user = new User();
user.name = "Alice";
user.email = "alice@example.com";
userRepository.persist(user);
Optional<User> found = userRepository.findByEmail("alice@example.com");
assertThat(found).isPresent();
assertThat(found.get().name).isEqualTo("Alice");
}
}
API 測試 (API Tests)
使用 REST Assured 測試 REST 端點:
@QuarkusTest
class UserResourceTest {
@Test
void createUser_validInput_returns201() {
given()
.contentType(ContentType.JSON)
.body("""
{"name": "Alice", "email": "alice@example.com"}
""")
.when().post("/api/users")
.then()
.statusCode(201)
.body("name", equalTo("Alice"));
}
@Test
void createUser_invalidEmail_returns400() {
given()
.contentType(ContentType.JSON)
.body("""
{"name": "Alice", "email": "invalid"}
""")
.when().post("/api/users")
.then()
.statusCode(400);
}
}
涵蓋率報告
開啟 target/site/jacoco/index.html 檢視詳細的涵蓋率指標:
- 整體行涵蓋率(Line coverage,目標:80%+)
- 分支涵蓋率(Branch coverage,目標:70%+)
- 找出未涵蓋到的關鍵執行路徑
Phase 4: Security Scanning(資安掃描)
套件相依性漏洞檢測 (Maven)
mvn org.owasp:dependency-check-maven:check
檢視 target/dependency-check-report.html 確認是否有已知 CVE 漏洞。
Quarkus 資安稽核
# 檢查帶有漏洞的 Extension
mvn quarkus:audit
# 列出所有 Extension
mvn quarkus:list-extensions
OWASP ZAP(API 資安測試)
docker run -t owasp/zap2docker-stable zap-api-scan.py \
-t http://localhost:8080/q/openapi \
-f openapi
常見資安檢查項目
- [ ] 所有機密資訊(Secrets)皆經由環境變數讀取(未寫死在程式碼中)
- [ ] 所有端點皆已加上輸入驗證(Input validation)
- [ ] 已正確配置身份驗證與權限控管(Authentication/authorization)
- [ ] CORS 已妥善設定
- [ ] 已設定適當的資安標頭(Security headers)
- [ ] 密碼皆使用 BCrypt 進行雜湊處理
- [ ] 具備防範 SQL Injection 機制(使用參數化查詢)
- [ ] 公開端點皆已設定 Rate limiting(流量限制)
Phase 5: Native Compilation(原生編譯)
測試 GraalVM 原生映像檔(Native Image)的相容性:
# 建置原生執行檔
mvn package -Dnative
# 或使用容器進行建置
mvn package -Dnative -Dquarkus.native.container-build=true
# 測試原生執行檔
./target/*-runner
# 執行基礎冒煙測試 (Smoke tests)
curl http://localhost:8080/q/health/live
curl http://localhost:8080/q/health/ready
原生映像檔疑難排解
常見問題與解法:
- 反射 (Reflection):針對動態載入的類別新增 Reflection 配置
- 資源檔 (Resources):透過
quarkus.native.resources.includes將資源檔案納入 - JNI:若使用原生函式庫,請務必註冊 JNI 類別
Reflection 配置範例:
@RegisterForReflection(targets = {MyDynamicClass.class})
public class ReflectionConfiguration {}
Phase 6: Performance Testing(效能測試)
使用 K6 進行壓力測試
// load-test.js
import http from 'k6/http';
import { check } from 'k6';
export const options = {
stages: [
{ duration: '30s', target: 50 },
{ duration: '1m', target: 100 },
{ duration: '30s', target: 0 },
],
};
export default function () {
const res = http.get('http://localhost:8080/api/markets');
check(res, {
'status is 200': (r) => r.status === 200,
'response time < 200ms': (r) => r.timings.duration < 200,
});
}
執行測試:
k6 run load-test.js
關鍵監控指標
- 回應時間(p50, p95, p99)
- 吞吐量(Throughput,requests/sec)
- 錯誤率(Error rate)
- 記憶體使用量(Memory usage)
- CPU 使用率
Phase 7: Health Checks(健康檢查)
# Liveness 存活檢查
curl http://localhost:8080/q/health/live
# Readiness 就緒檢查
curl http://localhost:8080/q/health/ready
# 完整健康檢查
curl http://localhost:8080/q/health
# 統計指標(若已啟用)
curl http://localhost:8080/q/metrics
預期回應格式:
{
"status": "UP",
"checks": [
{
"name": "Database connection",
"status": "UP"
}
]
}
Phase 8: Container Image Build(容器映像檔建置)
# 建置容器映像檔
mvn package -Dquarkus.container-image.build=true
# 或指定特定的 Registry 進行建置
mvn package \
-Dquarkus.container-image.build=true \
-Dquarkus.container-image.registry=docker.io \
-Dquarkus.container-image.group=myorg \
-Dquarkus.container-image.tag=1.0.0
# 測試容器運行
docker run -p 8080:8080 myorg/my-quarkus-app:1.0.0
容器資安掃描
# Trivy
trivy image myorg/my-quarkus-app:1.0.0
# Grype
grype myorg/my-quarkus-app:1.0.0
Phase 9: Configuration Validation(組態驗證)
# 檢查所有組態屬性
mvn quarkus:info
# 列出所有組態來源
curl http://localhost:8080/q/dev/io.quarkus.quarkus-vertx-http/config
特定環境檢查項目
- [ ] 各環境的資料庫 URL 均已正確設定
- [ ] 機密資訊已完成外置化(Vault、環境變數)
- [ ] 日誌層級(Logging levels)設定合適
- [ ] CORS 允許來源(Origins)配置無誤
- [ ] 已設定 Rate limiting 流量限制
- [ ] 監控與追蹤(Monitoring/tracing)已啟用
Phase 10: Documentation Review(文件審查)
- [ ] OpenAPI/Swagger 文件已同步更新(
/q/swagger-ui) - [ ] README 包含完整的環境建立與設定步驟
- [ ] API 變更事項均已記錄
- [ ] 針對破壞性變更(Breaking changes)提供遷移指南
- [ ] 組態屬性皆已補齊說明文件
產生 OpenAPI 規格檔案:
curl http://localhost:8080/q/openapi -o openapi.json
Verification Checklist(驗證檢查清單)
程式碼品質
- [ ] 建置成功且未產生 Warning 警告
- [ ] 靜態分析過關(無高/中風險告警)
- [ ] 程式碼符合團隊撰寫規範
- [ ] PR 中無留存被註解掉的程式碼或 TODO
測試
- [ ] 所有測試案例皆通過
- [ ] 程式碼涵蓋率 ≥ 80%
- [ ] 完成搭配真實資料庫的整合測試
- [ ] 資安測試全數通過
- [ ] 效能表現落於合理預期區間
資安
- [ ] 無套件相依性漏洞
- [ ] 身份驗證與權限控管邏輯已完成測試
- [ ] 輸入驗證防護完善
- [ ] 原始碼中絕無硬編碼機密資訊
- [ ] 資安標頭(Security headers)設定齊全
部署
- [ ] 原生編譯成功
- [ ] 容器映像檔可順利建置
- [ ] 健康檢查端點回應正常
- [ ] 目標環境的組態設定正確無誤
原生映像檔
- [ ] 原生執行檔建置成功
- [ ] 原生環境測試全數通過
- [ ] 啟動時間 < 100ms
- [ ] 記憶體佔用空間落在合理範圍
Automated Verification Script(自動化驗證腳本)
#!/bin/bash
set -e
echo "=== Phase 1: Build ==="
mvn clean verify -DskipTests
echo "=== Phase 2: Static Analysis ==="
mvn checkstyle:check pmd:check spotbugs:check
echo "=== Phase 3: Tests + Coverage ==="
mvn test jacoco:report jacoco:check
echo "=== Phase 4: Security Scan ==="
mvn org.owasp:dependency-check-maven:check
echo "=== Phase 5: Native Compilation ==="
mvn package -Dnative -Dquarkus.native.container-build=true
echo "=== All Phases Complete ==="
echo "Review reports:"
echo " - Coverage: target/site/jacoco/index.html"
echo " - Security: target/dependency-check-report.html"
echo " - Native: target/*-runner"
CI/CD Integration(CI/CD 整合)
GitHub Actions 範例
name: Verification
on: [push, pull_request]
jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK 21
uses: actions/setup-java@v3
with:
java-version: '21'
distribution: 'temurin'
- name: Cache Maven packages
uses: actions/cache@v3
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
- name: Build
run: mvn clean verify -DskipTests
- name: Test with Coverage
run: mvn test jacoco:report jacoco:check
- name: Security Scan
run: mvn org.owasp:dependency-check-maven:check
- name: Upload Coverage
uses: codecov/codecov-action@v3
with:
files: target/site/jacoco/jacoco.xml
Best Practices(最佳實踐)
- 每次發布 PR 前均先執行一次完整的驗證流程
- 將驗證步驟整合至 CI/CD 流水線中實現自動化
- 發現問題立即修復,避免累積技術債
- 維持測試涵蓋率在 80% 以上
- 定期更新套件相依性
- 定期驗證原生編譯狀態
- 持續監控效能變化趨勢
- 詳細記錄破壞性變更(Breaking changes)
- 仔細審查資安掃描結果
- 為各個環境驗證並落實相應的組態設定






