リンクをコピーしました

Expo で作っている 自作中のアプリ を iOS で配布するにあたり、まずは EAS Local で Mac 上に IPA を作り、TestFlight に上げるところまで試しました。
eas build --local を使えば、Expo のクラウドに任せずローカルのXcodeでビルドできます。
記録用に template-expo-build-cicd というテンプレートリポジトリも作ったので、つまづいたところを共有しながらメモとして残します。

EAS と App Store Connect の連携や証明書まわりは、すでに別プロジェクトで触っていたので今回はスムーズに進みました。
初めての場合は EAS Build の公式ドキュメント を一度読んでおくと安心です。

サンプルリポジトリ

この記事の手順はテンプレートとして作った template-expo-build-cicd をベースに試しました。
eas.json やビルド・提出の設定が入っているので、Bundle ID などを自分のものに差し替えて使えます。

git clone https://github.com/testkun08080/template-expo-build-cicd.git
cd template-expo-build-cicd
npm ci

clone 後に差し替える項目

テンプレートには筆者用の値が入っているので、ビルド前に次を自分のものに変えてください。

ファイル差し替える項目
app.jsonios.bundleIdentifier / extra.eas.projectId
eas.jsonsubmit.production.iosappleId / ascAppId / appleTeamId

extra.eas.projectIdeas init で自分の Expo プロジェクトに紐づけ直すのが確実です。
テンプレートの projectId のまま eas build すると、別のアカウントのプロジェクトに繋がってしまいます。

テンプレートの app.json(抜粋)

{
  "expo": {
    "name": "template-expo-build",
    "slug": "template-expo-build",
    "ios": {
      "bundleIdentifier": "com.testkun08080.template-expo-build",
      "infoPlist": {
        "ITSAppUsesNonExemptEncryption": false
      }
    },
    "extra": {
      "eas": {
        "projectId": "a77f74e1-5302-47a4-a581-eace64b7f025"
      }
    }
  }
}

bundleIdentifier は App Store Connect 側の Bundle ID と揃えます。
projectId は自分の EAS プロジェクトの値に差し替えます。

テンプレートの eas.json(抜粋)

Local ビルドでは production-local(中身は production の継承)か、そのまま production を使います。

{
  "cli": {
    "version": ">= 15.0.0",
    "appVersionSource": "remote"
  },
  "build": {
    "base": {
      "node": "20.18.0"
    },
    "production": {
      "extends": "base",
      "channel": "production",
      "autoIncrement": true,
      "ios": {
        "resourceClass": "m-medium"
      }
    },
    "production-local": {
      "extends": "production"
    }
  },
  "submit": {
    "production": {
      "ios": {
        "appleId": "REPLACE_WITH_APPLE_ID",
        "ascAppId": "REPLACE_WITH_ASC_APP_ID",
        "appleTeamId": "REPLACE_WITH_APPLE_TEAM_ID"
      }
    }
  }
}
  • appleId — Apple ID(メールアドレス)
  • ascAppId — App Store Connect の App Information にある Apple ID(数字)
  • appleTeamId — Apple Developer の Team ID

この3つを自分の値に書き換えておくと、あとで eas submit が楽です。

EAS Cloud と Local の使い分け

EAS CloudEAS Local
Mac 必須不要必須(Xcode 26.x)
ビルド場所Expo サーバー自分の Mac
主な用途手軽・CI 向きネイティブ周りのデバッグ
ビルドログダッシュボードターミナルに直接出る

普段は Xcode Cloud で回していますが、同じことを EAS Local でも経験しておくと、署名まわりのトラブルが起きたときに切り分けしやすいと感じました。

前提

  • Apple Developer Program への登録済み
  • App Store Connect にアプリを登録済み(Bundle ID が確定していること)
  • eas.json の production プロファイルが設定済み
  • eas login 済み
  • Xcode 26.2 がインストール済み(Expo SDK 55 向け)
  • Node.js 22 系

Xcode のバージョン確認:

xcodebuild -version

App Store Connect と Bundle ID

TestFlight に上げるには、先に App Store Connect でアプリを作っておく必要があります。
app.jsonios.bundleIdentifier と同じ Bundle ID を選びます。

Bundle ID まわりは次のどちらかで進められます。

  1. Identifiers の作成ページで先に作る
  2. ビルドしながら対話で作る
npx eas-cli build --profile production --platform ios --local

後者だと、証明書と Bundle ID をその場で作ってしまう流れにもできます。
僕はテンプレを使うときは、先に Bundle ID を決めて app.json に書いておく方が迷いが少なかったです。

その後、新規アプリの作成も行います。

App Store Connect で新規アプリを作成

作成後、App InformationApple ID(数字)を eas.jsonsubmit.production.ios.ascAppId に入れておきます。
テンプレートだとプレースホルダのままなので、例えばこう書き換えます。

{
  "submit": {
    "production": {
      "ios": {
        "appleId": "your-apple-id@example.com",
        "ascAppId": "1234567890",
        "appleTeamId": "ABCD123456"
      }
    }
  }
}

ascAppId は下のスクショの数字です。appleIdappleTeamId も一緒に入れておくと、提出時の対話が減ります。

App Store Connect の Apple ID(ascAppId)

Apple Developer 側でも、同じ Bundle ID が登録されていることを確認します。

Apple Developer の Bundle ID

EAS プロジェクトの作成

初回の eas build では、EAS プロジェクトがまだ紐づいていないことがあります。
対話形式で「自動作成しますか?」と聞かれたら Y で進めれば、app.jsonprojectId が付与されます。

Expo ダッシュボードのプロジェクト一覧
EAS プロジェクトの自動作成プロンプト

署名のセットアップ

Local ビルドでも、初回は eas credentials で Distribution 証明書とプロビジョニングプロファイルを EAS に登録しておくのが楽でした。
fastlane match のように証明書用 Git リポジトリは不要です。

eas credentials

Platform で iOSproduction を選ぶと、Apple Developer へのログインや証明書作成が走ります。

Apple Developer の証明書一覧
Distribution 証明書の詳細

EAS ダッシュボードの Credentials で、証明書とプロビジョニングプロファイルが Valid になっていれば OK です。

Expo Credentials — 証明書とプロビジョニングプロファイル

対話形式のセットアップが終わると、ターミナルにプロビジョニングプロファイル作成完了のメッセージが出ます。

プロビジョニングプロファイルの作成完了

ローカルビルドを実行する

依存関係を入れてから、ローカルビルドを実行します。

npm ci --legacy-peer-deps
eas build --platform ios --local --profile production \
  --output ./build.ipa

初回は --non-interactive を外して対話形式で進めると、足りない設定に気づきやすいです(後述)。

僕が遭遇したエラー

.xcworkspace を Xcode で開いて Archive は成功するのに、EAS Local だけ失敗したことがありました。
ログを見ると、プロビジョニングプロファイルに署名証明書が含まれていない、という内容でした。

[RUN_FASTLANE]
❌  Provisioning profile "*[expo] com.testkun08080.template-expo-build AppStore 2026-07-10T07:25:34.991Z" doesn't include signing certificate "Apple Distribution: myname (XXXXXXXX)". (in target 'templateexpobuild' from project 'templateexpobuild')

切り分けの手順

まずクラウドビルドで署名まわりが通るか確認しました。

npx eas-cli build --profile production --platform ios --clear-cache

僕の環境ではクラウドは問題なく通ったので、Mac のキーチェーンと EAS に登録されている証明書の食い違い が原因だと判断しました。

手元のMacとの証明書の比較にDeveloper ポータルから .cer をダウンロードして比較します。

証明書のダウンロード

キーチェーンアクセスで distri などと検索すると、Distribution 証明書が見つかります。
Local ビルドでハマったときは、ここに表示される証明書と EAS 側の証明書が一致しているかを確認しました。

キーチェーンアクセスで Distribution 証明書を検索

次を順に確認します。

security find-identity -v -p codesigning
  • キーチェーンアプリで Distribution 証明書を検索する(上の ss10)
  • EAS Credentials に表示されている Distribution 証明書と一致するか
  • Apple Developer でダウンロードした .cer のシリアルナンバーが同じか

一つでも違うと、上記の Provisioning profile エラーになります。
古い証明書がキーチェーンに残っているケースも多いので、使わないものは削除するか、EAS 側の証明書に合わせて作り直すのが早いです。

ビルド成功

証明書を揃えたあと、同じコマンドで Local ビルドが通りました。
カレントディレクトリに build.ipa が出力されます。

ローカルビルドの完了

TestFlight に提出する

eas submit --platform ios --path ./build.ipa

eas.jsonsubmit.production.ios.ascAppId が設定されていれば、提出先は自動で解決されます。
初回は暗号化に関する質問が出るので、HTTPS だけ使っている一般的なアプリなら Y で進めます。

暗号化に関する確認プロンプト

non-interactive フラグについて

--non-interactive は CI やスクリプト実行向けです。
署名や EAS プロジェクトの初回セットアップが終わってから付けるのが安全です。

eas build --platform ios --local --profile production \
  --output ./build.ipa --non-interactive

よくあるトラブル

プロビジョニングプロファイルと証明書の不一致

今回いちばん時間を取られたのがこれです。
Xcode の Archive が通っても EAS Local が落ちるときは、キーチェーン・EAS・Apple Developer の3か所で Distribution 証明書のシリアルナンバーを突き合わせてみてください。

ディスク容量

Local ビルドは DerivedData や Pods を Mac 上に展開するため、数 GB の空き容量があると安心です。

まとめ

  • eas build --local で Mac 上に IPA を生成できる
  • 提出は eas submit --path ./build.ipa で Cloud ビルドと同じ
  • 署名トラブルはキーチェーンと EAS Credentials の突き合わせが近道
  • ネイティブ周りのデバッグに向くが、Xcode 26.x とディスク容量が必要

次の記事では、EAS Cloud でクラウドビルドする方法を紹介します。
Localでやるのと比べたら二つぐらいのコマンドで終わるので簡単です。。。

Expo × EAS Cloud でローカルから TestFlight に上げる

関連リンク