Checkstyle と reviewdog を使って Java の PR を自動でレビューする

# 目的

この記事では、 Checkstyle, reviewdog, GitHub Actions を使って Java の PR を自動でレビューすることを目指します。

```plantuml
@startuml
actor Developer
participant GitHub
participant "GitHub Actions" as Actions
participant Checkstyle
participant reviewdog

Developer->GitHub: Push or create PR
GitHub->Actions: Trigger workflow
Actions->Checkstyle: Run Checkstyle
Checkstyle-->Actions: Return results
Actions->reviewdog: Pass Checkstyle results
reviewdog->GitHub: Post comments on PR
GitHub-->Developer: Display comments
@enduml
```

# 環境

- Java 17
- Spring Boot 3.2.0
- Checkstyle 10.12.6
- reviewdog 0.15

# 設定手順

## Checkstyle を設定する

### Plugin に追加する

checkstyle を plugin に追加します。

```diff:build.gradle

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.2.0'
    id 'io.spring.dependency-management' version '1.1.4'
+    id 'checkstyle'
}

+ checkstyle {
+     toolVersion = '10.12.6'
+ }

```

### 設定ファイルを配置する

Checkstyle の設定ファイルは、 Google と Sun のものが GitHub に存在しています。
今回は Google の設定ファイルを使用します。

https://github.com/checkstyle/checkstyle/blob/master/src/main/resources/google_checks.xml

plugin がデフォルトで読み込む設定ファイル名は `./config/checkstyle/checkstyle.xml` なので、同名で保存します。
もし別の名前を使用したい場合は configFile で指定できます。

```diff:build.gradle
checkstyle {
    toolVersion = '10.12.6'
+     configFile = "./config/checkstyle/google_checks.xml"
}
```

### Checkstyle を実行する（失敗）

Checkstyle を実行しようすると、ビルド段階でエラーが発生しました。

```console
./gradlew build

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':checkstyleMain'.
> Could not resolve all files for configuration ':checkstyle'.
   > Could not resolve com.google.guava:guava:32.1.3-jre.
     Required by:
         project : > com.puppycrawl.tools:checkstyle:10.12.6
      > Module 'com.google.guava:guava' has been rejected:
           Cannot select module with conflict on capability 'com.google.collections:google-collections:32.1.3-jre' also provided by [com.google.collections:google-collections:1.0(runtime)]
   > Could not resolve com.google.collections:google-collections:1.0.
     Required by:
         project : > com.puppycrawl.tools:checkstyle:10.12.6 > org.apache.maven.doxia:doxia-core:1.12.0 > org.codehaus.plexus:plexus-container-default:2.1.0
      > Module 'com.google.collections:google-collections' has been rejected:
           Cannot select module with conflict on capability 'com.google.collections:google-collections:1.0' also provided by [com.google.guava:guava:32.1.3-jre(jreRuntimeElements)]
```

com.google.guava:guava が競合しているようなのでこれを解決します。

### guava の競合を解決する

guava のリリースノートに解決方法が記載されていました。

https://github.com/google/guava/releases/tag/v32.1.0#:~:text=Reporting%20dependencies%20that%20overlap%20with%20Guava

```diff:build.gradle
+ configurations.checkstyle {
+     resolutionStrategy.capabilitiesResolution.withCapability("com.google.collections:google-collections") {
+         select("com.google.guava:guava:0")
+     }
+ }
```

### Checkstyle を実行する（成功）

改めてビルドすると今度は成功しました。
Checkstyle を実行すると、結果が `build/reports/checkstyle` に HTML と XML で出力されます。

```console
./gradlew check
[ant:checkstyle] [WARN] ./checkstyle-reviewdog-sample/src/test/java/com/example/checkstylereviewdogsample/CheckstyleReviewdogSampleApplicationTests.java:9:5: 'method def modifier' のインデントレベル 4 は正しくありません。期待されるレベルは 2 です。 [Indentation]
[ant:checkstyle] [WARN] ./checkstyle-reviewdog-sample/src/test/java/com/example/checkstylereviewdogsample/CheckstyleReviewdogSampleApplicationTests.java:11:5: 'method def rcurly' のインデントレベル 4 は正しくありません。期待されるレベルは 2 です。 [Indentation]
[ant:checkstyle] [WARN] ./checkstyle-reviewdog-sample/src/main/java/com/example/checkstylereviewdogsample/CheckstyleReviewdogSampleApplication.java:6:1: Javadoc コメントがありません。 [MissingJavadocType]
[ant:checkstyle] [WARN] ./checkstyle-reviewdog-sample/src/main/java/com/example/checkstylereviewdogsample/CheckstyleReviewdogSampleApplication.java:9:5: 'method def modifier' のインデントレベル 4 は正しくありません。期待されるレベルは 2 です。 [Indentation]
[ant:checkstyle] [WARN] ./checkstyle-reviewdog-sample/src/main/java/com/example/checkstylereviewdogsample/CheckstyleReviewdogSampleApplication.java:10:9: 'method def' の子のインデントレベル 8 は正しくありません。期待されるレベルは 4 です。 [Indentation]
[ant:checkstyle] [WARN] ./checkstyle-reviewdog-sample/src/main/java/com/example/checkstylereviewdogsample/CheckstyleReviewdogSampleApplication.java:11:5: 'method def rcurly' のインデントレベル 4 は正しくありません。期待されるレベルは 2 です。 [Indentation]

ls build/reports/checkstyle 
main.html       main.xml        test.html       test.xml

```

## reviewdog を設定する

### GitHub Actions を設定する

reviewdog を GitHub Actions で実行する workflow を作成します。

```yaml:.github/workflows/reviewdog.yml
name: reviewdog
on: [pull_request]

jobs:
  checkstyle:
    name: Checkstyle with reviewdog
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write

    steps:
      - name: Check out
        uses: actions/checkout@v4

      - name: Setup Java
        uses: actions/setup-java@v4
        with:
          distribution: 'temurin'
          java-version: '17'

      - name: Run Checkstyle
        run: ./gradlew check

      - name: Setup reviewdog
        uses: reviewdog/action-setup@v1
        with:
          reviewdog_version: latest

      - name: Run reviewdog for main
        env:
          REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: cat ./build/reports/checkstyle/main.xml |
          reviewdog -f=checkstyle -name="checkstyle" -reporter="github-pr-review"

      - name: Run reviewdog for test
        env:
          REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: cat ./build/reports/checkstyle/test.xml |
          reviewdog -f=checkstyle -name="checkstyle" -reporter="github-pr-review"
```

# 動作確認

適当な PR を作成して動作を確認します。

```java:SampleUtils.java
package com.example.checkstylereviewdogsample.utils;

public class SampleUtils {
    public static String getHelloWorld() {
        return "Hello World";
    }
}
```

この ファイルを commit して PR を作成すると、無事 reviewdog の自動レビューが実行されました。

![github.com_yk-mura_reviewdog-test_pull_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148751/58a07afe-d000-93be-d219-ef8e4ba037f4.png)

レビュー内容は Checkstyle の設定ファイルによりますので、適宜変更しましょう。