はじめに
GitHub Actionsを使い、Androidアプリのビルドと単体テスト、静的解析を行うCIを構築します。
本記事で書かないこと
- GitHub Actionsの概要や基本的な操作方法
私が以前書いた記事 が参考になると思います
設定ファイルの紹介
設定ファイルの内容を上から順に紹介します。
name
ワークフローの名前を設定します。
私は単純に「CI」としています。
name: CI
on
ワークフローを実行するトリガーを設定します。
私はGit-flowモデルで開発しており、以下のように設定しています。
on:
push:
branches:
- main
- develop
paths-ignore:
- docs/**
- README.md
- LICENSE
pull_request:
branches:
- develop
paths-ignore:
- docs/**
- README.md
- LICENSE
他の人からPull request(以下、「PR」と呼ぶ)を頂いたときにもCIが動くように、 develop
ブランチへのPRをトリガーにしています。
PRのマージ時にもCIが動くように、 develop
と main
ブランチへのプッシュもトリガーにしています。
feature/**
ブランチへのプッシュをトリガーにしていない理由は、 develop
ブランチへPRを出したときにCIが二重に動作するのを防ぐためです。
早めにCIを動かしたい場合、「WIP:」を付けてPRを出します(GitHubではドラフト機能があるので、それを使うのもありです)。
README.md
や LICENSE
など、Androidアプリに直接関係ないファイルは、単体でコミットしてもCIが動かないようにしています。
( README.md
のみ更新してプッシュしてもCIが動くような気がします…。私の設定が誤っているのでしょうか?)
jobs
今回はジョブを4つ用意して並行に実行しているので、順に紹介します。
build
ビルドを実行するジョブです。
基本的には『Androidテスト全書』を参考にしてGradleタスクを実行しているだけなので、詳細は省略します。
Gradleのキャッシュは、READMEの例をそのままコピペしています。
https://github.com/actions/cache/blob/master/examples.md#java---gradle
jobs:
build:
runs-on: ubuntu-latest
steps:
# チェックアウト
- uses: actions/checkout@v2
# JDKのセットアップ
- name: set up JDK 11
uses: actions/setup-java@v2
with:
distribution: 'zulu'
java-version: '11'
# Gradleのキャッシュ復元
- uses: actions/cache@v2
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
restore-keys: |
${{ runner.os }}-gradle-
# 依存関係の出力
- name: Displays the Android dependencies of the project
run: ./gradlew androidDependencies
# コンパイル
- name: Run Compile
run: ./gradlew assembleDebug
注意
- JDKは11を使用している
- 8を使いたい場合は
8
を指定する
- 8を使いたい場合は
test
単体テストを実行するジョブです。
build
ジョブと同様、詳細は省略します。
jobs:
test:
runs-on: ubuntu-latest
steps:
# チェックアウト
- uses: actions/checkout@v2
# JDKのセットアップ
- name: set up JDK 11
uses: actions/setup-java@v2
with:
distribution: 'zulu'
java-version: '11'
# Gradleのキャッシュ復元
- uses: actions/cache@v2
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
restore-keys: |
${{ runner.os }}-gradle-
# テスト
- name: Test with Gradle
run: ./gradlew test --stacktrace
# コードカバレッジをJaCoCo形式で取得
- name: Get code coverage for JaCoCo
run: ./gradlew jacocoDebugTestReport
# コードカバレッジをCodecovへアップロード
- name: Upload code coverage to Codecov
run: bash <(curl -s https://codecov.io/bash)
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
# テスト結果とコードカバレッジのアップロード
- name: Upload test results and code coverage Artifact
uses: actions/upload-artifact@v2
if: success() || failure()
with:
name: results
path: |
**/build/reports/tests/**/*
**/build/reports/test-results/**/*
**/build/reports/jacoco/**/*
if-no-files-found: warn
retention-days: 14
注意
-
jacocoDebugTestReport
タスクは自作- JaCoCoは別記事で説明する予定
- CodeCovを使う場合は
CODECOV_TOKEN
をシークレットに追加する- CodeCovも別記事で説明する予定
- テスト結果は成否にかかわらず確認したいため、アーティファクトのアップロードステップで
if: success() || failure()
を指定している
lint
Android Lintを使って静的解析するジョブです。
./gradlew lint
を実行して結果をアップロードしているだけなので、詳細は省略します。
jobs:
lint:
runs-on: ubuntu-latest
steps:
# チェックアウト
- uses: actions/checkout@v2
# 静的解析
- name: Run Inspection
run: ./gradlew lint
# 結果の表示
- name: Show results on GitHub
uses: yutailang0119/action-android-lint@v1
with:
xml_path: '**/build/reports/lint-results-*.xml'
# アーティファクトへアップロード
- name: Upload results Artifact
uses: actions/upload-artifact@v2
if: success() || failure()
with:
name: results
path: |
**/build/reports/lint-results-*.html
**/build/reports/lint-results-*.xml
if-no-files-found: error
retention-days: 14
注意
- 結果のファイル名は
lint-results.*
からlint-results-{Build variant}.*
に変更された- おそらくGradle 7から
-
yutailang0119/action-android-lint
アクションでGitHub上のファイルに指摘を表示している
detekt
detekt を使って静的解析するジョブです。
./gradlew detekt
を実行して結果をアップロードしているだけなので、詳細は省略します。
jobs:
detekt:
runs-on: ubuntu-latest
steps:
# チェックアウト
- uses: actions/checkout@v2
# 静的解析
- name: Lint with detekt
run: ./gradlew detekt
# アーティファクトへアップロード
- name: Upload results Artifact
uses: actions/upload-artifact@v2
if: failure()
with:
name: results
path: |
**/build/reports/detekt/**/*
if-no-files-found: error
retention-days: 14
Android Lintにはない観点で静的解析するため、両方とも使うのがオススメです。
ktlint
ktlint を使って静的解析するジョブです。
ktlint
を実行して結果をアップロードしているだけなので、詳細は省略します。
jobs:
ktlint:
runs-on: ubuntu-latest
steps:
# チェックアウト
- uses: actions/checkout@v2
# インストール
- name: Install ktlint
run: |
curl -sSLO https://github.com/pinterest/ktlint/releases/download/0.42.1/ktlint
chmod a+x ktlint
sudo mv ktlint /usr/local/bin/
# 静的解析
- name: Lint with ktlint
run: ktlint --reporter=checkstyle,output=build/ktlint-report.xml
continue-on-error: true
# 結果の表示
- name: Show results on GitHub
uses: yutailang0119/action-ktlint@v1
with:
xml_path: build/ktlint-report.xml
# アーティファクトへアップロード
- name: Upload results Artifact
uses: actions/upload-artifact@v2
if: failure()
with:
name: results
path: |
**/build/ktlint-report.xml
if-no-files-found: error
retention-days: 14
注意
-
yutailang0119/action-ktlint
アクションでGitHub上のファイルに指摘を表示している
設定ファイルの全体図
最後に設定ファイルの全体図を載せます。
name: CI
on:
push:
branches:
- main
- develop
paths-ignore:
- docs/**
- README.md
- LICENSE
pull_request:
branches:
- develop
paths-ignore:
- docs/**
- README.md
- LICENSE
jobs:
build:
runs-on: ubuntu-latest
steps:
# チェックアウト
- uses: actions/checkout@v2
# JDKのセットアップ
- name: set up JDK 11
uses: actions/setup-java@v2
with:
distribution: 'zulu'
java-version: '11'
# Gradleのキャッシュ復元
- uses: actions/cache@v2
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
restore-keys: |
${{ runner.os }}-gradle-
# 依存関係の出力
- name: Displays the Android dependencies of the project
run: ./gradlew androidDependencies
# コンパイル
- name: Run Compile
run: ./gradlew assembleDebug
test:
runs-on: ubuntu-latest
steps:
# チェックアウト
- uses: actions/checkout@v2
# JDKのセットアップ
- name: set up JDK 11
uses: actions/setup-java@v2
with:
distribution: 'zulu'
java-version: '11'
# Gradleのキャッシュ復元
- uses: actions/cache@v2
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
restore-keys: |
${{ runner.os }}-gradle-
# テスト
- name: Test with Gradle
run: ./gradlew test --stacktrace
# コードカバレッジをJaCoCo形式で取得
- name: Get code coverage for JaCoCo
run: ./gradlew jacocoDebugTestReport
# コードカバレッジをCodecovへアップロード
- name: Upload code coverage to Codecov
run: bash <(curl -s https://codecov.io/bash)
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
# テスト結果とコードカバレッジのアップロード
- name: Upload test results and code coverage Artifact
uses: actions/upload-artifact@v2
if: success() || failure()
with:
name: results
path: |
**/build/reports/tests/**/*
**/build/reports/test-results/**/*
**/build/reports/jacoco/**/*
if-no-files-found: warn
retention-days: 14
lint:
runs-on: ubuntu-latest
steps:
# チェックアウト
- uses: actions/checkout@v2
# 静的解析
- name: Run Inspection
run: ./gradlew lint
# 結果の表示
- name: Show results on GitHub
uses: yutailang0119/action-android-lint@v1
with:
xml_path: '**/build/reports/lint-results-*.xml'
# アーティファクトへアップロード
- name: Upload results Artifact
uses: actions/upload-artifact@v2
if: success() || failure()
with:
name: results
path: |
**/build/reports/lint-results-*.html
**/build/reports/lint-results-*.xml
if-no-files-found: error
retention-days: 14
detekt:
runs-on: ubuntu-latest
steps:
# チェックアウト
- uses: actions/checkout@v2
# 静的解析
- name: Lint with detekt
run: ./gradlew detekt
# アーティファクトへアップロード
- name: Upload results Artifact
uses: actions/upload-artifact@v2
if: failure()
with:
name: results
path: |
**/build/reports/detekt/**/*
if-no-files-found: error
retention-days: 14
ktlint:
runs-on: ubuntu-latest
steps:
# チェックアウト
- uses: actions/checkout@v2
# インストール
- name: Install ktlint
run: |
curl -sSLO https://github.com/pinterest/ktlint/releases/download/0.42.1/ktlint
chmod a+x ktlint
sudo mv ktlint /usr/local/bin/
# 静的解析
- name: Lint with ktlint
run: ktlint --reporter=checkstyle,output=build/ktlint-report.xml
continue-on-error: true
# 結果の表示
- name: Show results on GitHub
uses: yutailang0119/action-ktlint@v1
with:
xml_path: build/ktlint-report.xml
# アーティファクトへアップロード
- name: Upload results Artifact
uses: actions/upload-artifact@v2
if: failure()
with:
name: results
path: |
**/build/ktlint-report.xml
if-no-files-found: error
retention-days: 14
シンプルなYAMLファイルなので、慣れれば読みやすいと思います。
おわりに
GitHub Actionsで基本的なAndroidアプリのCIを回すことができました!
参考リンク
- GitHub Actionsのワークフロー構文 - GitHub ヘルプ
- UhooiPicBook-Android/ci.yml at develop · uhooi/UhooiPicBook-Android
- Feature/setup jacoco by uhooi · Pull Request #105 · uhooi/UhooiPicBook-Android
- Bump Android Studio to Arctic Fox by uhooi · Pull Request #156 · uhooi/UhooiPicBook-Android
- Show lint report on CI by yutailang0119 · Pull Request #180 · uhooi/UhooiPicBook-Android
- Run ktlint on CI by yutailang0119 · Pull Request #182 · uhooi/UhooiPicBook-Android