短周期のバーストビルドで怖いのは「キューで窓が潰れること」と「キャッシュが環境を静かに汚すこと」の二つです。GitLab Runner をクラウド Mac に登録し shell 実行器を選べば、手元で検証済みの Xcode・Ruby/CocoaPods・署名キーチェーンをそのまま再利用でき、Docker on Mac や SSH ラッパーを挟まずに済みます。代わりに同一ユーザのホーム直下のグローバル状態は、タグとキャッシュキーで律する必要があります。以下は当番で使っているパラメータ寄りのメモで、.gitlab-ci.yml をリポジトリに貼って試せます。GitHub 側の弾性プールと常駐ノードの比較は 2026年の短周期CIピーク構築:GitHub Actions 自ホスト macOS Runner は「クラウドMacの弾性プール」と「常駐ノード」どちらにすべきか?──遅延・キャッシュ・キューの意思決定マトリクス(実行可能なパラメータ一覧) と併せて読むと整理が早いです。
Shell Executor:クラウド Mac に載せる意味
Job が xcodebuild・Archive・notary・キーチェーン前提のスクリプト中心なら、shell はコンテナ実行器より運用が素直です。パス・権限・(必要なら)GUI セッションまで、人手ログインでの切り分けと同じ語彙で話せます。Runner 専用の OS ユーザか独立した Home を切り、DerivedData をデスクトップ作業と共有しないこと。並列 concurrent を上げるほどディスク IO と codesign のロック競合で尾が伸びるので、まずは壁時計で測ってから足します。
gitlab-runner で concurrent を固定し、shell executor の environment に CI_DERIVED_DATA_PATH や FASTLANE_SKIP_UPDATE_CHECK などを寄せると、YAML はステージ記述に集中でき、バーストで Runner を増やすときは設定差分だけ差し替えられます。
キャッシュキー:速さと正しさの両立
cache:key:files には少なくとも Gemfile.lock・Podfile.lock・Package.resolved などビルドに効くロックを入れます。Xcode の大版を上げたタイミングでは MACOS_CI_IMAGE_ID のような変数を prefix に足し、古い DerivedData が新ツールチェインへ混ざるのを防ぎます。policy: pull-push はデフォルトブランチ高頻度向き。リリース枝や nightly だけ全量 push を開けるとオブジェクトストレージへの書き込み増幅を抑えられます。
cache: key: files: - Gemfile.lock - Podfile.lock - YourApp.xcworkspace/xcshareddata/swiftpm/Package.resolved prefix: "${CI_COMMIT_REF_SLUG}-xcode${XCODE_VERSION}" paths: - .cocoapods/ - ~/Library/Developer/Xcode/DerivedData/ policy: pull-push
タグ戦略:burst・steady・「クラウド Mac のみ」
tags で mac-burst(短いタイムアウトでよい弾性ノード)と mac-steady(契約内の固定枠・署名や TestFlight 向け)を分けます。既定パイプラインは burst のみ。キーチェーン解錠や有人前提の工程は steady に限定し、クリティカルパスをバーストに奪わせない運用が安全です。突発負荷と日額レンタルの判断は 2026年の突発ビルドとApp Store審査:Macを買うか、日額/週額でクラウドMacを借りるか? が近い文脈です。
| タグの組み合わせ | 典型 Job | タイムアウトと再試行の目安 |
|---|---|---|
mac-burst + shell |
単体テスト、静的解析、無署名 Archive | timeout: 25m、ネットワーク系のみ retry: 1 |
mac-steady + shell |
notary、TestFlight アップロード | 長めの timeout、burst と同時スロットを共有しない |
mac-m4(機種ラベル任意) |
リンク負荷の大きい大規模ターゲット | Runner プールの買い/借りポリシーと合わせて命名を固定 |
GitHub Actions との併用:意思決定マトリクス(簡版)
二重ホストの典型は「OSS は GitHub、プライベートなレジストリとシークレットは GitLab」です。原則は「コードと秘密に近い側が重い Job を持つ」。GitHub に成熟した macOS workflow があれば軽いチェックだけ Actions に残し、社内キャッシュや GitLab Container Registry が要る工程をセルフホストへ寄せる、あるいはその逆もあり得ます。両方でキャッシュを有効にするときはバケット prefix と key を必ず分け、同名キーの上書き事故を避けます。
| 状況 | 先に GitLab(クラウド Mac shell) | 先に GitHub Actions |
|---|---|---|
| 正本が GitLab | はい。二重 clone / submodule を減らす | コミュニティ PR の軽いチェックだけ残す |
| GitHub Packages / OIDC 依存 | トークンを社内ミラーへ同期してから重処理 | ネイティブ連携が単純 |
| PR バースト | burst Runner とキュー上限 | larger runner の課金とクォータを別評価 |
tags が空でないか、「Run untagged」を切る。Q:キャッシュは当たるのにフルビルド? Xcode マイナーが変わったのに key に入っていないことが多い。xcodebuild -version を artifact に残して突き合わせる。Q:Actions と二重実行? rules:changes でトリガ面を絞り、「権威ある green」を片側に一本化する。
ios_burst: stage: build tags: [mac-burst, shell] rules: - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' variables: GIT_STRATEGY: fetch FASTLANE_OPT_OUT_USAGE: "1" script: - xcodebuild -version - bundle exec fastlane ci_unit
クラウド Mac mini なら、この構成がさらに素直になる
セルフホスト Runner の安定性は YAML より下のマシンで決まります。Apple Silicon のユニファイドメモリは Xcode のリンクと Swift コンパイルのピークをなだらかにし、macOS 上では Homebrew・キーチェーン・codesign の連鎖がそのまま使えます。クラウド Mac mini M4 の待機電力はおおよそ 4W 程度に抑えられるため、shell Runner を常時オンにしても電気代のストレスが小さく、静音筐体でデスク横にも置きやすいです。
Gatekeeper と SIP により脅威面は多くの汎用 Windows ワークステーションより狭く、クラッシュ率の低い macOS は長期無人運用にも向きます。タグで burst と steady を分け、キャッシュ鍵でツールチェインを固定する——本文の方針は、ハードを「借りるか買うか」より前に、まず再現性の土台として効きます。
GitLab と GitHub のハイブリッドを 運用で守れるノード に落とし込みたいなら、VPSSpark のクラウド Mac mini M4 はコストパフォーマンスの良い出発点です——プランを今すぐ確認し、Runner 登録後はパイプライン記述に集中できる状態を先に取りに行きましょう。