コード品質テスト code-quality-testing
パイプラインのコード品質テストの仕組みと、デプロイメントの品質を向上させる方法について説明します。
はじめに introduction
コード品質テストは、一連の品質ルールに基づいてアプリケーションコードを評価します。これはコード品質のみのパイプラインの主な目的であり、実稼動および非実稼動のすべてのパイプラインで、ビルド手順の直後に実行されます。
様々なタイプのパイプラインの詳細については、CI/CD パイプラインの設定を参照してください。
コード品質ルール understanding-code-quality-rules
コード品質テストでは、ソースコードをスキャンし、一定の品質基準を満たしていることを確認します。これは SonarQube と、OakPAL を使用したコンテンツパッケージレベルの調査を組み合わせて実装されています。汎用の Java ルールと AEM 固有のルールを組み合わせたルールは 100 以上あります。AEM 固有のルールの一部は、AEM エンジニアリングのベストプラクティスに基づいて作成され、カスタムコード品質ルールと呼ばれます。
3 層評価 three-tiered-gate
コード品質テストによって特定された問題は、3 つのカテゴリーのいずれかに分類されます。
-
重大 - パイプラインの即時失敗を引き起こす問題です。
-
重要 - パイプラインの一時停止状態を引き起こす問題です。デプロイメントマネージャー、プロジェクトマネージャーまたはビジネスオーナーは、問題をオーバーライドできます。この場合、パイプラインは続行されます。または、問題を承認できます。この場合、パイプラインはエラーで停止します。
-
情報 - 情報提供だけを目的とした問題です。パイプラインの実行には影響しません。
評価 ratings
この手順の結果は、評価 として提供されます。
次の表に、重大、重要、情報の各カテゴリの評価と失敗のしきい値を示します。
B = 軽度の脆弱性が 1 つ以上
C = 重要な脆弱性が 1 つ以上
D = 重大な脆弱性が 1 つ以上
E = 致命的な脆弱性が 1 つ以上
B = 軽度のバグが 1 つ以上
C = 重要なバグが 1 つ以上
D = 重大なバグが 1 つ以上
E = 致命的なバグが 1 つ以上
コードスメルの未処理の修正コストによって、アプリケーションに既に投入された時間の割合として定義されます。
- A = <=5%
- B = 6~10%
- C = 11~20%
- D = 21~50%
- E = >50%
次の式を使用して、単体テストラインのカバレッジと条件のカバレッジを組み合わせて定義します。Coverage = (CT + CF + LC)/(2*B + EL)
CT
= 単体テストの実行中に少なくとも 1 回はtrue
と評価された条件CF
= 単体テストの実行中に少なくとも 1 回はfalse
と評価された条件LC
= 被覆線 = lines_to_cover - uncovered_linesB
= 条件の合計数EL
= 実行可能な行の総数 (lines_to_cover)
重複したブロックに含まれる行の数として定義されます。コードブロックは、次の条件下で重複していると見なされます。
Java 以外のプロジェクト:
- 100 個以上の連続した重複トークンが必要です。
- これらのトークンは、少なくとも次の場所に分散している必要があります。
- 30 行の COBOL コード
- 20 行の ABAP コード
- 10 行の他言語コード
Java プロジェクト:
- トークンと行の数にかかわらず、10 個以上の連続した重複ステートメントが必要です。
重複を検出する際は、インデントの違いと文字列リテラルの違いは無視されます。
偽陽性の処理 dealing-with-false-positives
品質スキャンプロセスは完璧ではなく、実際には問題がないにもかかわらず問題として誤って特定することもあります。これは「偽陽性」と呼ばれます。
この場合、ルール ID を注釈属性として指定した標準の Java @SuppressWarnings
注釈を使用して、ソースコードに注釈を付けることができます。例えば、よくある問題の 1 つとして、ハードコードされたパスワードを検出する SonarQube ルールにおいて、ハードコードされたパスワードの識別方法が強引な場合があります。
次のコードは、AEM プロジェクトではかなり一般的です。AEM プロジェクトには、一部の外部サービスに接続するコードが含まれています。
@Property(label = "Service Password")
private static final String PROP_SERVICE_PASSWORD = "password";
この場合、SonarQube は致命的脆弱性を報告します。コードを見直した後、これが脆弱性でないことを確認し、適切なルール ID でこれに注釈を付けることができます。
@SuppressWarnings("squid:S2068")
@Property(label = "Service Password")
private static final String PROP_SERVICE_PASSWORD = "password";
ただし、コードが実際には次のような場合は、
@Property(label = "Service Password", value = "mysecretpassword")
private static final String PROP_SERVICE_PASSWORD = "password";
ハードコードされたパスワードを削除するのが正しい解決策です。
@SuppressWarnings
注釈をできるだけ具体的なものにする(問題の原因となっている特定のステートメントやブロックにのみ注釈を付ける)ことをお勧めしますが、クラスレベルで注釈を付けることもできます。コンテンツパッケージスキャンの最適化 content-package-scanning-optimization
Cloud Manager は、品質分析プロセスの一環として、Maven ビルドで生成されたコンテンツパッケージの分析を実行します。Cloud Manager は、このプロセスを高速化するための最適化を提供します。この最適化は、特定のパッケージ化の制約が観察された場合に有効です。最も重要なのは、単一のコンテンツパッケージ(一般的に「すべて」のパッケージと呼ばれます)を出力するプロジェクトで実行される最適化です。このパッケージには、ビルドで作成された他のいくつかのコンテンツパッケージが含まれ、スキップ済みとしてマークされます。Cloud Manager がこのシナリオを検出すると、「すべて」のパッケージを展開するのではなく、個々のコンテンツパッケージを直接スキャンし、依存関係に基づいて並べ替えます。例えば、次のビルド出力について考えてみましょう。
all/myco-all-1.0.0-SNAPSHOT.zip
(コンテンツパッケージ)ui.apps/myco-ui.apps-1.0.0-SNAPSHOT.zip
(スキップされたコンテンツパッケージ)ui.content/myco-ui.content-1.0.0-SNAPSHOT.zip
(スキップされたコンテンツパッケージ)
myco-all-1.0.0-SNAPSHOT.zip
内の唯一のアイテムがスキップされた 2 つのコンテンツパッケージである場合、「すべて」のコンテンツパッケージの代わりに 2 つの埋め込みパッケージがスキャンされます。
数十の埋め込みパッケージを生成するプロジェクトの場合、この最適化により、パイプライン実行あたり 10 分以上の時間を節約できることが示されています。
「すべて」のコンテンツパッケージに、スキップされたコンテンツパッケージと OSGi バンドルの組み合わせが含まれている場合は、特殊なケースが発生する場合があります。例えば、myco-all-1.0.0-SNAPSHOT.zip
に前述の 2 つの埋め込みパッケージと 1 つ以上の OSGi バンドルが含まれている場合、新しい最小限のコンテンツパッケージは OSGi バンドルのみで構築されます。このパッケージは常に cloudmanager-synthetic-jar-package
という名前で、含まれているバンドルは /apps/cloudmanager-synthetic-installer/install
に配置されます。
- この最適化は、AEM にデプロイされるパッケージには影響しません。
- 埋め込みコンテンツパッケージとスキップされたコンテンツパッケージの照合はファイル名に基づくので、複数のスキップされたコンテンツパッケージのファイル名が完全に同じである場合や、埋め込み中にファイル名が変更された場合は、この最適化を実行できません。