FlutterアプリをfastlaneでApp Distributionに配布する方法

FlutterアプリをfastlaneでFirebase app distributionで配布する方法を紹介します。
複数プラットフォーム/環境だと配布にかかる時間もばかにならないので自動化で効率化したいですね。


# 前提
Firebaseのセットアップ、アプリ登録、App Distributionの有効化は完了しているとします。

# プロジェクトルート
## 以下のGemfileを作成

```
source 'https://rubygems.org'
gem "fastlane"
gem "cocoapods"
```

## gemをインストール
```
bundle install
```

# fastlane初期化
```
bundle exec fastlane init
bundle exec fastlane  add_plugin firebase_app_distribution
```

## Fastfile
以下のFastfileを作成。
FIREBASE_TESTERSはApp Distributionにアップされて時のメール通知対象です。
FIREBASE_CLI_TOKENは環境変数FIREBASE_TOKENから読み込んでいます。

```
FIREBASE_TESTERS = "カンマ区切りのメアド"
# TODO トークンでなくサービスアカウントを使う
# トークンの取得は firebase login:ci
FIREBASE_CLI_TOKEN = ENV["FIREBASE_TOKEN"]

import "../android/fastlane/Fastfile"
import "../ios/fastlane/Fastfile"
```



# android iosそれぞれでfastlane導入
- プロジェクトルート/fastlane/Gemfileをそれぞれにコピー
- それぞれ `bundle install`
- それぞれ `bundle exec fastlane init`
- それぞれ `bundle exec fastlane  add_plugin firebase_app_distribution`

## androidのFastfile
devとprodの2つのflavorに対応して以下のようなFastfileを作成。
flutterのビルドコマンドはご自身の環境に応じて変更してください。

```
default_platform(:android)

platform :android do
  android_app_ids = {
    :dev => "FIREBASEのAPP_ID",
    :prod => "FIREBASEのAPP_ID"
  }

  desc "Publish by App Distribution"
  lane :publish do |options|
    flavor = options[:flavor]
    sh( "flutter","clean" )
    sh( "flutter","build","apk","--release", "--flavor",flavor.to_s,"--target","lib/entry-point/release-#{flavor.to_s}.dart" )
    firebase_app_distribution(
                  app: android_app_ids[flavor],
                  testers: FIREBASE_TESTERS,
                  release_notes_file: "android/fastlane/release_notes.txt",
                  firebase_cli_token: FIREBASE_CLI_TOKEN,
                  debug: true,
                  apk_path: "build/app/outputs/apk/#{flavor.to_s}/release/app-#{flavor.to_s}-release.apk"
              )
  end

  desc "Publish dev version by App Distribution"
  lane :publish_dev do
    publish(flavor: :dev)
  end

  desc "Publish prod version by App Distribution"
  lane :publish_prod do
    publish(flavor: :prod)
  end

  desc "Publish all version by App Distribution"
  lane :publish_all do
    publish(flavor: :dev)
    publish(flavor: :prod)
  end
end
```

## iOSのFastfile
devとprodの2つのflavorに対応して以下のようなFastfileを作成。
flutterのビルドコマンドやbuild_appのschemeやconfigurationご自身の環境に応じて変更してください。

```

default_platform(:ios)


platform :ios do
  ios_app_ids = {
    :dev => "FIREBASEのAPP_ID",
    :prod => "FIREBASEのAPP_ID"
  }

  desc "Publish by App Distribution"
  lane :publish do |options|
    flavor = options[:flavor]
    sh( "flutter","clean" )
    sh( "flutter","build","ios","--release", "--flavor",flavor.to_s,"--target","lib/entry-point/release-#{flavor.to_s}.dart" )

    build_app(
      workspace: "ios/Runner.xcworkspace",
      scheme: "#{flavor.to_s.capitalize}",
      configuration: "Release-#{flavor.to_s.capitalize}",
      export_options: {
        method: "ad-hoc"
      },
      clean: true,
      output_name: "#{flavor.to_s}.ipa",
      output_directory: "build/ios/"
    )

    firebase_app_distribution(
                  app: ios_app_ids[flavor],
                  ipa_path: "build/ios/#{flavor.to_s}.ipa",
                  testers: FIREBASE_TESTERS,
                  release_notes_file: "ios/fastlane/release_notes.txt",
                  firebase_cli_token: FIREBASE_CLI_TOKEN,
                  debug: true
              )
  end

  desc "Publish dev version by App Distribution"
  lane :publish_dev do
    publish(flavor: :dev)
  end

  desc "Publish prod version by App Distribution"
  lane :publish_prod do
    publish(flavor: :prod)
  end

  desc "Publish all version by App Distribution"
  lane :publish_all do
    publish(flavor: :dev)
    publish(flavor: :prod)
  end
end
```

# 配布方法
以下のコマンドで配布が可能です。

```
cd プロジェクトルート
# androidアプリを全flavorで配布
bundle exec fastlane android publish_all
# iosアプリを全flavorで配布
bundle exec fastlane ios publish_all
```