各環境ごとに Expo EAS Local Build (Managed workflow) して Firebase App Distribution で配信する際に発生した、各種エラー解決策

# 🌞 はじめに

試行錯誤してこの記事に辿り着かれた皆様、初めまして。

私は友達 🦜 と作っているプロダクトの開発を ReactNative + Expo (Managed workflow) + TypeScript の構成で行っており、
Development環境・Staging環境・商用環境 [^1] を分けてビルドして Firebase App Distribution（以降、FAD） で手軽に触れるよう整備しています。

EAS Build 自体はブランチ機能が導入されたこともあって大変便利なのですが、FADで配信するまでに様々なエラーに対面したため、調査にかなり時間がかかってしまいました。

備忘録として、同じ場面で困っている方の助けになればと思い、対処法をQiitaへ残すことにしました。
あとアドベントカレンダーの季節なので、初チャレンジしてみました🎄


# 🐤 ビルド時に発生したエラー

## Firebase設定ファイルの `no such file or directory`

### 内容

```shell
[PREBUILD] yarn run v1.22.19
[PREBUILD] $ /private/var/folders/s1/02tt52h506xb0yfcnrnw48xm0000gn/T/eas-build-local-nodejs/00a4863a-0987-44fb-9861-a4fffaf81aaf/build/client/node_modules/.bin/expo prebuild --no-install --platform android
[PREBUILD] - Creating native directory (./android)
[PREBUILD] ✔ Created native directory
[PREBUILD] - Updating package.json
[PREBUILD] ✔ Updated package.json
[PREBUILD] - Running prebuild
[PREBUILD] [Error: ENOENT: no such file or directory, open '/private/var/folders/s1/02tt52h506xb0yfcnrnw48xm0000gn/T/eas-build-local-nodejs/00a4863a-0987-44fb-9861-a4fffaf81aaf/build/client/google-services.json'] {
[PREBUILD]   errno: -2,
[PREBUILD]   code: 'ENOENT',
[PREBUILD]   syscall: 'open',
[PREBUILD]   path: '/private/var/folders/s1/02tt52h506xb0yfcnrnw48xm0000gn/T/eas-build-local-nodejs/00a4863a-0987-44fb-9861-a4fffaf81aaf/build/client/google-services.json'
[PREBUILD] }
[PREBUILD] - Running prebuild
[PREBUILD] ✖ Prebuild failed
[PREBUILD] Error: [android.dangerous]: withAndroidDangerousBaseMod: Cannot copy google-services.json from /private/var/folders/s1/02tt52h506xb0yfcnrnw48xm0000gn/T/eas-build-local-nodejs/00a4863a-0987-44fb-9861-a4fffaf81aaf/build/client/google-services.json to /private/var/folders/s1/02tt52h506xb0yfcnrnw48xm0000gn/T/eas-build-local-nodejs/00a4863a-0987-44fb-9861-a4fffaf81aaf/build/client/android/app/google-services.json. Please make sure the source and destination paths exist.
```

これが一番調査に時間がかかりました🤯

`[RUN_EXPO_DOCTOR] Running "expo doctor"` → `[PREBUILD] yarn run v1.22.22` の途中に、ファイルがコピーできないというエラーで失敗するという現象です。

### 原因

- Firebaseの設定ファイル（`google-services.json` / `GoogleService-Info.plist`）を `.gitignore` で除外していた
- Android向けの設定ファイル（`google-services.json`）はそのままの名前では使用できない

### 解説
`.gitignore` が参照されるのは EAS のクラウドビルドの話だと思っていたのですが、`--local` オプションを付けてローカルでビルドする際にも参照されるようで、ここに記載したファイルはビルド時に読み込むことができずエラーになるようでした。

また、`app.config.ts` の `googleServicesFile`[^2] でそれぞれ設定ファイルのパスを指定しますが、AndroidにおいてはFirebaseからダウンロードしたときのデフォルトの名前 `google-services.json` を指定するとエラーになってしまいました。

そこで環境ごとにファイル名を変えてパスを指定したところ、問題なくビルドできるようになりました。

今のディレクトリ構成はこんな感じになっています。

![ss000249-20241217-232737.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409628/e72e156a-0c59-6396-145e-b7591823ac98.png)

Firebaseの設定ファイルをgitで管理してもいいのか！？問題についてですが、
あの [pedantic_mono](https://pub.dev/packages/pedantic_mono) lintを開発されている mono さんは、Firebaseの設定ファイルは公開しても問題ないと仰っています🙆‍♂️（圧倒的信頼）（私もFlutter触ってます💓）
そもそもプロジェクトのリポジトリはPrivate権限のため、そこまで問題ないとは思いますが。。

https://x.com/_mono/status/1087680944612339713

Expo側での環境分けのやり方についてですが、`app.config.ts` で環境変数からパスを参照するように書いていて、`eas.json` で環境ごとの設定ファイルのパスを指定しています。

こうすることで、
`eas build --profile development --platform android --local --output 'build/android/dev.apk'` を実行すればDevelopment環境のAPKが、
`eas build --profile preview --platform ios --local --output 'build/ios/stg.ipa'` を実行すればStaging環境のIPAがビルドできる！！
といった形になります🙌

※今回の解説に影響しない部分は省略しています

```json: eas.json
{
  "build": {
    "development": {
      "env": {
        "EXPO_PUBLIC_APP_VARIANT": "development",
        "GOOGLE_SERVICES_PATH": "./google_services/development/android.json",
        "GOOGLE_SERVICES_INFO_PLIST_PATH": "./google_services/development/ios.plist",
      }
    },
    "preview": {
      "env": {
        "EXPO_PUBLIC_APP_VARIANT": "staging",
        "GOOGLE_SERVICES_PATH": "./google_services/staging/android.json",
        "GOOGLE_SERVICES_INFO_PLIST_PATH": "./google_services/staging/ios.plist"
      }
    },
    "production": {
```

```typescript: app.config.ts
const IS_DEV = process.env.EXPO_PUBLIC_APP_VARIANT === "development";
const IS_STG = process.env.EXPO_PUBLIC_APP_VARIANT === "staging";

export default {
  expo: {
    ios: {
      googleServicesFile: process.env.GOOGLE_SERVICES_INFO_PLIST_PATH,
    android: {
      googleServicesFile: process.env.GOOGLE_SERVICES_PATH,
```

ちなみに、パスの最初にある `./` は必須です。
これも無いとエラーになってしまいます。


## `expo-av` のエラー

### 内容
```shell
[RUN_GRADLEW] FAILURE: Build completed with 2 failures.
[RUN_GRADLEW] 1: Task failed with an exception.
[RUN_GRADLEW] -----------
[RUN_GRADLEW] * Where:
[RUN_GRADLEW] Script '/private/var/folders/s1/02tt52h506xb0yfcnrnw48xm0000gn/T/eas-build-local-nodejs/e780229a-f320-471b-89dc-e28545b3a114/build/client/node_modules/expo-modules-autolinking/scripts/android/autolinking_implementation.gradle' line: 408
[RUN_GRADLEW] * What went wrong:
[RUN_GRADLEW] A problem occurred evaluating project ':expo'.
[RUN_GRADLEW] > A problem occurred configuring project ':expo-av'.
[RUN_GRADLEW] > SDK location not found. Define a valid SDK location with an ANDROID_HOME environment variable or by setting the sdk.dir path in your project's local properties file at '/private/var/folders/s1/02tt52h506xb0yfcnrnw48xm0000gn/T/eas-build-local-nodejs/e780229a-f320-471b-89dc-e28545b3a114/build/client/android/local.properties'.
```

### 原因
- `brew install openjdk` でインストールできる最新版のJava（23）を使っている
- `ANDROID_HOME` の環境変数が未設定

### 解説
バージョン17のJavaをダウンロード ＆ `ANDROID_HOME` の環境変数を設定 の両方を行ったところ、このエラーは発生しなくなりました。

1️⃣ バージョン17のJavaをインストールする
以下のコマンドを実行してインストールしてください。[^3]
既に導入済みの場合は、先に `brew remove openjdk` で削除してください。

```shell
brew install openjdk@17
```

インストール後、以下のように出力されたらOKです。

```shell
hayato@HayatonoMacBook-Pro client % java --version
openjdk 17.0.13 2024-10-15
OpenJDK Runtime Environment Homebrew (build 17.0.13+0)
OpenJDK 64-Bit Server VM Homebrew (build 17.0.13+0, mixed mode, sharing)
```

2️⃣ `~/.zprofile` に以下を追記する
```shell
export ANDROID_HOME=$HOME/Library/Android/sdk
export PATH=$ANDROID_HOME/bin:$PATH
```

完了後、`source ~/.zprofile` を実行してから再度試すと、問題なくビルドできると思います。


# 🐔 FADで配信する際に発生したエラー

## FADへAPK / IPAをアップロードする際に発生するエラー

### 内容

![ss000237-20241211-234320.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409628/79d8512c-6ded-9d01-0dcc-47b1e089c6a8.png)

```
There's been an error processing your distribution. Ensure you are uploading a valid IPA or APK and try again.
```

### 原因
`eas.json` に [`"simulator": true`](https://docs.expo.dev/eas/json/#simulator) を書いたprofileを使っていたこと

### 解説
実機用のprofileからは `"simulator": true` の記述を消してビルドしたところ、問題なくアップロードできました。（エミュレータ用は別のprofileに分けました）

このオプションを書くと、実機用のビルドではなくなり、FAD上へのアップロードもできないようです。
詳しくは以下で解説されていました。

https://zenn.dev/manalink_dev/articles/20240604_expo_development_build#4.-%E5%AE%9F%E6%A9%9F%E3%81%A7%E8%AA%AD%E3%81%BF%E5%8F%96%E3%81%A3%E3%81%A6%E3%82%82%E3%80%81%E3%82%A2%E3%83%97%E3%83%AA%E3%82%92%E9%96%8B%E3%81%8F%E3%81%93%E3%81%A8%E3%81%8C%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%84


## 配信コマンド実行時のエラー

### 内容
`firebase appdistribution:distribute` コマンド実行時に発生しました

```shell
Error: App Distribution could not find your app 1:xxxxxx:ios:xxxxxx. Make sure to onboard your app by pressing the "Get started" button on the App Distribution page in the Firebase console: https://console.firebase.google.com/project/_/appdistribution
make: *** [publish-development] Error 1
```

### 原因
FADで該当アプリの「開始」ボタンが押されていなかった

### 解説
ブラウザでFADの画面を開き、「開始」ボタンを押してからコマンドを実行することで、無事に配信することができました。

![ss000247-20241217-224432.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409628/37c87069-cd66-80e8-ed44-f2c61203c909.png)

なお、この作業はFADに登録したアプリごとに行う必要があります。
（今回はiOS・AndroidごとにDevelopment・Staging環境を用意したため、計4回ボタンをポチポチしました）


# 🌚 おわりに
Expoでローカルビルドができることを知ってから、家の mac mini にJenkinsを導入し、特定のブランチにマージされたら自動ビルド・自動配信するシステムを構築しました。

皆さんも良き EAS Build ライフを！
そして良いクリスマスをお過ごしください🎅🎁

[^1]: 各環境について
    - Development：開発用環境。主に端末とPCをUSBで接続してデバッグする際に使用。
    - Staging：プライベート環境。コミュニティ内で動作チェックをする際に使用。
    - 商用：ストアでリリースしている環境。

[^2]: 参考サイト
    - https://docs.expo.dev/eas/environment-variables/#file-environment-variables
    - https://docs.expo.dev/versions/latest/config/app/#googleservicesfile-1

[^3]: Homebrewで別のバージョンをインストールする方法
    https://qiita.com/gishi_yama/items/ee3526e7e7a922148333#openjdk