GitHub ActionsによるAndroidプロジェクトへのktlintとDangerの導入事例

# はじめに

メグリのAndroid開発チームでは、Pull Requestを作成した際にktlintでコードフォーマットをチェックし、Dangerによってチェック結果を反映するようにしています。
これまで実行環境にはBitriseを利用していましたが、一部処理をGitHub Actionsに移行したので、その内容と経緯をまとめておきます。

# 移行の背景

GitHub Actionsに移行した主な理由は以下の２つです。

- プロジェクト（GitHubリポジトリ）作成時の初期設定の容易さ
- コスト削減

ただし、すべてのワークフローをGitHub Actionsに移行したわけではなく、アプリのビルドや配布などは引き続きBitriseで実行しています。

##  プロジェクト（GitHubリポジトリ）作成時の初期設定の容易さ

メグリでは毎月のように新しいプロジェクトが作られ、その度に初期設定をしていますが、その一つにDangerとの連携作業があります。

GitHub ActionsはGitHubのエコシステム内で直接動作するため、Dangerとの連携が容易です。特にGitHubのPersonal Access Token (PAT) が不要な点は、セットアップ作業を簡略化し、セキュリティ管理も簡素化でき、メリットとなります。

## コスト削減

GitHub ActionsとBitriseではLinuxやMacOSのマシンを利用できますが、ktlintとDangerは分あたり料金が一番安いLinuxマシンで実行することができます。

分あたりの料金は、弊社の環境ではGitHub Actionが 0.008ドル、Bitriseはおおよそ0.04ドルとなっており、GitHub Actionsが1/5のコストです。
さらに、GitHub Actionsでは1ヶ月で3000分の無料枠（個人利用であれば2000分）があり、ktlintとDangerだけの利用であれば、ほぼ無料枠内で実行可能なので、この点でもコストメリットがありました。（※ 2024/01/25時点）

ただし、GitHub ActionsとBitriseで同じLinuxマシンでもマシンスペックが違うため、単純に分あたりのコストだけでは比較できない点に注意が必要です。
弊社のあるプロジェクトでは、1回のktlintとDangerの実行に、GitHub Actionsでは約4分、Bitriseでは約3分かかっていますが、トータルコストではGitHub Actionsが安価でした。

実行時間は1分ほど長くなりましたが、それほど大きな違いではなく、運用上も特に問題ありませんでした。

#### 参考： 検証したときの主なスペック

||GitHub Actions|Bitrise|
|---|---|---|
|Machine type|Standard GitHub-hosted runner/Linux|Standard/Linux|
|CPU|Xeon(R) 8370C CPU @ 2.80GHz|Xeon(R) CPU @ 3.10GHz|
|# CPU|2 vCPU|4 vCPU|
|Memory|7GB|16GB|


# 設定


AndroidプロジェクトにおいてGitHub ActionsでktlintとDangerを実行するための設定は、以下の手順で行いました。

## ktlintの設定

ktlintは、Kotlinコードのフォーマットをチェックするためのツールです。以下の設定は、プロジェクトのルートディレクトリにあるbuild.gradle.ktsファイルと、アプリモジュールのbuild.gradle.ktsファイルに追加します。

ルートのbuild.gradle.ktsには、ktlintのプラグインをプロジェクトに適用するための設定を記述します。


```build.gradle.kts
plugins {
    id("org.jlleitschuh.gradle.ktlint") version "12.1.0" apply false
}
```

アプリモジュールのbuild.gradle.ktsには、ktlintの具体的な設定を定義します。

```app/build.gradle.kts
import org.jlleitschuh.gradle.ktlint.reporter.ReporterType

plugins {
    id("org.jlleitschuh.gradle.ktlint")
}

ktlint {
    android = true
    outputToConsole = true
    verbose = true
    debug = true
    ignoreFailures = true
    reporters {
        reporter(ReporterType.CHECKSTYLE)
    }
}
```

## Dangerの設定

DangerはPull Requestに自動でコメントをつけることができるツールです。
以下のGemfileとDangerfileをプロジェクトに追加し、GitHub Actionsでの実行を設定します。

Gemfileでは、必要なDangerのgemを定義します。

```ruby:Gemfile
source "https://rubygems.org"

gem "danger", "9.3.2"
gem "danger-checkstyle_format"
```

なお、dangerのバージョン9.4.0以上を使用した際に、Pull Requestにインラインでコメントが表示されないことがあったため、ここでは9.3.2を明示的に指定しています。

![danger_ktlint_pr.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/361241/31dc57dc-4ed8-a690-839e-f3bae54296de.png)


Dangerfileには、DangerがPull Requestにコメントを付ける際の設定を記述します。
ここでは、ktlintによるチェック結果をコメントとして反映しています。

```ruby:Dangerfile
github.dismiss_out_of_range_messages

# ktlint
checkstyle_format.base_path = Dir.pwd
Dir["*/build/reports/ktlint/*/*.xml"].each do |file|
  checkstyle_format.report file
end
```

## GitHub ActionsでktlinとDangerを実行する設定

GitHub Actionsを利用してPull Requestが作成された際に自動的にktlintとDangerを実行するように、以下のワークフローを設定します。

```.github/workflows/danger.yml
name: Run Danger

on:
  pull_request:
    branches: [main, master]

jobs:
  ktlint:
    runs-on: ubuntu-latest
    if: github.event_name  == 'pull_request'
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-java@v3
        with:
          distribution: 'temurin'
          java-version: '17'
      - run: ./gradlew ktlintCheck
      - uses: ruby/setup-ruby@v1
        with:
          ruby-version: '3.2.2'
          bundler-cache: false
      - uses: MeilCli/danger-action@v5
        with:
          plugins_file: 'Gemfile'
          install_path: 'vendor/bundle'
          danger_file: 'Dangerfile'
          danger_id: 'danger-pr'
        env:
          DANGER_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          DANGER_VERBOSE: true
```


GitHub Actionsでチェック結果のコメントを反映させるためにはリポジトリで許可されている必要があります。
初期設定では許可されてない場合があるので、その場合は `Actions > General > Workflow permissions` から、`Allow GitHub Actions to create and approve pull requests` をチェックします。

![screenshot_workflow_permissions.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/361241/f611c52b-4656-8a18-8aa2-f80847c6c5f2.png)


# おわりに

この記事では、GitHub Actionsに移行した背景と、ktlintおよびDangerの実行に関する具体的な設定方法をご紹介しました。
記事内に記載した内容を以下で公開しているので、よければご参照ください。
https://github.com/lanches-tanabe/ktlint_android_example


# お知らせ（採用情報）

メグリでは、こうした開発環境の改善や自動化、生成AIの活用に興味があるエンジニアを募集しています。
GitHub Actionsを始めとする最新技術を活用した効率的な開発環境の構築に加えて、モバイルアプリ開発、サーバサイド開発に興味がある方はぜひ以下のページをご覧ください。

https://mgre.co.jp/careers

カジュアル面談も随時実施していますので、お気軽にお問い合わせください。