マージとリリースを担う方へ

次のマージは、専用ビルドノードに任せましょう

まず検証可能なipaを手動でビルドし、その後CIに処理を任せます。起動、接続、CIへの登録、配布、日常の運用の順に進められるため、既存のパイプラインを最初から作り直す必要はありません。

1時間程度での導入を目指す手順ですが、所要時間を保証するものではありません。大容量の依存関係のダウンロード、Xcodeのインストール、署名用ファイルの準備により時間は変わります。ノードを受け取り済みの場合は、接続確認から始めてください。

起動前に必要な情報を確認

プロジェクトに合ったノードを選ぶ

ビルドがたまにしかなく、使っていないMacがある場合は、自前で運用する方が低コストかもしれません。マージのたびにビルドする、電源・ネットワーク・冷却を自分で管理したくない場合は、専用ノードのレンタルをご検討ください。OSXPortではMac miniを物理ノードとして提供し、1台を1社のお客様専用でご利用いただけます。仮想マシンではありません。

  1. 01

    プロジェクトの前提を確認

    再現可能なビルドコマンド、コードへのアクセス方法、必要なXcodeのバージョン、依存関係のロックファイルを用意します。まずはアプリ1つ、scheme1つ、ブランチ1つで始めましょう。初回導入でリリースシステム全体を移行する必要はありません。

  2. 02

    構成と利用期間を選ぶ

    注文ページで機種、地域、日・週・月・四半期単位の利用期間を選択します。Port M4 Baseは軽い試用に、複数ブランチのビルドやシミュレーターの利用にはPort M4 Plusが適しています。大規模なマルチターゲットプロジェクトではPort M4 Proをご検討ください。

  3. 03

    ノード情報を保存

    注文後、コントロールパネルでノードのアドレス、接続ユーザー名、認証情報を確認します。利用可能な状態かどうかは、コントロールパネルの最新表示をご確認ください。ノードIDをチームの資産台帳に記録し、ログインパスワードをリポジトリやチケット本文に記載しないでください。

  4. 04

    近い地域を選ぶ

    シンガポール、日本(東京)、韓国(ソウル)、香港、米国西部から選べます。チームの所在地だけでなく、リポジトリや依存関係の取得元の場所も考慮してください。地域をまたぐネットワークの実性能は、実際の取得・アップロード処理でご確認ください。

3つの構成をご用意しています。Apple Silicon M4・ユニファイドメモリ16GB・SSD 256GB、Apple Silicon M4・ユニファイドメモリ24GB・SSD 512GB、Apple Silicon M4 Pro・ユニファイドメモリ64GB・SSD 2TBです。初回の導入では並列数を増やしすぎず、まず1回のビルドに必要なメモリ、ディスク容量、成果物のサイズを記録しましょう。

まずノードを確認してからCIへ

ログインからビルド、書き出しまで同じユーザーで実行

初回接続では、ノードのアドレスとユーザーを確認してから開発ツールを調べます。以下はセッションの例であり、実際のノード出力ではありません。バージョン番号は表示形式の例です。実際の結果はノード上で実行して確認してください。

環境を再インストールする前に、3つの層を確認

接続:コントロールパネルに表示されたアドレス、ポート、ユーザー名で接続します。初回接続時はホストのフィンガープリントを確認してください。予期せず変わった場合は、ノードが交換されたかを確認し、検証をそのままスキップしないでください。タイムアウトする場合はアドレスとネットワークを、認証に失敗する場合はユーザー名と認証情報を確認します。

ツール:まず xcode-select -p で現在の開発者ディレクトリを確認し、 xcodebuild -version でバージョンを記録します。プロジェクトで別のバージョンが必要な場合は、インストール済みであることを確認してからパスを明示的に切り替えます。

プロジェクト:プロジェクトのディレクトリでロックされた依存関係をインストールし、既存のビルドコマンドを手動で実行します。対話型ログインで成功しても、バックグラウンドのrunnerが署名用ファイルにアクセスできるとは限りません。後でrunnerの実行ユーザーでも必ず確認してください。

以下の例では、 NODE_USER と NODE_ADDRESS にコントロールパネルで通知された値を設定します。App.ipa は成果物名の例です。Bundlerでfastlaneを管理しているプロジェクトでは、プロジェクトの規約に従って bundle exec fastlane gymを実行してください。

osxport · tokyo-node
$ ssh "$NODE_USER@$NODE_ADDRESS"
$ xcode-select -p
/Applications/Xcode.app/Contents/Developer
$ xcodebuild -version
Xcode 16.4
Build version 16F6
$ cd ~/workspace/App
$ fastlane gym
Creating archive
Exporting archive
Successfully exported and compressed dSYM file
Successfully exported and signed the ipa file
Exported ipa: ./build/App.ipa
$ ls -lh ./build/App.ipa

確認項目:リモートコマンドが正常終了し、バージョンがプロジェクトの要件を満たし、成果物のパスが存在すること。署名やコンパイルに失敗した場合は、最初のエラーの前後を含むログを保存してください。最後の1行だけを切り取らないでください。

既存のCIをそのまま活用

runnerを登録する前に、手動タスクを1つ成功させる

いずれの方法でも、macOSの物理ノード上で実行します。以下のチーム人数は運用方法の目安であり、処理能力を保証するものではありません。1回のビルドに必要なメモリ、同時に実行するシミュレーターの数、ディスク使用量をもとに並列数を決めてください。

GitHub Actionsの自ホスト型runner

おすすめ:約3~15人で、ワークフローファイルを使って共同作業しているチームに適しています。別途スケジューラーを構築せず、管理対象のリポジトリまたは組織にノードを登録できます。

  1. リポジトリまたは組織の設定から、macOSとチップアーキテクチャに合ったrunnerのインストーラーと登録コマンドを取得します。
  2. 専用の実行ユーザーで登録し、チーム独自のラベルを追加して、ワークフローの runs-on をそのラベルに設定します。
  3. まずバージョン確認と機密情報を含まないビルドを実行してから、バックグラウンドサービス、シークレットの注入、成果物のアップロードを設定します。

おすすめしない使い方:署名用ファイルを含むノードで、信頼できない外部からのプルリクエストを実行すること。ノードが専用でも、ワークフローごとに分離されるわけではありません。

runnerの確認項目を見る

GitLab Runner・shell executor

おすすめ:約3~30人で、コードと権限をGitLabに集約しているチームに適しています。shell executorはノード上のXcodeとコマンドライン環境を直接使用します。

  1. macOS用のGitLab Runnerをインストールし、プロジェクトまたはグループから提供された登録情報でrunnerを登録します。
  2. を選択し、 shell executorを使います。専用ラベルを設定し、実行できる保護ブランチとタスクの範囲を制限してください。
  3. 依存関係の復元、コンパイル、書き出し、成果物の保存を個別に検証できる段階に分け、まずは並列実行を1つに設定します。

おすすめしない使い方:同じshell executorで、信頼関係のない複数のお客様のリポジトリを実行すること。作業ディレクトリとホストへのアクセス権は、適切に管理する必要があります。

runnerの確認項目を見る

Jenkins agent

おすすめ:約10~30人で、Jenkins controllerとリリース承認の流れがすでにあるチームに適しています。ノードをmacOS agentとして追加できるため、パイプライン全体を移行する必要はありません。

  1. controllerで専用agentを作成し、ノードラベル、専用の作業ディレクトリ、実行ユーザーを指定します。
  2. controllerの設定に従って接続し、必要なJavaバージョンとagentの実行環境に互換性があることを確認してから、常時稼働を有効にします。
  3. テストタスクでmacOSラベルを明示的に指定し、環境変数、ツールのパス、成果物の保存権限を確認します。

おすすめしない使い方:たまにしかビルドしないのにcontrollerを新設すること。軽量なCIがすでにある場合、管理対象を増やす必要は通常ありません。

runnerの確認項目を見る

runnerがオンラインでも、次の4項目を確認

個人の対話型セッションだけでなく、runnerの実行ユーザーで確認してください。
確認項目確認方法合格条件
作業ディレクトリとツール実行: whoami、pwd および xcodebuild -versionユーザー、ディレクトリ、Xcodeのバージョンがタスク設定に合っている
リポジトリと依存関係へのアクセスCIで注入した権限を絞った認証情報を使い、指定ブランチを取得してロックファイルどおりに依存関係を復元する個人のターミナルにだけ存在する未宣言のトークンやパスに依存しない
署名の動作確認非対話型タスクでアーカイブと書き出しを完了する手動確認を求めるダイアログが表示されず、認証情報がログに出力されない
再接続と成果物の保存バックグラウンドサービスの状態を確認し、タスク完了後に成果物とログを取得するrunnerが接続を回復でき、成果物が一時作業ディレクトリだけに残らない

1台のノードに複数の管理対象タスク用の入口を登録できますが、CPU、ユニファイドメモリ、SSDは共有です。まずビルドの並列数を1に制限し、実測値を見ながら段階的に増やしてください。runnerの名前を増やしても、物理リソースは増えません。

Windowsで開発し、macOSでビルド

FlutterのiOSビルドをリモートで実行

Windowsはコーディング、コミット、ログ確認に使えます。iOSのコンパイルと署名はクラウド上のMacで実行します。専用ノードを使っても、有効なApple Developer Programの資格、署名証明書、秘密鍵、アプリに対応したプロビジョニングプロファイルは必要です。

  1. 01

    依存関係を固定

    同じコミットとロックファイルを同期し、Flutter、Dart、CocoaPods、Xcodeの互換性を確認します。まず flutter doctor -v を実行してツールチェーンを確認し、次に flutter pub getを実行します。別のパソコンの絶対パスをプロジェクトに持ち込まないでください。

  2. 02

    署名用ファイルを取り込む

    チームが承認した安全な方法で証明書、秘密鍵、プロビジョニングプロファイルを転送します。実際のビルドユーザーがアクセスできる専用キーチェーンに証明書を取り込み、プロビジョニングプロファイルと書き出し設定を用意します。bundle identifier、チームID、配布方法が一致しているか確認してください。

  3. 03

    実行して成果物を取得

    次を実行します。 flutter build ipa --releaseプロジェクトで書き出しルールの指定が必要な場合は、対応する --export-options-plistを渡します。成果物は通常、プロジェクトの build/ios/ipa/に出力されます。実際の出力を確認したうえで、CIからチームの成果物ストレージに保存してください。

  4. 04

    テストの範囲を明確にする

    リモート環境ではシミュレーターのテストや自動ビルドを実行できます。実機、センサー、操作感の検証は、引き続き実機で行ってください。React NativeのチームもiOSのコンパイルをノード上で実行できますが、依存関係の復元方法はプロジェクト固有のスクリプトに合わせてください。

キャッシュは高速化のための仕組みであり、バックアップではありません。プロジェクト、Xcodeのバージョン、依存関係のロックファイルに合わせてキャッシュキーを設計してください。署名に問題がある場合は、まず有効期限、秘密鍵、プロビジョニングプロファイルの対応関係を確認し、すべてのビルドキャッシュを削除しないでください。

まず書き出しを確認してからアップロード

配布用の認証情報はノードのログイン情報と分けて管理

TestFlightで配布するには、App Store Connectでアプリの必要な設定が完了しており、適切な配布権限が必要です。API Keyはアップロードの認証に使うもので、コンパイルに必要な署名証明書やプロビジョニングプロファイルの代わりにはなりません。

設定の手順

  1. インストール可能な成果物を確認します。まず fastlane gym またはプロジェクトで使用しているコマンドでアーカイブと書き出しを行い、bundle identifier、バージョン、ビルド番号を確認します。
  2. API Keyを用意します。必要な権限を持つ担当者が、適切なロールのApp Store Connect API Keyを作成します。Key IDとIssuer IDを記録し、秘密鍵ファイルを安全に保管してください。
  3. CIに注入します。秘密鍵と識別情報はチームのシークレット管理に保存します。タスクの開始時に権限を限定した設定ファイルを作成し、終了後に削除してください。設定ファイルや秘密鍵をリポジトリにコミットしないでください。
  4. アップロードして処理状況を確認します。pilotを実行し、アプリの識別情報とアップロード結果を確認します。アップロードに成功しても、テスターに配布されたとは限りません。後続の処理とテスト配布の状態も確認してください。

既存のipaをアップロードするコマンド

fastlane pilot upload \
  --api_key_path "$ASC_API_KEY_JSON" \
  --ipa "$IPA_PATH" \
  --skip_waiting_for_build_processing true

ASC_API_KEY_JSON にはfastlane形式で作成した一時的なAPI Key設定ファイルのパスを指定し、IPA_PATH には実際のipaのパスを指定します。Bundlerを使う場合は、コマンドの前に bundle execを付けてください。

アプリのバージョン、ビルド番号、コミットID、アップロード結果を記録してください。秘密鍵の内容や認証設定全体をログに出力しないでください。

アップロードに失敗したら、エラーの種類ごとに確認

認証エラーの場合はKey ID、Issuer ID、秘密鍵、ロールの権限を確認します。ビルド番号が重複している場合は番号を変更すればよく、runnerを再設定する必要はありません。署名やアプリ識別情報のエラーは、アーカイブと書き出しの段階に戻って確認してください。コンパイル、署名、アップロードを別々の確認ポイントにすると、毎回タスク全体を最初から実行する手間を省けます。

引き継ぎ内容をパイプラインに記録

ノードは365日稼働。タスクは移行できるように

ノードは365日、継続して稼働します。施設側では電源、ネットワーク、冷却を管理します。チーム側ではプロジェクトの依存関係、鍵、タスク設定、データのバックアップを管理してください。ハードウェアに異常がある場合は、チケットで確認が必要です。単一ノードだけを唯一の消失できないコピーとして扱わないでください。

再構築できる手順を常に用意

runnerのラベル、ツールのバージョン、環境変数名、依存関係のインストール手順、署名用ファイルの取り込み手順を記録します。個人の記憶に頼るより、自動化スクリプトで環境を再構築できるようにしておくと、引き継ぎが簡単です。

署名証明書と秘密鍵は暗号化してバックアップし、ビルド成果物とログはチームのストレージに保存してください。DerivedDataや依存関係のキャッシュはコストに応じてバックアップの要否を決められますが、再生成できる状態にしておきましょう。

導入チェックリストを確認

問題が起きたら、まず記録を残す

ノードID、発生日時とタイムゾーン、最後に成功したタスク、エラーの概要を記録します。SSHで接続できるか、runnerがオンラインか、タスクを開始できるかを個別に伝えてください。「ビルドが壊れた」だけでは状況を把握できません。

ログインできる場合は、必要なデータとログを先に取り出し、新しいタスクの実行を一時停止します。チケットには機密情報を伏せた内容だけを記載してください。調査のためにアクセス許可が必要な場合は、許可する範囲を明示し、秘密鍵やパスワード全体を送らないでください。

ログインして問題を報告

ノード交換後に再確認

サポート担当者が状況を確認した後、チケットで対応方法をお知らせします。ノードを交換する場合は、提供された情報に従ってアドレスと認証情報を更新し、ホストのフィンガープリントを再確認してください。

依存関係と署名用ファイルを復元し、runnerを再登録または再接続して、最小限のビルドを1つ実行します。新しいノードでタスクを実行できることを確認したら、古い接続情報と不要になったrunner登録を無効にしてください。

接続手順を再確認

ディスクを整理する前に、保持ルールを決めてください。成果物はリリース単位、ログはチームの監査要件に従って保存し、キャッシュは再生成できるようにローテーションします。ビルド中に作業ディレクトリを整理したり、システム全体のXcodeパスを切り替えたりしないでください。

請求情報とノードを一緒に引き継ぐ

最後の通知を待たず、リリース前に期限を確認

日単位は初回の試用や短期のビルドに、週単位は特定期間に集中して作業する場合に適しています。月・四半期単位はnightlyビルドの常時運用に向いています。利用期間を選ぶ際は、各期間の合計料金を確認してください。日単位の料金を長期利用の予算として見積もらないようにしましょう。

環境を変更する前に、権限の範囲を確認

チームでノードを使う際によくある6つの質問

Homebrewやプロジェクトの依存関係をインストールできますか?

一般的なmacOSプロジェクトと同様に、開発ツールやプロジェクトの依存関係を管理できます。インストール前にアーキテクチャ、インストール先、必要な権限を確認し、バージョンと手順を環境台帳に記録してください。初回導入では既存プロジェクトの依存関係を再現することを優先しましょう。すべてのツールを一度に更新すると、失敗の原因がプロジェクトか環境の変更か判別しにくくなります。

Xcodeのバージョンは選べますか?

プロジェクトの互換性要件に合わせてバージョンを選び、まずノードにインストールされているバージョンを確認してください。別のバージョンをインストールする場合は、ディスク容量、入手方法、プロジェクトの要件を確認します。特定のバージョンがあらかじめインストールされていると決めつけないでください。複数のタスクでノードを共有する場合は、 DEVELOPER_DIRをタスクの環境変数として設定すると、システム全体の切り替えによって実行中の他のタスクに影響するのを防げます。

root権限はありますか?runnerをrootで実行する必要はありますか?

macOSのグラフィカル画面とコマンドラインを利用できます。管理者ユーザーの有無と利用可能な sudo 権限は、コントロールパネルで提供される認証情報でご確認ください。インストール時に追加の権限が必要な場合は、チケットで事前に確認してください。rootでの直接ログインを標準の接続方法にせず、通常のCIタスクを高権限のユーザーで実行することも避けてください。ビルド、鍵、作業ディレクトリは最小権限の原則に沿って個別に管理します。

チームの複数人で1台のノードを使えますか?

専用ノードをチームのワークフローに組み込んで利用できます。ただし、ユーザーが増えても物理リソースは増えません。ユーザーごとに専用アカウントを割り当てるか、タスクの入口を明確にし、並列実行数を制限して、環境を変更する時間をチーム内で決めてください。メンバーごとのビルド権限と署名権限はチームで管理する必要があります。相互に分離されたマルチテナント環境としては利用できません。

他のお客様によってキャッシュが削除されることはありますか?

ノード1台はお客様1社専用で、ビルドリソースを他のお客様と共有しません。ただし、チーム内のクリーンアップスクリプト、ディスク管理、環境変更によってキャッシュが影響を受けることはあります。キャッシュは再生成可能な高速化用データとして扱い、コード、署名用ファイル、最終成果物は別途バックアップしてください。ノード交換時にロックファイルから依存関係を復元できるようにしておきましょう。

導入で行き詰まった場合、チケットには何を添付すればよいですか?

ノードID、CIの種類、該当タスクのコミットID、発生日時とタイムゾーン、最初に失敗した箇所の前後を含む機密情報を伏せたログをお知らせください。同じコマンドを対話型ターミナルとrunnerで実行したときに、動作が異なるかどうかも記載してください。アクセストークン、秘密鍵、パスワード、機密情報を含むパスは削除してください。追加調査にアクセス許可が必要な場合は、チケットで許可範囲を確認します。

実際のタスクでビルド機を検証

まず日単位で試し、nightlyの長期運用に使うか判断しましょう。Port M4 Baseは1日あたり$19.7から。コミットID、ビルドログ、成果物を保存し、自分のプロジェクトの実測値をもとに構成を選べます。