EAS ビルド及びサブミットの使い方

前回はクラウドIDE GitPodの使い方について紹介しましたが、今回はReact-Native Expoの新しいビルド＆サブミットであるEAS(Expo Application Services)の使い方の紹介です。EASビルドはローカルでも実行できますが、クラウドで実行するのが基本形で、３種類のプランから選択します。
[参考：EASのプラン](https://expo.dev/pricing)

自分は無料プランを使ってますが、ビルドが同時に１つしか実行できないのとビルド結果が45分で期限切れになる等の制限があるものの、十分使える範囲なので満足してます。
使い方はドキュメントに詳しいので、留意点やポイントを中心に紹介します。
１．Easビルド手順と留意点＆Development Clientの使い方
２．Easサブミット手順と留意点
３．まとめ

１．Easビルド手順と留意点＆Development Clientの使い方
まずはExpoの設定等が既に完了している前提で話を進めさせてもらいます。まずプロジェクトのディレクトリで下記コマンドでeas-cliをインストールします。

```node:console
npm install -g eas-cli
```

次にexpo-cliでログインしていない場合はeas loginでログインします。アカウントとパスワードはExpoと同じものを使用します。
次にeas build:configureで各種設定をしてその結果でeas.jsonという設定ファイルを自動で生成してくれるのですが、Q&A形式で入力していくので、面倒な場合はeas.jsonというファイルをプロジェクトディレクトリのルートに配置し、下記の設定例をコピーして必要箇所だけ修正した方が早いかもしれません。
ビルドの種類はdevelopment/preview/productionの３種類で、それぞれに設定項目を設定する構成になっており、設定例は下記のとおりです。

```expo:eas.json
{
  "build": {
    "development": {
      "developmentClient": true,
      "distribution": "internal"
    },
    "preview": {}, //"distribution": "internal"を削除（下記追記参照）
    "preview1": {
      "android": {
        "buildType": "apk"
      }
    },
    "production": {}
  }
}
```

ここでdevelopmentの中に"developmentClient": trueを設定すると、実機の検証をExpo GoでなくDevelopment Clientを使うことになります。Development Clientは別途プロジェクト側でexpo install expo-dev-clientでインストールが必要ですが、Managed WorkflowでExpo Goを使う場合は必要ないので(Bare Workflowでは必要！）削除又はfalseに設定して下さい。強いて言うと、Development ClientはBare Workflowを含む全てのExpoプロジェクトで実機デバックができるツールという感じで、使い方はExop Goとほぼ同じです。
preview1はAndroid用のビルドをapkにする場合の設定例ですが、この様に何種類かのビルドを定義することもできます（この場合のビルドコマンドは　eas build --profile **preview1** --platform android）。
追記）最近previewビルドしてその後Submitしたら失敗しました。原因はpreviewが"distribution": "internal"だと.apkファイルが生成され、.apkだとGoogle API Errorが出てSubmitに失敗するとのこと。"distribution": "internal"を削除してやると.aabファイルが生成されSubmitも上手くいきます（eas.json修正済み、追記終わり）。
またdevelopmentとpreviewの中の"distribution": "internal"は内部テスト用のビルドを意味しますが、iOSのTestFlightで外部テストをする場合はこの設定だとad hoc provisioning profileになってしまいインストールできないので、productionでビルドする必要があります。
eas.jsonの設定が完了したら、ビルドの種類に応じて下記のビルドコマンドを実行して下さい。

```node:console
eas build --profile development --platform ios //or android or all
eas build --profile preview --platform ios //or android or all
eas build --profile production --platform ios //or android or all
```
上記にオプション--auto-submitを追加するとサブミットも自動でやってくれます（ただし下記のeas.jsonの"submit"設定が事前に完了している必要があります）。ビルド後にサブミットする場合は次のサブミットに進みます。一方ビルド完了後にdevelopment clientを使用して実機デバッグする場合は、実機端末にビルド結果をExpoのビルドサイトからインストールしてから下記のコマンドでアプリを起動し、インストールしたdevelopment clientからQRコードで読取り起動します。Expo Goで実機デバッグする場合はビルドする必要は無いのですが、development clientでは一度ビルドした後に実機にインストールが必要なようです。またAndoridのapkでビルドした場合は、実機で開発者モードにすればビルド結果をそのままインストールできるはずです。

```node:console
expo start --dev-client -c --tunnel
```


２．Easサブミット手順と留意点
次にサブミットについてですが、ビルドと同様に下記のような設定をeas.jsonに追加します。これもコピペで中身を修正して使った方が早そうですね。

```expo:eas.json
{
  "build": {
     <上記を参照>
  },
  "submit": {
    "preview": {
      "android": {
        "serviceAccountKeyPath": "../path/to/api-xxx-yyy-zzz.json", //追加
        "track": "internal"
        },
      "ios": {
        "appleId": "your Apple ID",
        "ascAppId": "Apple Dev Consoleから", 
        "sku": "your app's sku from Apple Dev Console",
        "appleTeamId": "Apple Dev Consoleから",
        "language": "jp",
        "companyName": "your company name"
      }
    },
    "production": {
      "android": {
        "serviceAccountKeyPath": "../path/to/api-xxx-yyy-zzz.json",
        "track": "internal"
      },
      "ios": {
        "appleId": "your Apple ID",
        "ascAppId": "Apple Dev Consoleから",
        "sku": "your app's sku from Apple Dev Console",
        "appleTeamId": "Apple Dev Consoleから",
        "language": "jp",
        "companyName": "your company name"
      }
    }
  }
}
```

Androidの設定は問題無いと思いますが(追記：previewにも"serviceAccountKeyPath"が無いと失敗するようなので追加しました。APIの設定等は省略します）、iOSの設定が分かりにくいので捕捉します。"appleId"は文字通りApple IDのメールアドレスですが、"ascAppId"と"sku"はApp Store ConnectのApp情報内の一般情報に記載されている、Apple IDとSKUがそれぞれ該当します。紛らわしいのですがこのApple IDはAppに割り当てられた自動生成IDで10桁の数字です。SKUはApp Store Connectにアプリを新規登録した際に設定したもので、App Storeでは表示されないAppの固有IDです。また"appleTeamId"はDeveloperコンソールのMembershipで確認できます。"companyName"もこのMembershipのTeam Nameをそのままコピーして下さい。以上で設定は完了ですが、実際にサブミットする前にEASビルドが完了していることと、App Store Connectにアプリが登録済みであることが必須です。これらが完了したら下記コマンドで各プロファイルに応じたサブミットを実行して下さい。--latestをオプションで追加すると一番最新のビルドファイルをサブミットしてくれます。なおバージョン番号の管理・設定は別途必要なので、従来通りapp.json上で忘れす行って下さい。

```node:console
eas submit -p ios(or android) --latest --profile development
eas submit -p ios(or android) --latest --profile preview
eas submit -p ios(or android) --latest --profile production
```


３．まとめ
Expoの新しいビルド＆サブミット手法であるEASの使い方を紹介しました。EASは無料プランでも十分活用可能ですので、Expo利用者の方は是非使ってみて下さい。特にEASのサブミット機能は、Google Play Consoleへはもちろん、Apple DeveloperのApp Store Connectへのアプリファイルのアップロードまでほぼ自動化出来ますので（Mac不要）、大変重宝すると思います。

（追記）
以前既にexpoでビルドして問題無かったアプリをEASでビルドし直した際にビルドエラーが頻発したので、参考までに原因を紹介します。ビルドのログを分析した結果原因はパスの設定が相対パスになっていなかったことです。エラー発生場所は全て画像読み込みのrequire(<Path to image file>)で、パスを全て相対パスに変更したら治りました。
またEASでprodution以外のpreview等でビルドしてからサブミットする場合に、EAS側ではサブミットが成功してもAppleから下記のようなエラー通知メールが来ることがありました。
ITMS-90426: Invalid Swift Support - The SwiftSupport folder is missing. Rebuild your app using the current public (GM) version of Xcode and resubmit it.
色々試したのですが、produtionでビルドもサブミットも実行すると一応解決されたので、原因は不明ですが最後はprodutionで試してみて下さい。
EASでサブミットした結果を確認したい時は、EASのビルド画面でどれでも良いのでビルドした物を選択するとビルドの詳細が表示されますが、ここで初めて左サイドに「Submissions」とういメニューが下から二番目に表示されるので、これを選択するとサブミット結果が確認できます（とても分かり難い場所ですね）。
最後にEASサブミットがEASで成功してからApp Store Connect側に反映されるまで30分以上時間がかかる場合があるので、気長に待つようにして下さい。