🛠️

【Flutter】codemagic.yamlでFirebase App Distributionにベータ配布する (Android版)

2023/01/08に公開

Codemagic

今回は既存のFlutterアプリのAndroidのみをCodemagicのダッシュボードは使わず、codemagic.yaml を使用してFirebase App Distributionへベータ配布するまでをやってみたいと思います。
既にFlutterアプリが特定のGithubのリポジトリに作成されている前提になります。

Sign up

まずはCodemagicに Github アカウント でSign upします。

image1

「Github」を選択します。

image2

次に表示された内容に問題なければ「Authorize Codemagic CI/CD」を選択します。

image3

ダッシュボードが表示されれば成功です ✨

image4

リポジトリを連携

「Add your first app」から対象のリポジトリを追加します。
「Connect reporitory」では「Github」を選択します。

image5

次に対象のリポジトリを選択し、「Select project type」は「Flutter App」を選択します。

image6

今回は codemagic.yaml で管理したいので、「Switch to YAML configuration」を選択します。

image7

必要あれば「Export current ...」にもチェックを入れて「Save changes」を選択すると、codemagic.yaml がダウンロードされます。

image8

デフォルトのWorkflowでダウンロードされた codemagic.yaml の中身はこちら↓

# Automatically generated on 2022-11-24 UTC from https://codemagic.io/app/637f727a8d8ede4cc95b6595/settings
# Note that this configuration is not an exact match to UI settings. Review and adjust as necessary.

workflows:
  default-workflow:
    name: Default Workflow
    max_build_duration: 60
    environment:
      flutter: default
      xcode: latest
      cocoapods: default
    scripts:
      - |
        # set up debug keystore
        rm -f ~/.android/debug.keystore
        keytool -genkeypair \
          -alias androiddebugkey \
          -keypass android \
          -keystore ~/.android/debug.keystore \
          -storepass android \
          -dname 'CN=Android Debug,O=Android,C=US' \
          -keyalg 'RSA' \
          -keysize 2048 \
          -validity 10000
      - |
        # set up local properties
        echo "flutter.sdk=$HOME/programs/flutter" > "$FCI_BUILD_DIR/android/local.properties"
      - flutter packages pub get
      - flutter build apk --debug
      - find . -name "Podfile" -execdir pod install \;
      - flutter build ios --debug --no-codesign
    artifacts:
      - build/**/outputs/apk/**/*.apk
      - build/**/outputs/bundle/**/*.aab
      - build/**/outputs/**/mapping.txt
      - build/ios/ipa/*.ipa
      - /tmp/xcodebuild_logs/*.log
      - build/windows/**/*.msix
      - flutter_drive.log
    publishing:
      email:
        recipients:
          - xxxxxxxxx@gmail.com

↑を一旦Androidビルドするだけの↓に変更し、プロジェクトルートにファイルを追加、コミット&プッシュします。

workflows:
  build-android-workflow:
    name: Build Android Workflow
    labels:
      - Android
    max_build_duration: 60
    instance_type: mac_mini_m1
    environment:
      flutter: v3.3.8
    scripts:
      - |
        # set up debug keystore
        rm -f ~/.android/debug.keystore
        keytool -genkeypair \
          -alias androiddebugkey \
          -keypass android \
          -keystore ~/.android/debug.keystore \
          -storepass android \
          -dname 'CN=Android Debug,O=Android,C=US' \
          -keyalg 'RSA' \
          -keysize 2048 \
          -validity 10000
      - |
        # set up local properties
        echo "flutter.sdk=$HOME/programs/flutter" > "$FCI_BUILD_DIR/android/local.properties"
      - flutter packages pub get
      - flutter build apk --debug
    artifacts:
      - build/**/outputs/apk/**/*.apk
      - build/**/outputs/bundle/**/*.aab
      - build/**/outputs/**/mapping.txt
      - flutter_drive.log
    publishing:
      email:
        recipients:
          - xxxxxx@gmail.com

「App」一覧の対象リポジトリの設定画面へ進み、codemagic.yaml が反映されている事を確認して、「Start ew build」を実行します。

image9

ビルドに成功すると↓の様になります。
image10

設定しておいたメールアドレス宛には↓の様なメールが届きました。
image11

特定のブランチにpushされたら自動でビルドが走る様にする

    triggering:
      events:
        - push
      branch_patterns:
        - pattern: "develop"
          include: true
          source: true

特定のworkflowに↑を追加します。

Environment variables

Build-inされている環境変数

Build-inされている環境変数としては以下が用意されています。

環境変数
ANDROID_SDK_ROOT Android SDKの絶対パス
CI true
CONTINUOUS_INTEGRATION true
BUILD_NUMBER 指定したWorkflowでビルドされた時のBuild Number
PROJECT_BUILD_NUMBER 対象プロジェクトのBuild Number
FLUTTER_ROOT Flutter SDKの絶対パス
CM_BRANCH 現在ビルドしているブランチ
CM_TAG ビルドトリガーとなったタグ(トリガーがタグでない場合は設定されない)
CM_REPO_SLUG owner_name/repository_name 形式のslug
CM_COMMIT 現在ビルドしているコミットのハッシュ値
CM_PREVIOUS_COMMIT 前回ビルドに成功したコミットのハッシュ値 (初めての場合は未設定)
CM_PULL_REQUEST PullRequestのビルドの場合はtrue、それ以外はfalse
CM_PULL_REQUEST_NUMBER Git プロバイダ (Bitbucket、Github など) のプルリクエストを構築している場合は、その ID
CM_PULL_REQUEST_DEST PullRequestの場合はマージ先ブランチ
CM_CLONE_UNSHALLOW true に設定すると、上位 50 コミットの代わりにリポジトリの完全なクローンを実行
CM_CLONE_DEPTH クローン作成時にリポジトリから取得するコミット数
CM_RECURSIVE_SUBMODULE_INIT false を設定すると、再帰的なサブモジュールのcloneはされなくなる
CM_PROJECT_ID ビルド中のプロジェクトのUUID
CM_BUILD_ID ビルドのUUID
CM_TEST_STEP_STATUS テストステップの状態、成功または失敗
CM_BUILD_STEP_STATUS ビルドステップの状態、成功、失敗、またはスキップ。ワークフローエディタ使用時のみ有効で、codemagic.yamlでは使用できない
CM_BUILD_DIR Codemagicビルダーでクローンしたリポジトリのルートディレクトリへの絶対パス
CM_BUILD_OUTPUT_DIR ビルド中に生成されたアーティファクトファイルのパス
CM_EXPORT_DIR このディレクトリに追加されたファイルは、ZIP ファイルに追加され、ビルドの成果物として利用できるようになる
CM_FLUTTER_SCHEME 使用するiOSスキームの名称
CM_KEYSTORE_PASSWORD UIで設定されたAndroid keystoreのパスワード
CM_KEY_PASSWORD UIで設定されたAndroidキーのパスワード
CM_KEY_ALIAS UIで設定されたキーのエイリアス
CM_KEYSTORE_PATH VM上のファイルのパス
CM_ARTIFACT_LINKS post-publishingステップで利用可能な、生成されたビルド成果物に関する情報

自身で追加する環境変数

Variable groups

複数の環境変数にグルーピングしてタグ付けできるものの様です。
例としてstaging環境用と、production環境用でグルーピングしておき、それぞれ同じ環境変数名で定義しておけば、includeするグループに応じて値がstaging環境用か、production環境用かに設定されるようになります。

使用する場合は environment セクションで定義したグループ名をインクルードします。

workflows:
  workflow-name:
    environment:
      groups:
        - magic_values
        - other_values

Firebase App Distriutionへ配布

Firebase App Distribution with codemagic.yaml - Codemagic Docs

Android 署名時のkeystoreファイルの設定

まずは配布時の署名で使う keystore ファイルを作成します。
作成できたら、macosの場合以下コマンドで base64 エンコードしたものをコピーします。

$ cat xxxx.keystore | base64 | pbcopy

次にコピーしたkeystoreを環境変数 CM_KEYSTORE として設定します。

image12

他にもkeystore作成時の alias, password, keystore_password をそれぞれ
CM_KEY_ALIAS, CM_PASSWORD, CM_KEYSTORE_PASSWORD として環境変数を設定します。

image13

次に codemagic.yaml を修正します。

    environment:
      groups:
        - dev_keystore_credentials
      vars:
        CM_KEYSTORE_PATH: /tmp/keystore.keystore
    # ....
    scripts:
      - name: Set up key properties
        script: |
          echo $CM_KEYSTORE | base64 --decode > $CM_KEYSTORE_PATH

environment に先ほど環境変数で設定したgroupを指定します。
また、CM_KEYSTORE_PATH を別途workflow内で使用する環境変数としてkeystoreの保存先を定義しときます。
次に、scripts 内で base64 でエンコードした keystoreファイルを デコードし、 CM_KEYSTORE_PATH へ保存する処理を追加します。

次に android/app/build.gradle で↑で保存したkeystoreを使うように以下を追加 & 修正します。

android {
    // ....
    signingConfigs {
        release {
            if (System.getenv()["CI"]) { // codemagic用に追加
                storeFile file(System.getenv()["CM_KEYSTORE_PATH"])
                storePassword System.getenv()["CM_KEYSTORE_PASSWORD"]
                keyAlias System.getenv()["CM_KEY_ALIAS"]
                keyPassword System.getenv()["CM_KEY_PASSWORD"]
            } else {
                // ....
            }
        }
    }

    buildTypes {
        release {
            signingConfig signingConfigs.release
        }
    }
}

Firebase App Distributionの設定

Firebase App Distributionへ配布する為には、Firebase tokenservice account (Firebase App Distribution Admin roleが付与されたもの) が必要になります。
今回は Firebase token を使用して配布したいと思います。

こちら を参考に、firebase-tools を使用し firebase login:ci で生成されるtokenを取得します。

※ Dockerコンテナ内などで実行している場合、コンテナ内のlocalhostにはアクセスできないので、--no-localhost を指定すると変わりに authorization code で認証ができます。

$ firebase login:ci --no-localhost
⚠  Authenticating with a `login:ci` token is deprecated and will be removed in a future major version of `firebase-tools`. Instead, use a service account key with `GOOGLE_APPLICATION_CREDENTIALS`: https://cloud.google.com/docs/authentication/getting-started

To sign in to the Firebase CLI:

1. Take note of your session ID:

   XXXXX

2. Visit the URL below on any device and follow the instructions to get your code:

   https://auth.firebase.tools/login?code_challenge=...

3. Paste or enter the authorization code below once you have it:

? Enter authorization code: 
XXXXXXXXXXXXXXXXXXXXXXXXXX

✔  Success! Use this token to login on a CI server:

XXXXXXXXXXXXXXXX # ← これ!

Example: firebase deploy --token "$FIREBASE_TOKEN"

取得した token を FIREBASE_TOKEN として group dev_firebase_credentials で登録します。

image14

また、Firebaseに設定しているAndroidアプリのApp IDも環境変数に登録しときます。

image15

最後に codemagic.yaml に以下を追加します。

    environment:
      groups:
        - dev_firebase_credentials # 追加
    publishing:
      firebase: # publishingにfirebase追加
        firebase_token: $FIREBASE_TOKEN
        android:
          app_id: $ANDROID_APP_ID
          groups:
            - Developer

バッドノウハウ

Error: This project is not linked to a Google Play account. が表示される
aab でアップロードしようとすると Google Play account との link が必要
apk でアップロードだと必要ない。
参考URL

参考URL

Discussion