🤖

AndroidアプリのCI/CD環境の改善 -BitriseとGitHub Actionsの併用-

に公開

ポート株式会社 サービス開発部 Advent Calendar 2025 の6日目の記事です。

Androidアプリ開発をしている@shxun6934です。

はじめに

弊社のiOS/Androidアプリ開発では、Bitriseのみを用いて、CI/CD環境を構築し、運用していました。

構築設定

以下のような設定で構築しています。

  • 1つのWorkspaceに、同じサービスのiOS/Androidアプリが属している
  • Workspace内で同時に動くWorkflowが2つまで
  • UnitTestとLintを実行するWorkflow、DeployGateとApp Store/Google PlayへデプロイするWorkflow、実行結果をSlackへ通知するWorkflowが存在している
  • ↑のWorkflowを組み合わせて、GitHubのPRがOpenになったタイミングやcommitがpushされたタイミングで自動で実行される

課題

上記の構築の中の

  • 1つのWorkspaceに、同じサービスのiOS/Androidアプリが属している
  • Workspace内で同時に動くWorkflowが2つまで

が要因で、いくつか課題になっていることがありました。

リリースデプロイのリードタイムが長い

Bitriseは、開始された順にWorkflowを実行していきます。同時に動くWorkflow数が上限を超えた場合、上限を超えたタイミングで開始されるWorkflowは待機状態になり、実行中のWorkflowが実行完了し次第、実行されます。

1 A (実行中)
2 B (実行中)
3 C (待機中) <--- A, B のいずれかが実行完了した後に実行開始
4 D (待機中) <--- A, B, C のいずれか2つが実行完了した後に実行開始

この仕様は、Workspaceに適用されるので、iOS/AndroidがそれぞれのWorkflowを動かした場合やiOS内/Android内で別々にWorkflowを動かした場合、待機状態のWorkflowが溜まっていきます

実行時間に待機時間が追加されるため、リードタイムが長くなります

実際の開発では、iOS/Androidがそれぞれ同じタイミングでリリース作業を行っている時、どちらかのWorkflowが待機状態になってしまい、リリースデプロイが完了するまでの時間が長くなることがしばしばありました。

並列処理が実質不可能

Bitriseで並列処理を動かす場合は、Workflowを同時に動かす必要があります。弊社の環境で言えば、2つまでなら並列処理が可能です。

1 A (実行中)
2 B (実行中) <--- Aと同じタイミングで実行

ただ、同時に動かせるWorkflow数が少なすぎて、並列処理による実行時間の短縮が見込めませんでした
(今回は割愛しますが、一度、Bitriseでの並列処理を導入し、実行時間の短縮を試みました。が、実行時間の短縮には至りませんでした。)

解決方針

「リリースデプロイのリードタイムが長い」「並列処理が実質不可能」を解決するために、BitriseとGitHub Actionsを併用する形にしました。

GitHub Actions

(知っている人も多いと思いますが改めて)

GitHub Actionsは、GitHubが提供しているWorkflowを自動化するサービスです。
Bitriseのように、GitHub上にCI/CD環境を構築・運用することができます。

弊社のGitHubは、GitHub Enterpriseプランなので、大規模なCI/CD環境を構築することができます。

なぜGitHub Actions?

自分が携わっているiOS/Androidアプリは、別々ののRepositoryで管理しています。
GitHub ActionsをそれぞれのRepositoryで動かすことになるので、実行するWorkflowが干渉しなくなります。

よって、Bitriseよりは自由にWorkflowを実行することができるようになります。

なぜ併用?

GitHub Actionsへの完全移行を考えていますが、完全移行を行うためのリソースがそこまで取れなかったため、まずは段階的に移行することになりました。

併用するにあたり

ここからはAndroidアプリのみの話になります

BitriseとGitHub Actionsを併用していくにあたり、以下の内容を行いました。

  • Bitriseで実行している全てのWorkflowを、GitHub Actionsで実行できるようにする
  • 自動で実行している一部のBitriseのWorkflowを、GitHub Actionsで自動で実行する

Bitriseで実行している全てのWorkflowを、GitHub Actionsで実行できるようにする

Androidアプリ開発での、Bitriseで実行していたWorkflowは以下になります。

  • GitHub RepositoryからプロジェクトのCloneやAndroid SDKのインストール、環境変数の設定、キャッシュのリストアを実行するWorkflow
  • Unit TestとLint(Android LintとKtlint)を実行するWorkflow
  • Roomのマイグレーションテストを実行するWorkflow
  • aab or apk ファイルを作成するWorkflow
  • DeployGate or Google Playへデプロイし、Slackへ通知するWorkflow
  • キャッシュのセーブを実行するWorkflow

これらのWorkflowをGitHub Actionsでも実行できるように対応をしました。
この対応の中で学んだこと・苦戦したことを一部紹介します。

ビルドを共通化

「aab or apk ファイルを作成するWorkflow」にて、実行するstepがほぼ同じだったので、workflow_callを使用して共通化しました。

Reuse workflows

inputsを使用して、ビルド対象のバリアントを指定することで、リリースデプロイかbetaデプロイかの指定をできるようにもしました。

on:
  workflow_call:
    inputs:
      variant:
        description: 'ビルドバリアント'
        type: string
        required: true

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code # チェックアウト
        uses: actions/checkout@v4
      - name: Setup java # Javaの設定
        uses: actions/setup-java@v4
        with:
          distribution: 'temurin'
          java-version: '17'
      - name: Cache gradle # Gradle のキャッシュ設定
        uses: actions/cache@v4
        with:
          path: |
            ~/.gradle/caches
            ~/.gradle/wrapper
          key: gradle-${{ github.ref }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties', 'gradle/*.versions.toml') }}
          restore-keys: gradle-${{ github.ref }}-
      # (必要に応じて環境変数や署名の設定を行う)
      - name: Build # build リリースデプロイはaabを、stgデプロイはapkを生成
        run: |
            if [ "${{ inputs.variant }}" = "release" ]; then
                ./gradlew bundleRelease --stacktrace
            else
                ./gradlew assembleBeta --stacktrace
            fi

artifactsによる生成したファイルを出力

「aab or apk ファイルを作成するWorkflow」や「Unit TestとLint(Android LintとKtlint)を実行するWorkflow」にて、実行した後にファイルが生成されるGradleタスクがある場合は、GitHub Actionsのartifacts を用いて、他のWorkflowに共有できるようにしたり、GitHubからダウンロードできるようにしました。

aab or apk ファイルであれば他のWorkflow内で使用でき、Unit TestとLintの出力結果は内容をダウンロードして確認することができます。

# アップロードする時
- name: Upload apk as artifact
  uses: actions/upload-artifact@v4
  with:
    name: app-beta.apk
    path: /build/outputs/apk/beta/app-beta.apk
- name: Upload aab as artifact
  uses: actions/upload-artifact@v4
  with:
    name: app-release.aab
    path: /build/outputs/bundle/release/app-release.aab
# ダウンロードする時
- name: Download apk
  uses: actions/download-artifact@v4
  with:
    name: app-beta.apk
    path: /build/outputs/apk/beta/
- name: Download aab
  uses: actions/download-artifact@v4
  with:
    name: app-release.aab
    path: /build/outputs/bundle/release/

Slackの通知をリッチに

Bitriseでは、Send a Slack messageというstepを使用して、Slackへデプロイ完了の通知を行っていました。
SlackのIncoming Webhooks を利用して、Slackへ通知を送信しています。

これをGitHub Actionsで実現するためには、slackapi/slack-github-actionを使用します。

- name: Notify to slack
  uses: slackapi/slack-github-action@v2.1.1
  with:
  webhook: ${{ secrets.slack_webhook_url }}
  webhook-type: incoming-webhook
  payload-templated: true
  payload-file-path: "./.github/workflows/slack/beta-deploy.json"

Formatting message textBlock Kit Builderを参考にJSONを構築します。

{
  "text": "`beta` 版のデプロイが完了しました!",
  "attachments": [
    {
      "color": "#3bc3a3",
      "pretext": "*Build Succeeded!*",
      "author_name": "${{ github.actor }}",
      "title": "${{ env.commit_message }}",
      "fields": [
        {
          "title": "App",
          "value": "~~~-android",
          "short": true
        },
        {
          "title": "Branch",
          "value": "${{ env.branch_name }}",
          "short": false
        }
      ],
      "footer": "GitHub Actions",
      "footer_icon": "https://github.com/actions.png?size=16",
      "ts": "${{ env.unix_ts }}",
      "actions": [
        {
          "type": "button",
          "text": "GitHub Actions",
          "url": "https://github.com/~~~/~~~-android/actions/runs/${{ env.run_id }}",
          "style": "default"
        },
        {
          "type": "button",
          "text": "DeployGate",
          "url": "https://deploygate.com/users/~~~/apps/~~~.beta",
          "style": "default"
        }
      ]
    }
  ],
  "icon_emoji": ":robot_face:",
  "link_names": true,
  "username": "GitHub Actions",
  "reply_broadcast": false
}

他にも設定できる項目があるので、よりリッチなテキストにできます。

自動で実行している一部のBitriseのWorkflowを、GitHub Actionsで自動で実行する

今回は、Lint(Android LintとKtlint)を実行するWorkflowをGitHub Actionsで実行し、それ以外は既存のままBitriseで実行するようにしました。

使用しているサービスは2つですが、並列処理を行えるようになりました。

実際に運用してみて

10月末に運用を開始してみました。

Bitriseのみの場合の平均実行時間は、25分

BitriseとGitHub Actionsの併用をした場合の平均実行時間は、20分

5分くらい時間の短縮ができ、並列処理も可能になりました。

最後に

課題に感じていたことへの解消はできましたが、サービスを2つ使用しているため、その分の課金が発生しています。
なので、改善した実行時間をそのままに、GitHub Actionsへの完全移行を目指したいと思います。

ポート株式会社 エンジニアブログ

Discussion