DevOps / CI·CD 2026年4月25日

2026-04-25 レンタルクラウド Mac(HK / JP / KR / SG / US)での xcodebuild test コードカバレッジ、xcresult から JUnit、PR ゲート

MacXCode Engineering Team 2026年4月25日 約18分

iOS / macOS チームの多くは、レンタルした Apple Silicon Mac mini M4ヘッドレス xcodebuild test を回していても、PR を単一の 終了コード とベンダ UI の赤緑セルだけでマージしています。本稿(2026-04-25)は「テストが通った」と「今週の品質が 説明 できる」のギャップを埋めます:-resultBundlePath隔離ビルドルート 配下の ジョブ単位 ディレクトリへ、-enableCodeCoverage YES で LLVM profdataJUnit XML への エクスポートxcresulttool か信頼するラッパー)、そして xccov かダッシュボードパーサで守る 行率ポリシーテストプラン + 並列 xcresult を置き換えるのではなく補完します。コンパイラゲートは Swift 6 strict concurrency へ。こちらは テスト成果物とマージシグナル 側です。同日の OpenClaw 編:OpenClaw doctor とモデル許可リスト

終了コード 0 以外に PR ゲートが見るべきもの

健全なゲートは三つの束を運びます:(1) PR システムがテスト結果とフレークを 注釈 できる junit(または xunit);(2) Xcode で深掘りできる マージ済み または単一の .xcresult を、xcresult 隔離チケットと同じ 保持 で圧縮アーティファクトに;(3) マージベースと 差分 できる カバレッジ 要約(行または分岐はポリシー次第)で、死コード削除のリファクタを回帰扱いしない。HK / JP / KR / SG / US で複数 SSH ホストに扇ぐなら、宛先シャード 後の 集約 メトリクスでゲートを定義—ポリシーがターゲット部分集合だけを明示しない限り、一片の profdata だけを物語にしないでください。レイテンシはメタデータの マシンプールラベル とセットで。東京の コールド シミュレータと米東の ウォーム を公平な A/B にしない。

重要な xcodebuild フラグ:結果バンドル、カバレッジ、宛先

DEVELOPER_DIR=/Applications/Xcode.app と、名前の付いた シミュレータ -destination を固定。未指定の「最新 iOS」に浮かないでください。最小の明示パターン:

DEVELOPER_DIR=/Applications/Xcode.app xcodebuild test -workspace App.xcworkspace -scheme App -destination 'platform=iOS Simulator,name=iPhone 16,OS=18.2' -enableCodeCoverage YES -resultBundlePath "$CI_ROOT/Test-$(date +%s).xcresult" -derivedDataPath "$CI_DERIVED/job-$CI_JOB_ID" -parallel-testing-enabled YES CODE_SIGNING_ALLOWED=YES

シャードジョブでは -only-testing / -skip-testing を調整し、マージ方法を知る コーディネータ ジョブで締める。-retry-tests-on-failure は文書化した フレーク予算 があるときだけ—無限リトライは 署名・キーチェーン の壊れを隠します。別レーンで Swift 6 strict を回すなら、スキーム分割が本物でない限り同じ ユニット を二重に数えないでください。共有 NVMe の分を無駄にします。

.xcresult から JUnit:ヘッドレスで残るエクスポート

macOS CI では xcresulttool が使えます:テスト診断 を JSON か JUnit に、ピン留めした Xcode のフラグ次第で。典型:(1) -resultBundlePathランごとに一意 で、共有 NFS へのシmlink 配下に置かない;(2) 実行後に xcresulttool get --format json で健全性確認;(3) ベンダ向けに JUnit へ—多くの組織は薄い Ruby/Node アダプタを固定。各 testcase に安定した testsuite 名と classname を付け、PR UI が リトライ を重複排除できるように。複数 xcresult を マージ するときは Xcode の merge か時刻昇順など文書化した 順序。同一識別子で testStatus が衝突したら拒否。 xcresult は シミュレータ 深掘りと同様にコールドストレージへ。XML だけにしない。

LLVM profdataxccov、守れる閾値

-enableCodeCoverage YES ならコンパイラとリンカが xcrun llvm-profdata merge でマージし xcrun xccov view --report やポリシーに合う report で見られるデータを出します。実務的には自社の アプリコアフレームワークフロア を置き、生成コードと第三者はチェックインした 除外リスト で外す—未記載 の第三者がチームの予算を静かに食べないように。セルフホストランナー 移行後も数字は揃えるべきで、同一 git SHA のソース ハッシュ は一致するが インクリメンタル カバレッジは片方がターゲットを飛ばすとズレます—厳格レーンがインクリメンタルを完全オフにする理由の一つ。同じ夜に dSYM アップロード を変えるなら dSYM パイプラインが配ったと思っている bitcode/LLVM 成果物と一致しているか確認。

CI ガードレール: xccov が profdata パスを 開けない ときはビルドを落とす—黙ってカバレッジを「0%」にして通す のは 2026 年に未テスト diff を出したあとダッシュボードのせいにするパターンです。

シャードされた test:ゲートの前にマージ

-only-testing:Target/Class や宛先で分割すると各シャードが独自の profdataxcresult を持ちます。コーディネータ のマージゲートは:(1) 各シャードが 終了 しアーティファクトを上げたか;(2) 単一の xccov の前に profdata をマージ;(3) JUnit を集約し、意図的にシャードに無いスイートは skipped。インフラの先取りでシャードを 失った ら、書面の「欠損シャード許容」が無い限り(稀でデフォルトではない)マージは 失敗M4 扇出 と一緒に:並列は データ面(アーティファクト + カバレッジ)が一枚のレポートに 直列化 できるときだけ価値があります。

症状 / 層 / 対処

症状 対処 / 検証
テストは走ったがカバレッジ 0% ビルド設定 / ターゲット所属 scheme で Code Coverage が有効か、ターゲットがカバレッジフラグでビルドされているか
JUnit が空だが UI はパス ツールエクスポート ホストの Xcode 版で xcresulttool 出力を検証。ベンダのスタブを盲信しない
二ホストで行率が大きく違う ブランチ / インクリメンタル / シャード ゲートでインクリメンタルを止める、profdata をマージ、宛先を固定

同じ Mac が OpenClaw gateway も動かすなら、エージェント間で単一の /tmp共有しないTMPDIR はジョブ単位のはずです。リリースビルドでは リモート archiveApp Store Connect API での IPA エクスポート が同じ信頼の下流です。CI のテスト + カバレッジはリリースにタグ付けする 同じ ブランチアイデンティティであるべきで、文書化したプロモ遅延だけが許容です。

FAQ:マルチリージョン Mac プールの品質ゲート

質問 実務回答
ブランチカバレッジでブロックすべき? 言語ミックスが支えるなら。PM には行率の方が説明しやすく、セキュリティクリティカルは分岐も。
xcresult zip はどのくらい保持? インシデント SLA に合わせ—14 日以上 が一般的開始。1–2 TB リースなら長くも可能。
マトリクスは米東先かアジア先? インタラクティブ再現はコミッタの多数派に近いリージョン。フルマトリクスはリリースで。

この負荷に Mac mini M4 をレンタルする理由

シミュレータとカバレッジは GPU より CPU + NVMe + inode に縛られることが多い。MacXCode の地域にいるベアメタル Mac mini M4 は予測可能な I/O と、複数 CoreSimulator ルートを ウォーム 保つ十分な RAM を与え、OpenClaw gateway と騒がしい隣人を共有しません。p95 で第二レーンが要るなら、512 GB を三チームで詰め込むより プラン で拡張。稀な GUI 確認は VNC のブレイクグラス—2026 の週次には SSH + アーティファクト が主役であるべきです。

リージョン内で再現性の高い iOS テスト CI を

M4 · デフォルト SSH · 1–2 TB オプション