Android

Ktlint × ReviewDogでPull Requestをレビューする

Katz

はじめに 

このドキュメントではKtlintとReviewDogを組み合わせて、Ktlintが生成した静的解析レポートをReviewDogでPull Requestのレビューコメントとして記載する方法を解説します。

前提知識

Ktlintとは?

KtlintはKotlinのコードスタイルをチェックするツールです。Kotlinのコードが一貫したスタイルガイドに従っているかをチェックし、場合によっては自動修正することもできます。Ktlintを使うことでコードの品質を向上させることができます。

ReviewDogとは?

ReviewDogはLinter(コード解析ツール)が生成した静的解析レポートをPull Requestのレビューコメントとして自動的に記載するツールです。ReviewDogを使用することで静的解析に基づいたレビューを自動化し、コードの品質改善を効率化できます。

前提条件

プロジェクトの構造

近年のAndroidアプリ開発では、マルチモジュール構成が一般的です。そのため、今回使用するデモプロジェクトには、applibraryの2つのモジュールを含めることにします。

実装手順

Ktlint(ktlint-gradle)のセットアップ

Ktlintはコマンドラインツールなのですが、そのまま利用するとなると少々手間がかかります。今回はセットアップを簡単にするためktlint-gradleを使用してKtlintを利用可能にします。

  1. pluginsセクションにktlint-gradleの依存関係を追加する
  2. allprojectsセクションでktlint-gradleを設定する
Kotlin
import org.jlleitschuh.gradle.ktlint.reporter.ReporterType

plugins {
    alias(libs.plugins.android.application) apply false
    alias(libs.plugins.kotlin.android) apply false
    alias(libs.plugins.kotlin.compose) apply false
    alias(libs.plugins.android.library) apply false
    id("org.jlleitschuh.gradle.ktlint") version "12.1.1" apply false
}

// appとlibraryの2つのモジュールでktlint-gradleを有効化する
allprojects {
    // ktlint-gradleのpluginを有効にする
    apply(plugin = "org.jlleitschuh.gradle.ktlint")
    configure<org.jlleitschuh.gradle.ktlint.KtlintExtension> {
        // Ktlintのバージョンを指定する
        version.set("1.3.1")
     
        // Ktlintの実行結果をPLAIN・CHECKSTYLE・SARIFで出力する
        reporters {
            reporter(ReporterType.PLAIN)
            reporter(ReporterType.CHECKSTYLE)
            reporter(ReporterType.SARIF)
        }
        
        // Ktlintを実行して、警告・エラーがあり失敗しても、無視するようにする
        ignoreFailures.set(true)

        // Ktlintを実行する際に自動生成されたコードは無視する、kotlinディレクトリにあるコードを対象にする
        filter {
            exclude("**/generated/**")
            include("**/kotlin/**")
        }
    }
}

Ktlint(ktlint-gradle)の動作チェック

ktlint-gradleには以下のGradleタスクが用意されており、これらのGradleタスクでKtlintによる静的解析やフォーマットを実行できます。

Gradleタスク名称内容
loadKtlintReportersKtLint Reporters を事前ロードします。
runKtlintCheckOverKotlinScriptsプロジェクトの Kotlin スクリプトファイルに対して実際のリントチェックを実行します。
ktlintKotlinScriptCheck 静的解析で見つかったエラーに基づいてレポートを生成し、Gradle コンソールに問題を出力します。このタスクの実行は、loadKtlintReporters と runKtlintCheckOverKotlinScripts のタスク実行結果に依存します。
runKtlintFormatOverKotlinScriptsプロジェクトの Kotlin スクリプトファイルをコードスタイルに従ってフォーマットしようとします。
ktlintKotlinScriptFormatフォーマットできないエラーに基づいてレポートを生成し、Gradle コンソールに問題を出力します。このタスクの実行は、loadKtlintReporters と runKtlintFormatOverKotlinScripts のタスク実行結果に依存します。
ktlintCheckすべての SourceSet およびプロジェクトの Kotlin スクリプトファイルをチェックします。
ktlintFormatすべての SourceSet の Kotlin ファイルおよびプロジェクトの Kotlin スクリプトファイルをコードスタイルに従ってフォーマットしようとします。

この中でも特に利用頻度が高いGradleタスクはktlintCheckktlintFormatになります。そのため下記のコマンドでktlintCheckktlintFormatのGradleタスクが正常に実行されるか動作をチェックしておきます。

ktlintCheckの動作チェック

  1. ./gradlew ktlintCheckを実行する
  2. タスクが成功すること、build/reports/ktlintに各種レポートの生成を確認する
Zsh
katz@macbookpro AndroidReviewdogDemo % ./gradlew ktlintCheck 

BUILD SUCCESSFUL in 2s
13 actionable tasks: 11 executed, 2 up-to-date

ktlintFormatの動作チェック

  1. ./gradlew ktlintFormatを実行する
  2. タスクが成功すること、build/reports/ktlintに各種レポートの生成を確認する
Zsh
BUILD SUCCESSFUL in 2s
13 actionable tasks: 11 executed, 2 up-to-date
katz@macbookpro AndroidReviewdogDemo % ./gradlew ktlintFormat

💡なぜktlint-gradleを利用するのか?

  • ktlint-gradleを利用しない場合には、Ktlintのコマンドをインストールして、Ktlintのコマンドを利用して静的解析レポートを出力します。またはKtlintによる自動フォーマットを実行する場合にも、Gradleタスクを自前で用意する必要があり少々実装が面倒です。
  • ktlint-gradleではよく使うユースケースのGradleタスクをあらかじめ定義してくれるのでKtlintの導入のハードルを下げることができます。またKtlintのバージョン設定やレポーター設定の変更も簡単にできるようになっており、利用することのメリットが大きいです。そのため今回はktlint-gradleを利用してセットアップを進めました。

ReviewDog(GitHub Action)のセットアップ

ReviewDogはコマンドラインツールですが、今回はGitHub Actionで動作させようと思います。なので以下のようなGitHub Actionのyamlファイルを作成して、Pull Requestが更新されたタイミングでReviewDogが動作させ、Ktlintの静的解析結果からレビューコメントを作成するようにします。

  1. actions/checkout@v4を利用し、CI環境上に最新のプロジェクトをチェックアウトする
  2. actions/setup-java@v4を利用し、CI環境上にJava環境をインストールする
  3. reviewdog/action-setup@v1を利用し、CI環境上にReviewDogをインストールする
  4. ktlint-gradlektlintCheckをKtlintを実行して静的解析レポートをsarifファイルとして出力する
  5. 生成したsarifファイルのパスを検索し、発見したsarifファイルをreviewdogに読み込む
YAML
name: Check pull request

on:
  pull_request

permissions:
  contents: write
  
jobs:
  check:
    runs-on: ubuntu-latest
    name: Check pull request
    permissions:
      pull-requests: write
    steps:
      # 1. 最新のプロジェクトをチェックアウトする
      - uses: actions/checkout@v4

      # 2. プロジェクトのビルドを実行するために必要なJava環境をセットアップする
      - uses: actions/setup-java@v4
        with:
          distribution: 'corretto'
          java-version: 17

      # 3. ReviewDogの公式が提供しているActionを利用して、ReviewDogをセットアップする
      - name: Setup reviewdog
        uses: reviewdog/action-setup@v1
        with:
          reviewdog_version: v0.18.0

      # 4. ktlint-gradleが提供するktlintCheckタスクを実行して、Ktlintの静的解析レポートを生成する
      - name: ktlint
        run: ./gradlew ktlintCheck

      # 5. Ktlintの静的解析レポートを検索して、順番にReviewDogに読み込ませて、Pull Requestコメントを生成する<strong>
      - name: Run reviewdog for Ktlint
        env:</strong>
          REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.REVIEW_DOG }}
        # Reporterにはgithub-pr-checkを利用する場合はこちら、Files Changedのレビューコメントが記載される
        run: |
          find . -regex '^.*/build/reports/ktlint/ktlintMainSourceSetCheck/ktlintMainSourceSetCheck.sarif' -type f | while read file_path; do
           cat "$file_path" | reviewdog -reporter=github-pr-check -f=sarif -fail-on-error
          done

💡 ReviewDogのレポーターの種類

  • Reviewdogではレポーターを指定することで、静的解析結果をどのような形式で表示するか指定することができます。
  • GitHub上で利用できるレポーターには以下の3つの種類がありますが、今回はgithub-pr-checkを利用してPull Requestのレビューコメントに静的解析結果を記載しています。
レポーターの種類内容
github-check基本的にはgithub-pr-checkと同じだが、Pull Requestだけでなくcommitでも動作する
github-pr-checkgithub-pr-checkレポーターはGitHub Checksに結果を報告する。
github-pr-reviewgithub-pr-review、GitHub Personal API Access Tokenを使ってGitHub PullRequestのレビューコメントに結果を報告する。

実行結果

Pull Requestを作成しGitHub Actionsのワークフローが動作すると、Ktlintが検出した警告・エラーをReviewDogにより自動でコメントします。

このようにReview Dogを利用するとKtlintの警告やエラーなどの問題がある箇所がレビュー時にわかるようになり品質向上が期待できます。こちらの動作確認にしたコードは以下に保存してありますので、詳しい内容は以下のコードを確認ください。

https://github.com/kaleidot725/AndroidReviewdogDemo

参考文献

ABOUT ME
Katz
Katz
Androidエンジニア
AndroidエンジニアをやっているKatzです。最近はKotlin Multiplatformを中心にやっています。経歴やお仕事の依頼については、私のプロフィールに詳細を記載していますので、ご確認ください。
記事URLをコピーしました