Reviewdogを飼ってみた

# Reviewdogとは

Reviewdogは、コードレビューツールの1つで、CI (Continuous Integration) またはローカル環境でのコードの変更を自動的にレビューするためのものです。
Reviewdogは、各種linterと統合することが可能で、それらの出力をパースし、結果を表示することが可能です。
このツールは、GitHubなどのプラットフォームに対応しています。また、Reviewdogは、プルリクエストの差分に対してのみフィードバックが可能でプルリクエストに対して直接コメントを付けることが可能になります。
基本的にはlinterと組み合わせて使用されるかと思いますが、今回はlinterを使用せずGithub ActionsでReviewdogとkotlinを使用し独自のチェックを行うようにしてみます。
https://github.com/reviewdog/reviewdog

# Github Actionsのworkflow作成

```yaml
name: Reviewdog

permissions:
  contents: read

on:
  pull_request:
    branches:
      - main # プルリクエストのマージ対象がmainの場合実施されます。

jobs:
  review:
    runs-on: ubuntu-latest
    steps:
      - name: check out
        uses: actions/checkout@v2
        with:
          ref: ${{ github.event.pull_request.head.ref }}
          fetch-depth: 0

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

      - name: set up jdk 1.8
        uses: actions/setup-java@v1
        with:
          java-version: 1.8

      - name: run reviewdog
        env:
          CI_PULL_REQUEST: ${{ github.event.pull_request.number }}
          CI_COMMIT: ${{ github.sha }}
          CI_REPO_OWNER: ${{ github.repository_owner }}
          CI_REPO_NAME: ${{ github.event.repository.name }}
          CI_BRANCH: ${{ github.head_ref }}
          REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.REVIEWDOG_TOKEN }}
        run: |
          kotlinc -script ./reviewdog/Main.kts
          cat ./result.txt | reviewdog -name="test" -efm="%f:%l:%c:%m" -reporter=github-pr-review

```

**`setup reviewdog`**：**`reviewdog/action-setup@v1`** アクションを使用して、reviewdog をセットアップします。

**`set up jdk 1.8`**：**`actions/setup-java@v1`** アクションを使用して、JDK 1.8 をセットアップします。これにより、次のステップで Kotlin スクリプトを実行するための Java 環境が準備されます。

**`run reviewdog`**：環境変数を設定した後、Kotlin スクリプトを実行し、その結果を reviewdog に渡しています。

- reviewdogの環境変数について
1. **`CI_PULL_REQUEST`**: GitHub Actionsのコンテキストからプルリクエストの番号を取得します。これは現在処理しているプルリクエストのIDとなります。
2. **`CI_COMMIT`**: GitHub ActionsのコンテキストからコミットのSHAを取得します。これは現在のコミットのSHA（コミットハッシュ）となります。
3. **`CI_REPO_OWNER`**: GitHub Actionsのコンテキストからリポジトリの所有者の名前を取得します。
4. **`CI_REPO_NAME`**: GitHub Actionsのコンテキストからリポジトリの名前を取得します。
5. **`CI_BRANCH`**: GitHub Actionsのコンテキストからブランチ名を取得します。これはプルリクエストのソースブランチ名となります。
6. **`REVIEWDOG_GITHUB_API_TOKEN`**: レポジトリのシークレットから**`REVIEWDOG_TOKEN`**を取得します。これはReviewdogがGitHub APIを利用するために必要な認証トークンです。

# 独自解析の実装

```kotlin
import java.io.File

fun main() {
    val targetDirectory = File("./test")
    val report = File("./result.txt")
    report.createNewFile()
    val keyword = "TODO"

    targetDirectory
        .walk() // フォルダ内の全ファイルとディレクトリを走査します
        .filter { it.isFile } // ファイルだけを対象とします
        .forEach { file ->
            // ファイルの各行を走査します
            file.readLines().forEachIndexed { index, line ->
                // 特定のキーワードが含まれている行を出力します
                if (line.contains(keyword)) {
                    report.appendText("${file.path}:${index + 1}:1: TODO found \n")
                }
            }
        }
}

main()
```

指定したディレクトリ（この場合は **`./test`** ディレクトリ）内の全てのファイルを走査し、特定のキーワード（この場合は **`TODO`**）を含む行が存在するファイルを見つけ出します。
見つけた結果は **`./result.txt`** ファイルに書き出されます。
**`./result.txt`** ファイルに書き出されたメッセージはreviewdogに渡されます。

# Reviewdogが吠える

実際に差分に`TODO` が含まれる場合以下のようにプルリクエストにReviewdogからコメントされます。
犬のアイコンがかわいいですね！

![スクリーンショット 2023-07-25 23.51.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3330132/8f19c5b1-b54a-b03e-b404-58fd43fcf4e1.png)

# まとめ

GitHub Actions で reviewdog を飼って独自解析する方法についてご紹介しました。
linterではチェックできないものがあれば独自の解析を実装してみるのもいいかと思いました。
簡単なチェック項目であれば実装も難しくないので色々と活用方法がありそうです。