2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

GitHub ActionsでAndroidリリースAPKを自動ビルドする

2
Last updated at Posted at 2026-05-20

GitHub ActionsでAndroidリリースAPKを自動ビルドする

目次


はじめに

GitHub ActionsでAndroidアプリのリリースビルドを自動化する手順をまとめます。
PRマージ時の自動ビルドに加え、workflow_dispatch を使った任意タイミングでの手動実行にも対応します。

完成イメージ

  • PRマージ時に自動でリリースAPKをビルド
  • Actionsタブから手動でも任意ブランチに対してビルド実行
  • ビルド完了後、PRにArtifactsのリンクをコメント通知

1. keystoreファイルの作成

JDK付属の keytool コマンドでkeystoreを生成します。

keytool -genkey -v \
  -keystore release.keystore \
  -alias my-key-alias \
  -keyalg RSA \
  -keysize 2048 \
  -validity 10000

実行すると対話形式で以下を入力します(一部抜粋)。

キーストアのパスワードを入力してください:
新規パスワードを再入力してください:
識別名を入力します。サブコンポーネントを空のままにする場合はドット(.)を1つ入力し、
中カッコ内のデフォルト値を使用する場合は[ENTER]を押します。
姓名は何ですか
  [Unknown]: Taro Yamada
組織単位名は何ですか
  [Unknown]: MyTeam
...

生成した release.keystore.gitignore に追加し、絶対にリポジトリにコミットしないこと。


2. GitHub Secretsへの登録

keystoreはバイナリファイルのため、Base64エンコードしてSecretsに登録します。

エンコード

# Mac/Linux
base64 -i release.keystore | pbcopy

# Windows (PowerShell)
[Convert]::ToBase64String([IO.File]::ReadAllBytes("release.keystore")) | Set-Clipboard

GitHub Secretsが安全な理由・想定されるリスク

GitHub Secretsには以下のセキュリティ特性があります。

  • クライアントサイドで暗号化公式ドキュメントによると、SecretsはLibsodium sealed boxによってGitHubのサーバーに届く前に暗号化される。ワークフロー実行時まで復号されない
  • ログにマスクされる — ワークフローのログ上でSecretsの値は自動的に *** に置換される
  • 読み取り不可 — 登録後はGitHub UIからも値を参照できない(上書きのみ可能)

ただし、以下のリスクは理解しておく必要があります。

リスク 内容
Write権限者は全員利用可能 公式ドキュメントに「リポジトリへのWrite権限を持つユーザーはSecretsにアクセスできる」と明記されている。同じプライベートリポジトリのメンバーは誰でもワークフロー経由でSecretsを利用でき、悪意あるワークフローを追加されると値を外部送信される可能性がある
ログへの意図しない出力 echo $SECRET のように明示的に出力するコードを書くとマスクが外れる場合がある。公式ドキュメントでは「ログの自動マスクを確実に機能させるために、Secretの値に構造化データを使わないこと」と明記されている
フォークからのPRは参照不可 外部コントリビューターのフォークPRではSecretsは渡されない(意図的な制限)

GitHubの仕様上、リポジトリへのWrite権限を持つメンバーは全員、すべてのSecretsをワークフロー経由で利用できます公式ドキュメント)。SecretsごとにRead/Writeを細かく制御する機能はないため、チーム開発ではリポジトリメンバーへのWrite権限付与自体を慎重に行うことが重要です。

Secretsの登録

リポジトリの Settings → Secrets and variables → Actions → New repository secret から以下4つを登録します。

Secret名
KEYSTORE_BASE64 Base64エンコードしたkeystore
KEYSTORE_PASSWORD keystoreファイル全体のパスワード
KEY_ALIAS エイリアス名(例: my-key-alias
KEY_PASSWORD キー個別のパスワード

KEYSTORE_PASSWORDKEY_PASSWORD は別概念です。keystoreはファイル全体を保護するパスワード、KEY_PASSWORDはkeystore内の特定キーを保護するパスワードです。値を同じにすることも可能ですが、Secretsは別々に管理しておくことを推奨します。


3. build.gradleへの署名設定

CI(GitHub Actions)ではシークレットを環境変数から、ローカルでは local.properties から読み込む設定にします。これにより、keystoreの情報をコードにハードコードせず両環境に対応できます。

android {
    val localProps = Properties().apply {
        val f = rootProject.file("local.properties")
        if (f.exists()) load(f.inputStream())
    }

    signingConfigs {
        create("release") {
            storeFile = file(
                (System.getenv("KEYSTORE_PATH")
                    ?: localProps.getProperty("KEYSTORE_PATH", "release.keystore")).trim()
            )
            storePassword = (System.getenv("KEYSTORE_PASSWORD")
                ?: localProps.getProperty("KEYSTORE_PASSWORD"))?.trim()
            keyAlias = (System.getenv("KEY_ALIAS")
                ?: localProps.getProperty("KEY_ALIAS"))?.trim()
            keyPassword = (System.getenv("KEY_PASSWORD")
                ?: localProps.getProperty("KEY_PASSWORD"))?.trim()
        }
    }

    buildTypes {
        release {
            signingConfig = signingConfigs.getByName("release")
            isMinifyEnabled = false
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }
}

ローカルビルド用の設定

ローカルでリリースビルドする場合は local.properties に以下を追記します。

KEYSTORE_PATH=../release.keystore
KEYSTORE_PASSWORD=your_keystore_password
KEY_ALIAS=my-key-alias
KEY_PASSWORD=your_key_password

local.properties.gitignore にデフォルトで含まれていますが、念のため含まれていることを確認してください。

優先順位は 環境変数 > local.properties となるため、CI環境では自動的にGitHub Secretsが使われます。


4. ワークフローの設定

.github/workflows/pull_request.yml を以下のように設定します。

name: Pull Request # ワークフローの名前

on: # ワークフローの発動条件
  pull_request: # プルリクエスト
    branches: # 対象ブランチ
      - main
      - 'feature/**'
    paths:
      - 'app/**'           # appモジュール配下の変更時のみ
      - 'build.gradle.kts' # ルートのGradle変更時も含める
    types: # イベントタイプ
      - closed # プルリクエストがクローズされたとき
  workflow_dispatch: # UIでのワークフローのトリガー

permissions: # 権限
  contents: read # リポジトリのコード取得に必要(upload-artifactはリポジトリへの書き込みを行わないためreadで十分)
  pull-requests: write    # PRにコメントする権限
jobs: # ジョブ
  build: # ジョブの名前
    # プルリクエストがマージされたとき及び、workflow_dispatchイベントが発生したとき
    if: github.event.pull_request.merged == true || github.event_name == 'workflow_dispatch'
    runs-on: ubuntu-latest # 実行環境

    steps: # ステップ
      - name: Checkout # チェックアウト
        uses: actions/checkout@v4 # actions/checkout@v4 を使用

      - name: Set Up JDK # JDK のセットアップ
        uses: actions/setup-java@v4 # actions/setup-java@v4 を使用
        with: # 設定
          distribution: 'zulu' # Zulu ディストリビューション
          java-version: '21' # Java 21

      - name: Setup Gradle # Gradle のセットアップ
        uses: gradle/actions/setup-gradle@v6 # gradle/actions/setup-gradle@v6 を使用

      - name: Decode Keystore
        # GitHub SecretsにBase64で保存したkeystoreをデコードしてファイルに書き出す
        # ファイルはビルド後に自動削除されるランナーの一時領域に置く
        # ${{ secrets.XXX }} をrunに直接展開せずenv経由で渡す
        # 公式推奨: https://docs.github.com/en/actions/reference/security/secure-use#use-an-intermediate-environment-variable
        env:
          KEYSTORE_BASE64: ${{ secrets.KEYSTORE_BASE64 }}
        run: |
          echo "$KEYSTORE_BASE64" | base64 -d > ${{ github.workspace }}/release.keystore

      - name: Build With Gradle # Gradle でビルド
        run: ./gradlew assembleRelease # リリースビルド
        env:
          KEYSTORE_PATH: ${{ github.workspace }}/release.keystore
          KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
          KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
          KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}

      - name: Upload APK # APK のアップロード
        uses: actions/upload-artifact@v4 # v4 以降に変更
        with: # 設定
          name: app-release.apk # アーティファクト名
          path: app/build/outputs/apk/release/app-release.apk # APK のパス

      - name: Comment on PR
        if: github.event.pull_request.merged == true
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
        run: |
          gh pr comment "${{ github.event.pull_request.number }}" --repo "${{ github.repository }}" --body "🚀 リリースビルドが完了しました。
          APKファイルは以下のリンク先(Artifactsセクション)からダウンロードできます:
          $RUN_URL"

5. 署名確認

ダウンロードしたAPKが正しく署名されているかは apksigner で確認できます。

~/Library/Android/sdk/build-tools/35.0.0/apksigner verify --verbose app-release.apk

apksigner はAndroid SDKのBuild Toolsに含まれています。上記はフルパス指定の例ですが、パスを通しておくとコマンド名だけで実行できます。

~/.zshrc(または ~/.bashrc)に以下を追記し、反映します。

export PATH="$PATH:$HOME/Library/Android/sdk/build-tools/35.0.0"
source ~/.zshrc

パスが通っているかは以下で確認できます。

which apksigner
# => /Users/yourname/Library/Android/sdk/build-tools/35.0.0/apksigner

署名されている場合、以下のように Verifies と表示されます。

Verifies
Verified using v1 scheme (JAR signing): false
Verified using v2 scheme (APK Signature Scheme v2): true
Verified using v3 scheme (APK Signature Scheme v3): false
...
Number of signers: 1

v2 scheme: true であれば署名は正常です。


Tips: トリガー対象ファイルの絞り込み(paths)

paths を追加することで、特定ファイルの変更時だけビルドをトリガーできます。READMEやドキュメントの修正など、アプリコードに関係ない変更でビルドが走るのを防げます。

on:
  pull_request:
    branches:
      - main
      - 'feature/**'
    types:
      - closed
    paths:
      - 'app/**'            # appモジュール配下の変更時のみ
      - 'build.gradle.kts'  # ルートのGradle変更時も含める
メリット デメリット
paths あり ドキュメントやREADMEの修正でビルドが走らない。CI時間・コスト節約 パス設定のミスでビルドがスキップされるリスクがある
paths なし シンプルで確実にビルドが走る 関係ない変更でもビルドが走る

プロジェクトの規模が小さいうちは paths なしでシンプルに運用し、ドキュメント管理やモジュール分割が増えてきたタイミングで導入を検討するのがおすすめです。


Tips: 手動実行(workflow_dispatch)について

workflow_dispatch を設定することで、ActionsタブのUIから任意のタイミング・任意のブランチに対してビルドを実行できます。

注意点: workflow_dispatch のトリガーはワークフローファイルがデフォルトブランチに存在する場合のみ有効になります。featureブランチで追加しても「Run workflow」ボタンは表示されないため、mainへのマージ後に動作確認しましょう。


まとめ

ステップ 内容
1 keytool でkeystoreを生成
2 Base64エンコードしてGitHub Secretsに4つ登録
3 build.gradle で環境変数・local.propertiesから署名設定を読み込む
4 ワークフローYAMLにDecodeとビルドステップを追加
5 apksigner でAPKの署名を確認

PRマージ時の自動化に加え workflow_dispatch を組み合わせることで、柔軟なCI/CDが構築できます。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?