Studyplus Engineering Blog

スタディプラスの開発者が発信するブログ

Firebase App DistributionへFabric Betaから社内向けアプリ配信を移行しました

こんにちは、新生モバイルクライアントグループの若宮(id:D_R_1009)です。 今回は社内向けのテストアプリ配信の更新について書きたいと思います。

移行の経緯

スタディプラスAndroidチームでは歴史的な経緯により、Fabric Betaを長らく利用していました。 しかしながら、2020年3月をもってFabric Betaがクローズすることになったため別のサービスへ移行する必要が生じました。

get.fabric.io

いくつかのサービスを検討し、結局Firebase App Distributionを利用することとしました。 いつの間にかベータ版になっていたのが決め手です。

firebase.google.com

試行錯誤したところ、今までと変わらない(一部より利便性を増して)環境構築をできたので共有したいと思います。 「もっといい方法があるよ!」などあれば、ブックマークにコメントを付けて頂けると嬉しいです!

テストアプリ配信環境

テストアプリを配信するにあたり、次の2つの方法を用意しています

  1. CI上で次期リリース用PR作成時に検証環境( Stage )/開発環境( Debug )向きのapkを作成し配信する
  2. ローカル環境(開発者のマシン)から検証環境( Stage )/開発環境( Debug )向きのapkを作成し配信する

1つ目はよくあるCD環境ではないかなと思います。 リリース直前に一通りアプリを触ってテストするため、リリース用PRをベースにビルドを走らせています。 また、サーバーチームのエンジニアが実際にアプリからサーバーAPIを叩く処理を触ることがあるため、社内向けにストアから配信したコードとほぼ同じものを配信する目的もあります。

2つ目のローカルマシンによる実行を用意しているのは、開発者が少なく機能ごとの開発が多いため、検証環境向きのデイリービルドを行っていないためです。 動いているプロジェクトの状況に応じて、またサーバーチームやデザイナーの求めに応じてビルドを走らせてるため、ローカル環境からアップロードできる仕組みを用意しています。

今回Firebase App Distributionを利用するにあたり、このCIとローカルの2つの環境でビルドを走らせるのが少々難しくなっていました。

fastlaneによるlaneの用意

CIとローカル環境用のlaneを用意しておきます。 大きな違いとしてはCI用のlaneでは firebase cli tokenfirebase cli path を設定しておきますが、ローカル環境用では用意していません。

default_platform(:android)

  desc "Debug build and upload Firebase Distribution(for CI)"
  lane :build_and_deploy_debug do
    gradle(
      task: "assemble",
      build_type: "Debug"
    )
    firebase_app_distribution(
      app: ENV["APP_ID_DEBUG"],
      testers_file: "./tester/testers.txt",
      groups_file: "./tester/groups.txt",
      release_notes_file: "./app/BetaDistributionReleaseNotes.txt",
      firebase_cli_token: ENV["FIREBASE_CLI_TOKEN"],
      firebase_cli_path: "./node_modules/.bin/firebase"
    )
  end

  desc "Debug build and upload Firebase Distribution(for local machine)"
  lane :build_and_deploy_debug_local do
    gradle(task: 'clean')
    gradle(
      task: "assemble",
      build_type: "Debug"
    )
    firebase_app_distribution(
      app: ENV["APP_ID_DEBUG"],
      testers_file: "./tester/testers.txt",
      groups_file: "./tester/groups.txt",
      release_notes_file: "./app/BetaDistributionReleaseNotes.txt"
    )
  end
end

CI用の FIREBASE_CLI_TOKEN は公式ドキュメントの通り firebase login:ci を利用して取得しています。

Firebase CLI reference  |  Firebase

Firebase App Distributionの利用はいくつか選択肢がありますが、個人的には fastlane の利用が一番やりやすいのではないかと思います。

firebase.google.com

CircleCIではAndroid用のDocker ImageにRubyの環境が用意されているため、すぐに利用することができます。 もしも fastlane の導入が気になるようでしたら、下記記事を是非ご覧ください。

tech.studyplus.co.jp

CI(CircleCI)の設定

CircleCIではグローバルな環境にFirebase CLIをインストールできないため、作業ディレクトリにnpmを利用してFirebase CLIを用意します。 標準のAndroid用Docker Imageではnodeが用意されていないため -node 付きのnodeが利用できるImageを利用するのが良いと思われます。

version: 2.1
executors:
  android_defaults:
    docker:
      - image: circleci/android:api-29-node

commands:
  setup_bundle:
    steps:
      - restore_cache:
          keys:
            - v1-bundle-cache-{{ checksum "Gemfile.lock" }}
            - v1-bundle-cache-
      - run:
          name: Set path and clean option
          command: |
            bundle config set path './vendor/bundle'
            bundle config set clean 'true'
      - run:
          name: bundle install
          command: bundle check || bundle install --jobs=4 --retry=3
      - save_cache:
          paths:
            - ./vendor/bundle
          key: v1-bundle-cache-{{ checksum "Gemfile.lock" }}

  setup_node:
    steps:
      - restore_cache:
          keys:
            - v1-npm-cache-{{ checksum "package-lock.json" }}
            - v1-npm-cache-
      - run:
          name: npm install
          command: npm install
      - save_cache:
          paths:
            - ./node_modules
          key: v1-npm-cache-{{ checksum "package-lock.json" }}

  setup_android:
    steps:
      - restore_cache:
          keys:
            - v1-gradle-cache-{{ checksum "build.gradle" }}-{{ checksum  "app/build.gradle" }}
            - v1-gradle-cache-
      - run:
          name: Download Dependencies
          command: ./gradlew androidDependencies
      - save_cache:
          paths:
            - /home/circleci/.gradle
          key: v1-gradle-cache-{{ checksum "build.gradle" }}-{{ checksum  "app/build.gradle" }}
  run_build_debug:
    steps:
      - run:
          name: Create new debug build(.apk) and upload Firebase Distribution
          command: bundle exec fastlane android build_and_deploy_debug

jobs:
  build_debug:
    executor:
      name: android_defaults
    steps:
      - checkout
      - setup_bundle
      - setup_node
      - setup_android
      - run_build_debug

workflows:
  deploy:
    jobs:
      - build_debug:
          filters:
            branches:
              only:
                - /^release.*/

Firebase App Distributionへapkを送信する処理がfastlaneに閉じているため、CircleCIではキャッシュの管理程度のステップになります。 なお実運用しているステップでは、途中でリリースノートにブランチ名やコミットログの書き込みなどを行っています。

開発者マシン(shell script)の設定

Mac OSとLinux向けに、Firebase CLIがインストールコマンドを叩いている環境に応じて環境構築をしてくれるスクリプトを公開しています。

Firebase CLI reference  |  Firebase

スタディプラスのモバイルクライアントチームは全員がMacBookProを利用しているため、こちらのスクリプトを採用しました。 このことにより firebase login コマンドの対話的な処理で firebase cli token に該当するリフレッシュトークンを取得することができるようになります。

#!/bin/zsh
echo "Build debug apk, and upload Firebase Distribution"

echo "Login firebase"

curl -sL https://firebase.tools | bash
firebase login

echo "Update local module"

# bundle
bundle config set path './vendor/bundle'
bundle config set clean 'true'
bundle install

echo "Start build"

# Build and upload
bundle exec fastlane android build_and_deploy_debug_local

echo "Done!"

事前にRubyやrbenvによる環境構築が必要となりますが(Bundlerのバージョンアップのため)、一度設定するだけだったので共有コストもほとんどかかりませんでした。 実行時間も短い(6分程度)のため、気軽に実行できる環境が維持されています。

終わりに

今回はFabric BetaからFirebase App Distributionへの移行事例を紹介しました。 実作業時間としては3〜4時間程度だっため、作業負荷もそこまで高くなく、改めてFirebaseの使いやすさを確認することとなりました。

現状ではアプリサイズが原因なのか、Debugのビルド時間にばらつきがあるため、引き続きCI設定を改善していきたいと思います!