AndroidでGithub Actionsを活用する
自動ワークフロー
.github/workflowsに作っていく
プルリクエスト時
ビルドする
# ワークフローの名前(GitHub のActionsタブに表示される)
name: PR Checks
# イベントのトリガー
on:
pull_request:
jobs:
# ジョブ名
build-and-test:
# ジョブが実行される環境
runs-on: ubuntu-latest
steps:
# ソースコードのチェックアウト(ダウンロード)
- name: Checkout code
uses: actions/checkout@v4
- name: Set up JDK
uses: actions/setup-java@v4
with:
java-version: '17' # Javaのバージョンを指定
distribution: 'temurin' # JDKのディストリビューションを指定
# 実行権限を付与するステップを追加
- name: Grant execute permission for gradlew
run: chmod +x gradlew
# アプリビルドの実行
- name: Build with Gradle
run: ./gradlew assembleDebug
Lintチェックする
# Lintチェックの実行
- name: Run Lint
run: ./gradlew lintDebug
単体テストする
# 単体テスト実行
- name: Run Unit Tests
run: ./gradlew testDebugUnitTest
タグを付与する
# PRにラベルを付けるジョブ
label-pr:
runs-on: ubuntu-latest
permissions:
pull-requests: write
issues: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Add PR labels based on changes files
# labelerアクションを使用する、labeler.ymlファイルを参照
uses: actions/labeler@v5
# 書き込みにはGitHubトークンが必要(ワークフロー内のみ有効)
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
sync-labels: true # ラベルの自動作成を有効化
jobが複数ある場合依存関係がない場合デフォルトで並列実行になる
ちなみにタイムアウトの時間はデフォルトで360分なので明示的に指定してもいいかもしれない
# ワークフローの名前(GitHub のActionsタブに表示される)
name: PR Checks
# イベントのトリガー
on:
pull_request:
jobs:
# ジョブ名
build-and-test:
# ジョブが実行される環境
runs-on: ubuntu-latest
# 3タイムアウトを30分に指定
timeout-minutes: 30
steps:
# ソースコードのチェックアウト(ダウンロード)
- name: Checkout code
uses: actions/checkout@v4
.github/labeler.yamlを作成する
pathとファイル名はこれじゃないと動かないので注意
UI:
- changed-files:
- any-glob-to-any-file: ['**/ui/**']
Domain:
- changed-files:
- any-glob-to-any-file: ['**/domain/**']
Data:
- changed-files:
- any-glob-to-any-file: ['**/data/**']
Test:
- changed-files:
- any-glob-to-any-file: ['**/test/**', '**/androidTest/**']
Config:
- changed-files:
- any-glob-to-any-file: ['**/*.gradle', '**/*.gradle.kts', '**/*.toml', '**/gradle.properties', '**/AndroidManifest.xml']
手動ワークフロー
リリース作業を自動化する
実現すること
- Githubでアップデートするversion指定する
- gradleファイルのversionをアップデートしたPRを出す
- リリースノートをドラフトで作成、前回との差分を表示、署名済みのapkとaabを添付する
これらを行う必要があるがゼロから行うと結構大変なので既に公開されているactionを利用する
実現したい内容がすでに公開されているactionにあるか確認したほうがいい
公式
その他
行うこと
- ローカルでキーストアを作成する
- Githubでの秘匿情報の設定
- build.gradle.ktsの修正
- Githubでのワークフロー時のPermission設定をする
- ワークフローの作成
ローカルでキーストアを作成する
Android Studioのツールバーからbuild > Generated Signed App Bundle or Apkから作成
Githubでの秘匿情報の設定
Github Actionsで署名付きアプリを作るにあたって必要になる。秘匿情報は必要だがリポジトリに含めるわけにはいかないため。
Githubでリポジトリに移動してからSettings > Seacrets and Valiables > actions
Repository secretsに
- KEYSTORE_BASE64
- KEYSTORE_PASSWORD
- KEY_ALIAS
- KEY_PASSWORD
を設定していく
KEYSTORE_PASSWORD、KEY_ALIAS、KEY_PASSWORDはローカルで設定したものをそのまま設定する
KEYSTORE_BASE64はひと手間必要になってくる
ローカルで作成したキーストア(~.jks)を設定したいがバイナリファイルためBase64にエンコードしたものをGithubに設定する
bashで
base64 -w 0 sampleActions.jks > keystore.base64
keystore.base64の内容をKEYSTORE_BASE64に設定する
build.gradle.ktsの修正
ローカルでビルドする場合はlocal.propertiesの設定を使用する
ワークフローではlocal.propertiesがないのでそれを利用して分岐する
Githubの秘匿情報から取得するするように設定する
signingConfigs {
create("release") {
val localProps = rootProject.file("local.properties")
if (localProps.exists()) {
val props = Properties().apply { load(localProps.inputStream()) }
storeFile = rootProject.file(props["storeFile"] ?: "")
storePassword = props["storePassword"] as? String ?: ""
keyAlias = props["keyAlias"] as? String ?: ""
keyPassword = props["keyPassword"] as? String ?: ""
} else {
storeFile = file("release.jks")
storePassword = System.getenv("KEYSTORE_PASSWORD")
keyAlias = System.getenv("KEY_ALIAS")
keyPassword = System.getenv("KEY_PASSWORD")
}
}
}
buildTypes {
release {
signingConfig = signingConfigs.getByName("release")
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
Githubでのワークフロー時のPermission設定をする
Githubのリポジトリに移動してからSettings > actions > General
Workflow permissionsで
Read and write permissions
Allow GitHub Actions to create and approve pull requests
書き込みとPRを作成する権限を与える
ワークフローの作成
.github/workflowsにrelease.ymlを作成
name: Android Release
on:
workflow_dispatch:
inputs:
version_name:
description: 'Version Name (例: 1.0.1)'
required: true
type: string
permissions:
contents: write
pull-requests: write
jobs:
release:
runs-on: ubuntu-latest
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
cache: gradle
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Decode keystore
run: echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 --decode > app/release.jks
- name: Build signed APK/AAB
env:
KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
run: |
./gradlew assembleRelease
./gradlew bundleRelease
- name: Clean up keystore
if: always()
run: rm -f app/release.jks
- name: Create GitHub Release
uses: ncipollo/release-action@v1
with:
tag: "v${{ github.event.inputs.version_name }}"
name: "Release v${{ github.event.inputs.version_name }}"
# 自動生成リリースノートを有効化
generateReleaseNotes: true
artifacts: |
app/build/outputs/apk/release/*.apk
app/build/outputs/bundle/release/*.aab
draft: true
token: ${{ secrets.GITHUB_TOKEN }}
- name: Bump Version
uses: chkfung/android-version-actions@v1.2.2
with:
gradlePath: app/build.gradle.kts
versionName: ${{ github.event.inputs.version_name }}
versionCode: ${{ github.run_number }}
- name: Create Pull Request
uses: peter-evans/create-pull-request@v6
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: "Release v${{ github.event.inputs.version_name }} (build ${{ github.run_number }})"
branch: "release/v${{ github.event.inputs.version_name }}-${{ github.run_number }}"
title: "Release v${{ github.event.inputs.version_name }}"
body: |
## Release Summary
Version: ${{ github.event.inputs.version_name }}
Build: ${{ github.run_number }}
## Files Changed
- Updated version in `app/build.gradle.kts`
## Release Assets
- APK: Available in GitHub Release
- AAB: Available in GitHub Release
## Next Steps
1. Review and test the release
2. Merge this PR to main
3. Publish the GitHub Release (currently draft)
draft: false
delete-branch: true
ワークフローの流れ
- 環境準備
- リポジトリチェックアウト
- JDK 17セットアップ
- gradlewに実行権限付与
- アプリビルド
- キーストア作成
- 署名済みAPK/AAB生成
- キーストア削除(セキュリティ)
- リリース作成
- GitHub Releaseを作成(ドラフト)
- バージョン更新
- build.gradle.ktsのバージョン番号更新
- Pull Request作成
詳細
- workflow_dispatchとすることで手動のワークフローになる
- inputsで何を入力するか定義する
- permissionsで書き込み権限を付与する
- Set up JDK 17ではgradleを使用できるようにする
- Grant execute permission for gradlewではgradlewが使用できるように実行権限を付与する
- Decode keystoreではbase64の形式で設定している秘匿情報をデコードする
- Build signed APK/AABではenvでGithubの秘匿情報の設定を読み込む
- ワークフローのenv → GradleのSystem.getenv() → 署名設定完成
- Clean up keystoreではワークフローが失敗しても必ずキーストアを削除する
- 後でPR作るときに含まれてしまう
- Create GitHub Releaseでは公開されているActionを利用する、artifactsを設定すると指定したものをリリースノートに添付できる
- Bump Versionでは公開されているActionを利用する
- Create Pull Requestは公開されているActionを利用する
- https://github.com/peter-evans/create-pull-request
- draft: falseにすることですぐにPRがオープンな状態で表示される
- delete-branchをtrueにすることで次のワークフロー時に残っていた場合は削除される
Discussion