すでに専用リモート Mac上で xcodebuild をグリーンにできる一方、夜間に「昨日は通ったのに」というフレークが出ることもあります。根本原因は多くの場合、差分ではなく環境のばらつきです。本稿は VPS 的な意思決定の枠組みを示します。ばらつきの蓄積とリストアコストに失敗を分類し、常時稼働ノードとスナップショット/ゴールデンイメージによるクリーンな基線への回帰を比較表で対比し、6 ステップの引き継ぎ Runbookまでまとめます。Runner、再現可能ビルド、エンタープライズプール各記事とあわせて読む前提で書いています。
リモート Mac は何か月も SSH する Linux ビルドホストのように感じますが、macOS には自動アップデート、GUI ダイアログ、重い開発者向けレイアウトが加わります。同じマシンに Runner、デスクトップ作業、デバッグが混在するとばらつきが静かに積み上がります。以下の 7 項目をプラットフォームレビューで使ってください。該当が多いほど、Runbook に文書化された「リストアボタン」が必要です。
サイレントな OS/Xcode 更新:アップデート後に xcodebuild -version が台帳と一致しなくなり、ベースライン検証がないと環境漂流をマージリスクと誤読します。
グローバルランタイムの漂流:brew やスクリプトがグローバルにインストールし、Runner ユーザの PATH が対話ログインと食い違うと、launchd ジョブが突然 gem を見つけられなくなります。
共有 DerivedData の汚染:複数リポジトリが名前空間なしでデフォルトキャッシュを共有すると、中断ビルドが壊れた状態を残し、コンパイルが不規則に赤くなります。
キーチェーンと署名の混線:リリースと CI が同一ユーザを共有すると、証明書ローテーションが全パイプラインに波及し、ヘッドレスでのロック解除方針が曖昧だと不確実性が増えます。
ディスク圧迫とログ肥大:ローテーションや成果物保持期間がないと、診断ログや古いアーカイブがシステムディスクを圧迫し、症状は IO タイムアウトや不安定なネットワークのように見えます。
プロバイダのメンテナンス:ハイパーバイザ移行や egress 方針の変更が固定出口の前提を壊します。プローブとベースライン回帰がなければ調査が空回りします。
記録されたゴールデン瞬間がない:組織が承認したクリーンな基線が最後にいつだったか誰も言えず、消火が高いブラスト半径の手作業クリーンアップになります。
よくある誤りは、macOS を借り物のハードウェアのように扱い、契約上のコンピュートノードとして扱わないことです。プロファイル化され、復元可能な専用リモート Mac では、インシデントを「誰が何を変えたか」から「漂流閾値を超えたか——スナップショットに戻すべきか」へ再フレームできます。次に、スローガンではなくコストとリスクで 2 つの基盤モデルを揃えた表を示します。
アーキテクチャレビュー向けの表です。左は長寿命マシンを育てるメリットと負担、右はクリーンな基線をボタンにする側です。実務ではハイブリッドが多く、日々は永続ノードで回し、大きなアップグレード後のメンテナンス窓でスナップショット復元を行います。
| 観点 | 常時稼働の専用ノード | スナップショット/ゴールデンイメージのロールバック |
|---|---|---|
| 主なメリット | キャッシュヒット率が高くコールドスタートが少なく、デバッグ向けにログが連続する | ばらつきを素早くリセットでき、回帰経路が短く、大きなアップグレード後に強い |
| 主なリスク | 漂流、隠れたグローバル依存、「グリーンだが説明できない」 | 復元時間;悪いイメージはどこでも同じエラーを再現する——バージョン管理が必須 |
| ディスク戦略 | 名前空間、クォータ、定期クリーンアップ、監査 | システムボリュームのロールバック;キャッシュは別ボリューム——DerivedData をイメージに焼き込まない |
| 向いているパイプライン | 高コミット率、キュー遅延、インクリメンタルビルド | リリース前ゲート、大きな Xcode ジャンプ、環境起因が疑われるインシデント |
| Runner との関係 | Runner プロセスは接続されたまま;ラベルが安定 | 復元後にサービスアカウント、作業ディレクトリ、権限を再検証する |
CI のために「Mac を VPS のように買う」とは、長寿命のコンピュート契約と、既知の良好な基線へ戻すオフランプの両方が必要だということです。
セルフホスト Runner を動かすなら、同じ Runbook にノード復元を書き留め、サービスアカウント・作業ディレクトリ・キャッシュボリュームをまとめて検証し、「Runner はオンラインだが環境は半壊」という状態を避けてください。
専用リモート Mac と SSH を前提とします。ベンダーのスナップショット手順の代わりにはなりませんが、プラットフォームエンジニアリングが確認すべき最小の閉ループです。順序が重要です:変更を凍結し、復元し、ゲートを走らせ、その後に同時実行を戻します。
書き込みとキューイングを凍結:メンテナンス中は Runner が新規ジョブを取らないよう一時停止するか、ラベルを変え、復元の途中で DerivedData が書き込まれないようにします。
現在の指紋を記録:チケットに sw_vers、xcodebuild -version、xcode-select -p、固定した brew パッケージを before/after 比較用に残します。
スナップショットロールバックまたはイメージ再インストールを実行:プロバイダの手順でシステムボリュームを復元します。ゴールデンイメージを使う場合はイメージ ID を変更記録に紐づけ、曖昧な latest イメージを避けます。
最小ツールチェーンを再構築:Xcode CLI、Ruby/Bundler、またはピン留めしたスタックをバージョン固定スクリプトで入れます。窓の間はログなしの ad-hoc brew upgrade を禁止します。
ベースラインゲートジョブを実行:代表的なリポジトリまたはカナリアでクリーンクローン+アーカイブ+テストを走らせ、グリーンのあとで同時実行を広げます。クリーンクローンの定義は 再現可能ビルド の記事に合わせます。
Runner と監視を復帰:launchd/サービス、ディスク余裕、ログディレクトリ権限を確認し、イメージ ID と指紋の三点セットを台帳に記録します。
#!/usr/bin/env bash
set -euo pipefail
LOG="ci-baseline-$(date +%Y%m%d-%H%M).txt"
{
date -u
sw_vers
xcodebuild -version
xcode-select -p
which ruby; ruby -v || true
which node; node -v || true
} | tee "$LOG"
注:同一ホストで Fastlane リリース も動かす場合、復元後にリリース用ユーザの Keychain と API キーのマウントが期待パスにあるか確認し、「CI はグリーンだがリリースが壊れる」を避けてください。
よくある誤設定は、大きなチームキャッシュをゴールデンイメージに焼き込むことです。イメージが肥大し、アップグレードがつらくなります。キャッシュは捨て可能な加速層として扱います。安全側は、OS+Xcode+ピン留めスクリプトをイメージで固定し、キャッシュは別ボリュームのプロジェクト別サブパスに置くことです。エンタープライズビルドプール と同様、1 ノードに複数アプリがある場合はデフォルトパスの衝突を避け、ORG/REPO/BRANCH で名前空間化し、古いディレクトリを期限切れにします。
警告:システムボリュームの復元はデータボリュームを自動では消しません。キャッシュ破損が疑われる場合は、署名素材に触れずにキャッシュだけを消すプレイブックを別途持ってください。
社内共有用です。閾値は SLA とプロバイダ能力に合わせて調整してください。
ノート PC はスリープと OS 変化に悩まされ、純粋な Linux では Apple の macOS ツールチェーンが動きません。説明可能で復元可能な iOS CI 面としては、専用リモート Mac にスナップショットまたはイメージ戦略を組み合わせる方が、延々と手作業で消すより優ることが多いです。NodeMini のクラウド Mac Mini レンタルは、固定 SSH 入口、明確なディスク階層、繰り返し使えるノードプロファイルを提供し、VPS フリートのような運用感を目指せます。
グリーンはその実行が通ったことの証明にすぎません。長寿命ノードではツールチェーン更新、キャッシュ汚染、グローバル依存の漂流が積み重なります。台帳・漂流閾値・任意のスナップショットロールバックを用意してください。サイズと料金は Mac Mini レンタル料金 で比較できます。
原則として、共有キャッシュを読み取り専用イメージに焼き込みません。OS とツールチェーンをイメージで固定し、キャッシュはプロジェクト別名前空間付きの掃除可能ボリュームに置き、再現可能ビルドのディレクトリ戦略に揃えます。
Runner の記事は登録とキューイングを扱い、本記事はノードモデルと復元のリズムを扱います。接続性のベースラインは ヘルプセンター を参照してください。