mcpField
L
limrun-xcode

limrun-xcode

github.com/limrun-incクラウド・DevOps243.2k 回インストール1 日前に更新
リポジトリ

limrun-xcode について

limrun-xcodeは、LimrunのリモートXcode環境でAppleプロジェクトをビルドするスキルです。異なるOSやコンテナから作業する開発者向けで、lim CLIによるソース同期とビルドに加え、Xcodeバージョン選択、ディスクスナップショット、シミュレーターでのXCTestに対応します。

主な機能

  1. 01ソースを同期してリモートビルド
  2. 02Xcodeバージョンの選択と固定
  3. 03ディスクスナップショットの再利用
  4. 04シミュレーターでのXCTest実行
  5. 05リモートコマンド実行とファイル取得

活用シーン

  1. 01ローカルmacOS環境なしでAppleプロジェクトをビルド
  2. 02CIでXCTestを実行して結果を確認
  3. 03ビルド作業間でワークスペースのスナップショットを再利用
  4. 04プロジェクト生成コマンドをリモート実行

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/limrun-inc/skills --skill limrun-xcode

インストール後、Claude Code で/limrun-xcodeを入力して読み込まれたか確認します。

詳細

リモート Xcode ビルド

Linux、Windows、macOS、VM、コンテナーなど、どの環境からでも Limrun のリモート Xcode で Apple プロジェクトをビルドできます。lim xcode build はソースをリモートの Xcode インスタンスに同期してビルドし、シミュレーターが接続されている場合はアプリをインストールして再起動します。このワークフローではリモートインスタンス上でビルドします。ローカルの Xcode、シミュレーター、ビルドツールは使用しません。実行が完了すると、Limrun シミュレーター上でアプリが起動し、検証された状態になります。

アプリ起動後の操作(タップ、入力、要素ツリー、スクリーンショット、録画)には、limrun-ios-simulator スキルを使用してください。Bazel ワークスペースでは、このスキルではなく limrun-bazel を使用してください。

認証と CLI

必要に応じてインストールします:npm install --global lim。認証には lim login または LIM_API_KEY を使用します(.env やシェルに表示されなくても、ユーザーの環境にすでに設定されている場合があります。確認してから尋ねてください)。CLI が信頼できる情報源です。このスキルに記載されているコマンドは検証済みですが、フラグでエラーが発生した場合や、ここに記載されていないフラグが必要な場合は、推測せずに --help を確認してください:

lim xcode --help
lim xcode build --help
lim xcode run --help

ビルド

xcodebuild の代わりに、次のコマンドでビルドします:

lim xcode build .

これにより、記憶されている Xcode ターゲットが作成または再利用され、現在のディレクトリが同期されて、ビルドログが stdout と stderr にストリーミングされます。

プロジェクトに複数のスキームがある場合や、ワークスペースファイルを使用している場合は、--scheme と --workspace を使用します:

lim xcode build . --scheme MyApp --workspace MyApp.xcworkspace

特定の Xcode 構成を指定するには、--configuration Debug または --configuration Release を使用します。省略した場合、Limrun は limbuild のプロジェクト種別ごとのデフォルトを使用します。ネイティブ Xcode ビルドでは Debug、React Native / Expo ビルドでは Release です。

lim xcode build . --configuration Debug
デタッチビルドとログ

--detach を使用すると、ビルドが受け付けられた時点で処理を返せます。Webhook の指定は任意です。logs は exec ID を指定せずに最新のビルドを読み込みます。インスタンス削除後に保持されたログも対象です。完了まで待つには --follow を追加します。

lim xcode build . --detach
lim xcode logs
lim xcode logs --follow
Xcode バージョンを選択する

サンドボックスは、ノードのデフォルトの Xcode(現在は 26.4)でビルドされます。フリートには、各メジャーバージョンのリリース済み(GA)Xcode が 1 つと、Apple がシード版を提供している間はベータ版が 1 つ用意されています。現在は 26.4 GA、27.0 GA、27.1 ベータ版です。選択方法は 2 つあります。

  • メジャーバージョンのみ(27)を指定すると、そのメジャーバージョンの最新 GA リリースが選択されます。ベータ版は選択されず、Apple のポイントリリースに自動で追従します。App Store ビルドにはこちらを使用してください。
  • メジャー.マイナーバージョン(27.1)を指定すると、そのバージョンに固定されます。ベータ版を選ぶ場合はこちらを使用します。

ワークスペースの設定は一度行えば、以降のすべてのビルド、テスト、RBE セッション、新しいサンドボックスに適用されます。フラグを指定すると、そのコマンドに限って設定が上書きされます。

lim xcode version list      # Select is the value to type, Channel is ga or beta; * marks the one in use
lim xcode use xcode@27      # prefer the Xcode 27 GA for this workspace; switches the remembered sandbox now
lim xcode build .           # builds with 27
lim xcode version           # "27.0 (27A266a)" shows the sandbox's current Xcode
lim xcode version set 27.1  # pin the 27.1 beta instead
lim xcode build . --xcode-version 26   # one-off override, not remembered
lim xcode version unset     # forget the preference; the sandbox goes back to the node default

Xcode と mise の選択を組み合わせるには、lim xcode use xcode@27 node@24 を実行します。

スクリプトで使用する場合、lim xcode version list --quiet はセレクターを 1 行に 1 つずつ出力します(26、27、27.1)。--json は { installed, bound, preferred } を返します(installed[].channel は ga または beta です)。表では、現在使用中の Xcode に * が付きます。ノードにないバージョンを lim xcode version set で記録することはできません(エラーに利用可能なバージョンが表示されます)が、サンドボックスが単にビジー状態の場合は設定が保持されます。

サンドボックスで使用中の Xcode がワークスペースの設定と異なる場合、次のビルド時にそのことが通知され、最初に切り替えが行われます。切り替えると、別のバージョンで作成されたビルドキャッシュは無効になり(次のビルドはクリーンな状態から開始します)、ビルド、同期、または lim xcode rbe スタックの実行中は切り替えが拒否されます。永続ディスクスナップショット(--snapshot-key)を使用する場合は、myapp-27 と myapp-27.1 のように、Xcode の系列ごとに個別のキーを使用してください。アーカイブはキーごとに保存され、異なる Xcode で復元すると消去されます。

メジャー.マイナーバージョンの固定は、フリートからそのバージョンが削除されるまで有効です。その後は lim xcode build がデーモンのメッセージとともに失敗し、lim xcode version set 27 または lim xcode version unset の実行を促すヒントが表示されます。ベータ版が GA になると、同じメジャー.マイナーバージョンのセレクターでベータ版が置き換えられます(ビルドは 1 回、クリーンな状態から開始します)。メジャーバージョンのみの指定は、そのメジャーバージョンの最新のリリース済み Xcode に追従するため、ノード上で 27.1 が GA になるとすぐに 27.1 に切り替わります。

ベータ版の Xcode からの App Store へのアップロードは Apple に拒否されるため、--upload-to-appstore ではメジャーバージョンのみの指定(27。27.1 ではありません)を使用してください。betaSeed ではなく channel で判定してください。Apple の 27.1 シード版は、シード番号なしで提供されます。

--dev-server-url は、React Native / Expo ビルドで --configuration Debug を指定した場合にのみサポートされます。これはインストール後に開く URL です。limbuild はこれが解析可能な絶対 URL であることを検証し、接続されたシミュレーターへのインストール後に、変更せずその URL を開きます。フレームワーク固有のスキルが適切な URL を構築します。

lim xcode build . --configuration Debug --dev-server-url '<absolute-url>'

アプリが想定した URL を使わずに起動する場合は、アプリを明示的に開き、ビルド/インストールの問題と URL ルーティングの問題を切り分けてください。

lim ios open-url --id <ios-instance-id> '<absolute-url>'

ディスクスナップショット

Xcode インスタンス間で、ソースファイル、依存関係、DerivedData を再利用します。

CLI 0.35.1 以前では、--snapshot-* の代わりに --cache-* を、 --wait-snapshot の代わりに --wait-cache を使用します。スナップショットへの名称変更後も、 以前のフラグはエイリアスとして引き続き使用できます。

プロジェクトディレクトリから、スナップショットキーを指定して作成し、ビルドしてから削除します。

XCODE_ID=$(lim xcode create --snapshot-key myapp-main --quiet)
lim xcode build . --id "$XCODE_ID" --scheme MyApp
lim xcode delete "$XCODE_ID" --wait-snapshot

初回実行はコールドスタートになります。以降の実行では保存済みのスナップショットが復元されます。正常なビルドの後に同期がなければ、終了時にスナップショットが保存され、同じキーの以前のスナップショットが置き換えられます。--wait-snapshot は保存の完了を待ち、結果を報告します。CI では、ビルドに失敗した場合でもクリーンアップ手順で削除を実行してください。

ワークスペース全体を保存するには、--snapshot-paths を設定しないでください。実行間でプロジェクトフォルダーの名前を変更しないでください。プロジェクト、Xcode のバージョン、同時実行する CI ジョブごとに、別々のキーを使用してください。

ブランチのフォールバックを設定するには、作成時に --snapshot-restore-keys "myapp-pr51,myapp-main" を追加します。各エントリーでは、次のエントリーに進む前に、完全一致するもの、次に一致するリテラルプレフィックスのうち最も新しいものを検索します。このフラグを指定しない場合、保存キーも復元キーとして使用されます。保存せずにスナップショットを再利用するには、復元キーのみを渡します。

スナップショットは作成時に設定してください。復元キーとパスは固定されます。 既存のインスタンスで build --snapshot-key を指定できるのは、スナップショットがすでに有効で、未割り当ての保存キーを割り当てる場合に限られます。このコマンドではスナップショットの復元や有効化はできません。

保存がスキップされる条件、コールドビルド、SDK の使用方法については、ディスクスナップショットガイドを参照してください。

プライベート依存関係の認証情報

--additional-file を使用して既存の認証情報ファイルをコピーします。このフラグは sync でも使用できます。

lim xcode build . \
  --additional-file "$HOME/.npmrc=~/.npmrc" \
  --additional-file "$HOME/.netrc=~/.netrc"

リモート側の ~/ はサンドボックスのホームディレクトリを指します。それ以外の宛先は、ワークスペースからの相対パスです。後続の同期でもファイルを保持するには、フラグを再度指定します。設定で参照されている環境変数には、--env を渡してください。

開発ツールのバージョン

同期後、lim xcode use でサンドボックス内のツールを選択し、不足しているバージョンをインストールします。同期したプロジェクトで選択されているツールをインストールするには、lim xcode tools install を実行してください(詳細)。メジャーバージョンを指定してください。Ruby、Flutter、Mint などの 1.0 未満のツールでは、メジャー・マイナーバージョンを指定します。

lim xcode tools
# Node includes npm/npx, Ruby includes gem, Flutter includes Dart, CocoaPods includes cocoapods-patch.
lim xcode use node@24 pnpm@10 yarn@4 bun@1 [email protected] bundler@4 cocoapods@1 \
  cmake@3 java@jetbrains-21 corretto@21 [email protected] [email protected] \
  xcodegen@2 xcbeautify@3 zsign@1
lim xcode tools install
lim xcode use --cwd apps/mobile node@24
lim xcode tools install --cwd apps/mobile
lim xcode run -- mise use --pin [email protected]

プロジェクトのコマンドを実行する

xcodebuild の前、またはその実行以外でリモート macOS コマンドが必要なリポジトリでは、lim xcode run [relative-cwd] -- <command> を使用します。CLI は最初に現在のディレクトリを同期します。作業ディレクトリは同期されたルートからの相対パスで、既定値は . です。

lim xcode run -- make api
lim xcode run apps/api -- make generate

区切り文字の前に環境変数を渡します。同じインスタンスに必要なソースの状態がすでにある場合に限り、--no-sync を使用してください。

lim xcode run --env API_ENV=development -- npm run generate
lim xcode run --no-sync -- make api

サンドボックスには Node、Ruby、CMake、Mint、mise、Homebrew が含まれています。mise、Mint、Homebrew でインストールしたツールは、インスタンスのサンドボックスホームに保存され、そのインスタンスで後続のコマンドを実行する際にも引き続き使用できます。

lim xcode run -- 'mise trust && mise install'
lim xcode run -- 'mint install apollographql/apollo-ios-cli'
lim xcode run -- brew install tree

コマンドは一度限りで、非対話型です。TTY や stdin チャネルはありません。

サンドボックスのファイルをダウンロードする

lim xcode pull-file <remote-path> [destination] --id <instance-ID> を使用します。 パスには、絶対パスまたは同期されたプロジェクトルートからの相対パスを指定できます。 テキスト、バイナリ、base64 の内容を含め、ビルドログや実行ログを使ってファイルを転送しないでください。 ファイルを書き込むコマンドの完了を待ってください。ディレクトリは先にアーカイブし、インスタンスを削除する前にダウンロードしてください。

生成された Xcode プロジェクト(XcodeGen)

リポジトリに project.yml があり、.xcodeproj が Git の追跡対象外になっている場合は、ローカルで xcodegen を実行せず、プロジェクトがないことをエラーとして扱わないでください。リモートサンドボックスでは、ビルド前に project.yml からプロジェクトを生成します。

lim xcode build .

仕様ファイルはリポジトリのルート、または 1 つ下のディレクトリ(ios/ など)にあります。フラグは不要です。ビルドのたびにプロジェクトが再生成されるため、project.yml の編集は再ビルドするだけで反映されます。コミット済み、または強制同期された .xcodeproj が常に優先されます。サンドボックスでプロジェクトが生成されるのは、同期によってプロジェクトが提供されなかった場合のみです。

リポジトリのコード生成処理によって、ビルドに必要な Git の追跡対象外の入力(生成されたローカル Swift パッケージや、設定から生成されるソースなど)が作成される場合は、その処理を先にローカルで実行し、--include を使って出力を強制同期してください。

make generate   # or whatever the repo's codegen step is
lim xcode build . --include '^ios/GeneratedKit/'

--include で指定するのは、gitignore の構文ではなく、--ignore と同じ正規表現です。ディレクトリ全体が無視されている場合、そのディレクトリ内のファイルを対象にするには、上記のようにディレクトリのパス自体にも一致するパターンが必要です。

シミュレーターで実行する

lim xcode build はビルドとインストールを行います。ユーザーがアプリを見る、または操作する必要があるまでは、シミュレーターを接続しないでください。状態の確認と接続は次のとおりです。

lim xcode get             # is a simulator already attached?
lim ios create --attach   # attach one (installs the last build immediately)

ユーザーに表示するブラウザーがない場合は --no-open を追加してください。ローカルでストリーム URL を開かず、共有用に URL を出力します。

接続時の出力に署名付きストリーム URL が含まれている場合は、[Live simulator](<signed-stream-url>) のような Markdown リンクとしてユーザーに共有してください。

シミュレーターが接続されている場合、lim xcode build が成功するたびにアプリが自動的に再インストールされ、再起動されます。別途インストールする手順は不要です。タップ、入力、要素ツリーの読み取り、スクリーンショットの撮影、録画を行うには、limrun-ios-simulator に切り替えてください。

テストを実行する(XCTest)

lim xcode test はサンドボックスでスキームのテストターゲットをビルドし、接続されたシミュレーター上で実行します(ユニットテストと UI テストの両方が対象です)。各テストケースにつき 1 行の結果がストリーミングされます。テストが 1 つでも失敗すると、実行コマンドはゼロ以外の終了コードを返すため、CI のゲートとして使用できます。

lim xcode test .
lim xcode test ./MyProject --scheme MyApp

lim xcode build --ios と同様に、シミュレーターを使うターゲットを自動取得します。また、繰り返し実行する際はインスタンスを再利用するため、すばやく試行を繰り返せます。スキームにはテストアクションが設定されている必要があります(Xcode の共有スキームでは、プロジェクトにテストターゲットがある場合、テストアクションが設定されています)。--xcode-version 27 を指定すると、そのメジャーバージョンの GA(27.1 を指定した場合はベータ版)でテストをビルドします。シミュレーターはフリートのデフォルトランタイムを引き続き使用するため、警告が表示されたうえで実行されます(ランタイムに依存する失敗が起こる可能性があります)。

xcodebuild の識別子形式 Target[/Class[/method]] を使って、テスト対象を選択できます。複数の項目を指定するには、フラグを繰り返してください。この 2 つのフラグは同時に指定できません。

lim xcode test . --only-testing MyAppTests/LoginTests/testValidLogin
lim xcode test . --skip-testing MyAppUITests

ターゲット名だけを指定すると、そのターゲット全体が選択またはスキップされます。ビルドで生成されなかったターゲットを指定する --only-testing の項目があると、すべてのテストを黙って実行するのではなく、実行が失敗します。

機械処理向けには、--json を指定すると、テストケースごとの未加工イベントが NDJSON でストリーミングされ、最後に {"exitCode": N} レコードが出力されます。

lim xcode test . --json > results.ndjson

--build-only はシミュレーターを取得せずにテストターゲットをコンパイルします。生成物は後で実行できるよう、サンドボックスに保持されます。

多くのテストスイートを連続して実行したインスタンスで、UI テストが最初の操作時に失敗する場合は、次回の実行で --inactivity-timeout 30m を指定し、新しいインスタンスを使用してください。

署名済みデバイスビルド(IPA)

ユーザーが App Store Connect チームの API キーを持っている場合は、Apple のクラウド署名を優先してください。 Apple がクラウド管理の証明書とプロビジョニングプロファイルを作成または再利用するため、ユーザーが p12 や .mobileprovision を用意する必要はありません。キー ID、発行者 ID、.p8 ファイルは、フラグまたは環境変数としてユーザー自身のマシン上で設定されます。会話の中で値を尋ねないでください。

lim xcode build . --sdk iphoneos --configuration Release \
  --signing-method release-testing --team-id "$APPLE_TEAM_ID" \
  --asc-key-id "$ASC_KEY_ID" --asc-issuer-id "$ASC_ISSUER_ID" \
  --asc-key AuthKey.p8 \
  --upload myapp.ipa

署名方法:

  • debugging:登録済みの開発デバイス向けの開発署名済み IPA。
  • release-testing:登録済みのテストデバイス向けの配布署名済み IPA。
  • app-store-connect:App Store Connect 向けの配布署名済み IPA。

クラウド署名にはデバイス SDK(--sdk iphoneos または --sdk watchos)、発行者 ID を含むチーム API キー、およびそのキーの Apple Developer チームと一致する --team-id が必要です。配布方法では、API キーは Admin キーであるか、クラウド管理の配布証明書へのアクセスが有効になっている必要があります。Cloud signing permission error は、その権限が不足していることを意味します。No Account for Team は、チーム ID と API キーが一致しないことを意味します。Failed Registering Bundle Identifier は、バンドル ID が別のチームに属しており、自動登録できないことを意味します。

クラウド署名では、--entitlements からのみエンタイトルメントが取得され、プロジェクトの .entitlements ファイルからは取得されません。アーカイブは未署名であり、エクスポート時にエンタイトルメントが保持されるのは既存のコード署名からのみだからです。ケイパビリティ(HealthKit、CloudKit、アプリグループ、プッシュ通知)を使用するアプリでは、必ずこのフラグを渡してください。渡さないと、ケイパビリティは IPA から警告なく削除されます。パスだけを指定するとアプリが対象になり、<bundleId>=<path> を指定すると埋め込みバンドル(ウィジェット、watch アプリ)が対象になります。バンドルごとに指定してください。

lim xcode build . --sdk iphoneos --configuration Release \
  --signing-method release-testing --team-id VMBY3VYW4U \
  --asc-key-id 2X9R4HXF34 --asc-issuer-id "$ASC_ISSUER_ID" \
  --asc-key AuthKey.p8 \
  --entitlements ./MyApp/MyApp.entitlements \
  --entitlements com.example.myapp.widgets=./Widgets/Widgets.entitlements \
  --upload myapp.ipa

plist の値はすべて完全に展開しておく必要があります($(AppIdentifierPrefix) は使用せず、具体的なプレフィックスを記述してください)。また、エクスポート管理キー(application-identifier、com.apple.developer.team-identifier、get-task-allow、beta-reports-active)は含めないでください。すべてのケイパビリティを開発者ポータルの App ID で有効にしておく必要があります。有効になっていない場合、エクスポートは該当するケイパビリティ名を示して失敗します。

ユーザーがすでに p12 とプロファイルを持っている場合は、手動署名も引き続き利用できます。

lim xcode build . --sdk iphoneos --configuration Release \
  --certificate-p12 dist.p12 --certificate-password "$P12_PASSWORD" \
  --provisioning-profile app.mobileprovision \
  --upload myapp.ipa

アップロード出力には、署名済み IPA のダウンロード URL が含まれます。ビルドが SUCCEEDED であれば、署名はすでにサーバー上で Apple の検証に合格しています。ユーザーから依頼されない限り、IPA を自分で再検証しないでください。署名が無効な場合は、壊れた成果物を生成せず、ビルドが明確に失敗します。

アプリに拡張機能(WidgetKit ウィジェット、共有シート、インテント)または watch アプリが含まれる場合、App Store 署名にはバンドル ID ごとに 1 つのプロビジョニングプロファイルが必要で、すべて同じ配布証明書で発行されていなければなりません。バンドルごとに --provisioning-profile を繰り返し指定してください。各プロファイルは、内部の application-identifier に基づいてバンドルと照合されるため、順序は問いません。

lim xcode build . --sdk iphoneos --configuration Release \
  --certificate-p12 dist.p12 --certificate-password "$P12_PASSWORD" \
  --provisioning-profile app.mobileprovision \
  --provisioning-profile widgets.mobileprovision \
  --upload myapp.ipa

複数のプロファイルを使用する場合、すべてのプロファイルに明示的な(ワイルドカードではない)バンドル ID が必要です。signing preflight failed: no provisioning profile covers ... エラーには、プロファイルが不足している埋め込みバンドル名が示されます。そのバンドル ID と完全に一致するプロファイルをユーザーに依頼してください。

リーフ証明書だけでなく、CA チェーン全体を含む p12 を使用してください。必要に応じて、チェーンも含めて再エクスポートしてください。

openssl pkcs12 -export -inkey dist.key -in dist.pem -certfile wwdr.pem -out dist-chain.p12

ビルド出力で確認するエラー文字列:

  • Unknown issuer hash:p12 に CA チェーンがありません。上記のようにチェーンも含めて再エクスポートしてください。
  • code signature verification failed:プラットフォームの署名後チェックで成果物が拒否されました。ユーザーのコードに問題があるわけではありません。再試行し、解消しない場合は報告してください。
  • p12 のパスワードエラー:--certificate-password がファイルと一致していません。ユーザー自身のマシンで値を修正してください。

App Store Connect へのアップロード

署名済み IPA を TestFlight または App Store 配信用に App Store Connect へアップロードするには、署名済みデバイスビルドで App Store Connect API キーフラグとともに --upload-to-appstore を指定します。

lim xcode build . --sdk iphoneos --configuration Release \
  --certificate-p12 dist.p12 --certificate-password "$P12_PASSWORD" \
  --provisioning-profile app.mobileprovision \
  --upload-to-appstore --asc-key-id "$ASC_KEY_ID" --asc-issuer-id "$ASC_ISSUER_ID" \
  --asc-key AuthKey.p8

クラウド署名では、同じ API キーを使って署名とアップロードを行えます。

lim xcode build . --sdk iphoneos --configuration Release \
  --signing-method app-store-connect --team-id "$APPLE_TEAM_ID" \
  --asc-key-id "$ASC_KEY_ID" --asc-issuer-id "$ASC_ISSUER_ID" \
  --asc-key AuthKey.p8 \
  --upload-to-appstore --auto-build-number

--upload-to-appstore を使用するには、クラウド署名または手動署名フラグに加えて、--asc-key-id と --asc-key が必要です。ユーザーが Asset Storage にも IPA を保存したい場合は、--upload <asset-name> と組み合わせてください。

デバイス用 IPA にはアプリのシンボルが含まれるため(Payload/ の隣にある Symbols/)、App Store Connect は別途 dSYM をアップロードしなくてもクラッシュレポートをシンボリケートできます。これには、ビルドで dSYM が生成される必要があります。--configuration Release ではデフォルトで生成されますが、Debug では生成されず、その場合 IPA にシンボルは含まれません。

ユーザーはこれらを自分のマシン上で、フラグまたは CLI がローカルで読み取る環境変数として指定します。会話に貼り付けるものではありません。3 つとも App Store Connect の「Users and Access」ページにある「Integrations」タブの「App Store Connect API」にあります。

  • --asc-key-id:API キーの隣にある Key ID です。まだ持っていない場合は、Developer ロールの Team Keys を案内してください。ビルドをアップロードできる最小権限のロールです。チームキーの作成には Admin アカウントが必要です。
  • --asc-issuer-id:「Integrations」ページの最上部にある Issuer ID です(キーごとの値ではなく、チームの値です)。クラウド署名にはチームキーとこのフラグが必要です。手動署名とアップロードの場合は、個人用 API キーであれば省略してください。
  • --asc-key:ダウンロードした .p8 ファイルのパスです。Apple はコピーを保持せず、ページを離れるとダウンロードリンクは消えます。ユーザーがファイルを紛失した場合は、新しいキーを生成する必要があります。.p8 をコミットしたり、内容をファイルに貼り付けたりしないでください。ファイルシステム上のパスを指定してください。

デフォルトでは、アップロードのコミットが完了するとすぐにビルド処理が戻り、Apple の処理結果は App Store Connect に任せます(処理には通常、何分もかかります)。結果が出るまで待ってから戻るには、--asc-wait-timeout <seconds>(最大 1800)を指定します。最終行で結果を確認してください。

  • App Store Connect: upload accepted.:完了です。Apple の処理が終わると、ビルドが TestFlight に表示されます。
  • App Store Connect: uploaded, still processing on Apple's side (upload <id>).:終了コードは 0 で、アップロードは成功しています。Apple 側で処理中です。ビルドを再試行しないでください。
  • App Store Connect upload failed; the build and signing succeeded.:終了コードは 1 で、Apple のエラーテキストはログの前の方にあります。失敗したのは配信のみです。

認識すべきエラー文字列:

  • バンドルバージョンがすでに使用されているという Apple のメッセージ:CFBundleVersion を更新して(Expo の場合は app.json の expo.ios.buildNumber)、再ビルドします。
  • HTTP 401:キー ID/Issuer ID/.p8 の不一致、またはキーが失効しています。
  • HTTP 403:キーのロールではビルドをアップロードできません。Developer ロール以上が必要です。
  • no App Store Connect app with bundle id:アプリレコードがありません。API では作成できないため、ユーザーが App Store Connect で手動作成する必要があります。
  • ビルド後、TestFlight で「Missing Compliance」のままになる:ビルド時にアプリが輸出コンプライアンスに関する質問に回答していません。Info.plist で ITSAppUsesNonExemptEncryption を NO に設定し(Expo の場合は app.json で expo.ios.config.usesNonExemptEncryption: false)、再ビルドしてください。

テスターへの配信を自動化するには、アプリの内部 TestFlight グループで自動配信を有効にし(作成時のみ設定可能)、上記のコンプライアンスキーを設定する必要があります。そうすれば、アップロード後の作業は一切不要です。

プレビュービルド

プルリクエストで再現可能なプレビューを作成するには、パッケージ化された iOS プレビューアクションを優先してください。 アプリをビルドしてアップロードし、PR のプレビューコメントを更新して、ビルダーをクリーンアップします。入力項目とワークフローの例については、リポジトリを参照してください。

ユーザーからプレビュービルドを求められた場合、または PR を作成する場合にのみ、再利用可能なプレビューアセットを作成してください。ビルドしてアップロードします。

ASSET_NAME="<bundle id / pr number / or any session identifier>.zip"
lim xcode build . --upload ${ASSET_NAME}
# Debug preview build:
lim xcode build . --configuration Debug --upload ${ASSET_NAME}

ビルドのアップロードでは、デフォルトで TTL が 14 日に設定されます。アップロードするたびに、アセットの有効期限がその日から 14 日後に延長されます。変更するには、Go の duration(例: 720h。1dは無効です)を指定して --upload-ttl を渡してください。

次にプレビューリンクを作成し、最後のメッセージに含めてください(PR を作成する場合は、PR にも含めてください)。

https://console.limrun.com/stream?asset=${ASSET_NAME}&platform=ios

注意点

  • ビルドエラーへの対応も作業の一部です。 ビルドに失敗した場合は、エラー出力を確認し、コードを修正して再ビルドしてから報告してください。
  • プロジェクトの mise ファイルに、ビルドで使わないツールが含まれていることがあります。 サンドボックスで最初にビルドまたは実行すると、同期された mise ファイル内のすべての [tools] エントリに対して mise install が実行されます。そのため、データベースやクラウド CLI が大量に記載されたモノレポのルート mise.toml は、処理を遅くしたり失敗させたりする可能性があります。問題なく動作する場合は、引き続きプロジェクトファイルを使用してください。動作しない場合は、その隣にビルドで使うツール(たとえば node や pnpm)のみを記載した mise.limrun.toml を追加してください。そのディレクトリでは、Limrun は他の mise ファイルではなく、このファイルを読み込みます。
  • Xcode の埋め込みサンドボックスは廃止されました。 TypeScript SDK(0.54.0 以降)と lim(0.35.0 以降)は、iOS インスタンス内に Xcode サンドボックスを作成しなくなりました。アップグレード後に、iosInstances.create で 'sandbox' does not exist in type 'Spec'、コードが status.sandbox.xcode.url を読み取る箇所で Property 'sandbox' does not exist on type 'Status'、または lim xcode コマンドで Expected an Xcode instance (sandbox_...), got ios_... が発生する場合があります。Xcode サンドボックスを単独で作成し、シミュレーターをアタッチしてください。既存のシミュレーターには lim ios create --xcode、または lim xcode create --attach --simulator-id <ios-instance-id> を使用します。SDK では、クライアント上で xcodeInstances.create の後に attachNewSimulator() または attachSimulator(iosInstance) を呼び出します。lim xcode コマンドには sandbox_ ID を、lim ios コマンドには ios_ ID を渡してください。詳細: https://docs.limrun.com/docs/ios/build-with-xcode#moving-off-the-embedded-xcode-sandbox
  • lim ios コマンドのインスタンス ID。 これらのコマンドは、現在のインスタンスを cwd の Git ワークツリーから解決するため、No instance ID provided and no recent ios instance found で失敗する場合があります。lim xcode get で ID を取得し、--id <ios-instance-id> を渡してください。詳しい手順は、limrun-ios-simulator の「Targeting the right instance」セクションを参照してください。
  • バンドル ID の確認。 バンドル ID がわからない場合は、Xcode プロジェクトファイルを確認するか、ビルドの成功後に lim ios list-apps を実行してください。
  • 認証が必要なコマンドで認証エラーが発生する場合は、セッションの期限が切れているか、LIM_API_KEY が誤っています。ユーザーのマシンで lim login を実行すると、セッションを更新できます。
  • ビルド設定は Limrun のデフォルトを上書きします。 --build-setting KEY=VALUE は環境変数形式の任意のキーを受け入れ、同じキーの管理値を置き換えます。デバイス向けビルドではすでに標準アーキテクチャが使用され(埋め込みの Watch アプリでは arm64_32 が維持されます)、カバレッジ計測も無効になっているため、App Store へのアップロードに追加の設定は不要です。
  • ビルド成功後にアーティファクトが見つからない場合。 サーバーは、スキーム名とプロダクト名が異なる場合(スキーム「MyApp Dev」で MyApp-dev.app をビルドする場合など)も含め、ビルドされた .app を自動的に解決します。それでもアップロードが built artifact not found で失敗する場合は、--artifact-name MyApp-dev.app を使って、バンドルファイル名全体を明示的に渡してください(.app 拡張子も含めます)。この場合、サーバーはその名前をビルド成果物からそのまま取得します。
  • 同期するファイルは小さく保ってください。 1 つのファイルが約 2 MB 以上あると、ビルド開始前にクライアント側の同期が ENOMEM で失敗する場合があります。大きなアセットは圧縮してください。
  • シンボリックリンクが同期されるのは、相対パスで同期対象フォルダー内に収まる場合です。 ターゲットが絶対パスのシンボリックリンクは警告とともにスキップされます。ビルドで必要な場合は、相対パスのターゲットで作り直してください。同期対象フォルダーの外に出る相対リンクがあると同期に失敗します。そのリンクを --ignore で除外するか、ターゲットを含むリポジトリのルートから同期してください。
  • 署名エラーは明確に表示されます。 Unknown issuer hash は p12 に CA チェーンが含まれていないことを意味するため、チェーンを含めて再エクスポートしてください。code signature verification failed は、プラットフォームの署名後チェックでアーティファクトが拒否されたことを意味します。これはコードの問題ではないため、再試行するか、そのまま報告してください。

コメント