mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-06-14 12:11:27 +08:00
315 lines
8.4 KiB
Markdown
315 lines
8.4 KiB
Markdown
---
|
||
name: quarkus-verification
|
||
description: "Quarkusプロジェクトの検証ループ: ビルド、静的解析、カバレッジ付きテスト、セキュリティスキャン、ネイティブコンパイル、リリースまたはPR前のdiffレビュー。"
|
||
origin: ECC
|
||
---
|
||
|
||
# Quarkus 検証ループ
|
||
|
||
PR前、大きな変更後、デプロイ前に実行。
|
||
|
||
## いつアクティブにするか
|
||
|
||
- Quarkusサービスのプルリクエストを開く前
|
||
- 大規模なリファクタリングまたは依存関係アップグレード後
|
||
- ステージングまたは本番のデプロイ前検証
|
||
- 完全なビルド → lint → テスト → セキュリティスキャン → ネイティブコンパイルパイプラインの実行
|
||
- テストカバレッジが閾値を満たしていることの検証(80%以上)
|
||
- ネイティブイメージ互換性のテスト
|
||
|
||
## フェーズ1: ビルド
|
||
|
||
```bash
|
||
# Maven
|
||
mvn clean verify -DskipTests
|
||
|
||
# Gradle
|
||
./gradlew clean assemble -x test
|
||
```
|
||
|
||
ビルドが失敗した場合、停止してコンパイルエラーを修正。
|
||
|
||
## フェーズ2: 静的解析
|
||
|
||
### Checkstyle、PMD、SpotBugs(Maven)
|
||
|
||
```bash
|
||
mvn checkstyle:check pmd:check spotbugs:check
|
||
```
|
||
|
||
### SonarQube(構成されている場合)
|
||
|
||
```bash
|
||
mvn sonar:sonar \
|
||
-Dsonar.projectKey=my-quarkus-project \
|
||
-Dsonar.host.url=http://localhost:9000 \
|
||
-Dsonar.login=${SONAR_TOKEN}
|
||
```
|
||
|
||
### 対処すべき一般的な問題
|
||
|
||
- 未使用のimportまたは変数
|
||
- 複雑なメソッド(高い循環的複雑度)
|
||
- 潜在的なnullポインター参照
|
||
- SpotBugsが検出したセキュリティ問題
|
||
|
||
## フェーズ3: テスト + カバレッジ
|
||
|
||
```bash
|
||
# すべてのテストを実行
|
||
mvn clean test
|
||
|
||
# カバレッジレポートを生成
|
||
mvn jacoco:report
|
||
|
||
# カバレッジ閾値を強制(80%)
|
||
mvn jacoco:check
|
||
|
||
# またはGradleで
|
||
./gradlew test jacocoTestReport jacocoTestCoverageVerification
|
||
```
|
||
|
||
### テストカテゴリ
|
||
|
||
#### ユニットテスト
|
||
モック化された依存関係でサービスロジックをテスト:
|
||
|
||
```java
|
||
@ExtendWith(MockitoExtension.class)
|
||
class UserServiceTest {
|
||
@Mock UserRepository userRepository;
|
||
@InjectMocks UserService userService;
|
||
|
||
@Test
|
||
void createUser_validInput_returnsUser() {
|
||
var dto = new CreateUserDto("Alice", "alice@example.com");
|
||
var expected = new User();
|
||
expected.id = 1L;
|
||
expected.name = dto.name();
|
||
|
||
when(userRepository.persist(any(User.class))).thenReturn(expected);
|
||
|
||
User result = userService.create(dto);
|
||
|
||
assertThat(result.name).isEqualTo("Alice");
|
||
verify(userRepository).persist(any(User.class));
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 統合テスト
|
||
実データベース(Testcontainers)でテスト:
|
||
|
||
```java
|
||
@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テスト
|
||
REST AssuredでRESTエンドポイントをテスト:
|
||
|
||
```java
|
||
@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`を確認:
|
||
- 全体行カバレッジ(目標: 80%以上)
|
||
- ブランチカバレッジ(目標: 70%以上)
|
||
- カバーされていない重要パスを特定
|
||
|
||
## フェーズ4: セキュリティスキャン
|
||
|
||
### 依存関係脆弱性(Maven)
|
||
|
||
```bash
|
||
mvn org.owasp:dependency-check-maven:check
|
||
```
|
||
|
||
CVEについて`target/dependency-check-report.html`を確認。
|
||
|
||
### Quarkusセキュリティ監査
|
||
|
||
```bash
|
||
# 脆弱なエクステンションを確認
|
||
mvn quarkus:audit
|
||
|
||
# すべてのエクステンションをリスト
|
||
mvn quarkus:list-extensions
|
||
```
|
||
|
||
### 一般的なセキュリティチェック
|
||
|
||
- [ ] すべてのシークレットが環境変数に(コード内ではなく)
|
||
- [ ] すべてのエンドポイントで入力バリデーション
|
||
- [ ] 認証/認可が構成済み
|
||
- [ ] CORSが適切に構成済み
|
||
- [ ] セキュリティヘッダーが設定済み
|
||
- [ ] パスワードがBCryptでハッシュ済み
|
||
- [ ] SQLインジェクション保護(パラメータ化クエリ)
|
||
- [ ] パブリックエンドポイントでレート制限
|
||
|
||
## フェーズ5: ネイティブコンパイル
|
||
|
||
GraalVMネイティブイメージ互換性をテスト:
|
||
|
||
```bash
|
||
# ネイティブ実行可能ファイルをビルド
|
||
mvn package -Dnative
|
||
|
||
# またはコンテナで
|
||
mvn package -Dnative -Dquarkus.native.container-build=true
|
||
|
||
# ネイティブ実行可能ファイルをテスト
|
||
./target/*-runner
|
||
|
||
# 基本的なスモークテストを実行
|
||
curl http://localhost:8080/q/health/live
|
||
curl http://localhost:8080/q/health/ready
|
||
```
|
||
|
||
### ネイティブイメージトラブルシューティング
|
||
|
||
一般的な問題:
|
||
- **Reflection**: 動的クラス用のreflection構成を追加
|
||
- **Resources**: `quarkus.native.resources.includes`でリソースを含める
|
||
- **JNI**: ネイティブライブラリ使用時にJNIクラスを登録
|
||
|
||
例のreflection構成:
|
||
```java
|
||
@RegisterForReflection(targets = {MyDynamicClass.class})
|
||
public class ReflectionConfiguration {}
|
||
```
|
||
|
||
## フェーズ6: ヘルスチェック
|
||
|
||
```bash
|
||
# 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
|
||
```
|
||
|
||
## 検証チェックリスト
|
||
|
||
### コード品質
|
||
- [ ] ビルドが警告なしで通過
|
||
- [ ] 静的解析クリーン(高/中の問題なし)
|
||
- [ ] コードがチーム規約に従う
|
||
- [ ] PRにコメントアウトされたコードやTODOがない
|
||
|
||
### テスト
|
||
- [ ] すべてのテストが通過
|
||
- [ ] コードカバレッジ ≥ 80%
|
||
- [ ] 実データベースとの統合テスト
|
||
- [ ] セキュリティテストが通過
|
||
- [ ] パフォーマンスが許容範囲内
|
||
|
||
### セキュリティ
|
||
- [ ] 依存関係脆弱性なし
|
||
- [ ] 認証/認可がテスト済み
|
||
- [ ] 入力バリデーション完了
|
||
- [ ] ソースコードにシークレットなし
|
||
- [ ] セキュリティヘッダーが構成済み
|
||
|
||
### デプロイメント
|
||
- [ ] ネイティブコンパイル成功
|
||
- [ ] コンテナイメージがビルド可能
|
||
- [ ] ヘルスチェックが正しく応答
|
||
- [ ] ターゲット環境で構成が有効
|
||
|
||
## 自動検証スクリプト
|
||
|
||
```bash
|
||
#!/bin/bash
|
||
set -e
|
||
|
||
echo "=== フェーズ1: ビルド ==="
|
||
mvn clean verify -DskipTests
|
||
|
||
echo "=== フェーズ2: 静的解析 ==="
|
||
mvn checkstyle:check pmd:check spotbugs:check
|
||
|
||
echo "=== フェーズ3: テスト + カバレッジ ==="
|
||
mvn test jacoco:report jacoco:check
|
||
|
||
echo "=== フェーズ4: セキュリティスキャン ==="
|
||
mvn org.owasp:dependency-check-maven:check
|
||
|
||
echo "=== フェーズ5: ネイティブコンパイル ==="
|
||
mvn package -Dnative -Dquarkus.native.container-build=true
|
||
|
||
echo "=== 全フェーズ完了 ==="
|
||
echo "レポートを確認:"
|
||
echo " - カバレッジ: target/site/jacoco/index.html"
|
||
echo " - セキュリティ: target/dependency-check-report.html"
|
||
echo " - ネイティブ: target/*-runner"
|
||
```
|
||
|
||
## ベストプラクティス
|
||
|
||
- すべてのPR前に検証ループを実行
|
||
- CI/CDパイプラインで自動化
|
||
- 問題を即座に修正し、技術的負債を蓄積しない
|
||
- カバレッジを80%以上に維持
|
||
- 依存関係を定期的に更新
|
||
- ネイティブコンパイルを定期的にテスト
|
||
- パフォーマンストレンドを監視
|
||
- 破壊的変更を文書化
|
||
- セキュリティスキャン結果をレビュー
|
||
- 各環境の構成を検証
|