GitHub ActionsでiOS CI/CDを一から構築する
GitHub ActionsでのiOSアプリのパイプライン全体を、構築する順に説明します。まずコンパイルとテスト。次に署名。最後にアーカイブとアップロードです。各ステップは小さく、YAMLはそのままコピーして使えます。GitHubホスト型runnerでも専用Macでも動き、変わるのはruns-onの行だけです。
1. 骨組み
name: ios
on:
pull_request:
push:
branches: [main]
concurrency:
group: ios-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
runs-on: macos-latest # or [self-hosted, macOS, your-label]
timeout-minutes: 30
steps:
- uses: actions/checkout@v42. Xcodeを選ぶ
ホスト型イメージには複数のバージョンのXcodeが入っています。イメージの更新で知らないうちにビルドが変わらないよう、明示的に1つを選んでください。
- run: sudo xcode-select -s /Applications/Xcode_26.6.app
- run: xcodebuild -version専用Macなら、バージョンはマシン上で一度固定すれば済み、このステップは不要になります。
3. 依存関係
- uses: actions/cache@v4
with:
path: |
~/Library/Caches/org.swift.swiftpm
Pods
key: ${{ runner.os }}-deps-${{ hashFiles('**/Package.resolved', '**/Podfile.lock') }}
- run: pod install --repo-update # CocoaPods projects only4. シミュレータでビルドとテスト
- run: |
xcodebuild test \
-scheme MyApp \
-destination 'platform=iOS Simulator,name=iPhone 17' \
-resultBundlePath TestResults \
| xcpretty
- uses: actions/upload-artifact@v4
if: failure()
with: { name: test-results, path: TestResults }プルリクエストではここで終わりです。この先はリリースの作業なので、mainでだけ実行します。
5. Macの共有ログインなしでコード署名する
Apple IDではなく、App Store Connect APIキーを使います。キーID、発行者ID、.p8の内容をリポジトリのシークレットに保存します。そしてxcodebuildに、クラウド管理のプロファイルで署名させます。
- run: echo "${{ secrets.ASC_KEY_P8 }}" > AuthKey.p8
- run: |
xcodebuild archive \
-scheme MyApp -configuration Release \
-archivePath build/MyApp.xcarchive \
-allowProvisioningUpdates \
-authenticationKeyPath "$PWD/AuthKey.p8" \
-authenticationKeyID "${{ secrets.ASC_KEY_ID }}" \
-authenticationKeyIssuerID "${{ secrets.ASC_ISSUER_ID }}"6. エクスポートしてTestFlightにアップロードする
- run: |
xcodebuild -exportArchive \
-archivePath build/MyApp.xcarchive \
-exportPath build/export \
-exportOptionsPlist ExportOptions.plist \
-allowProvisioningUpdates \
-authenticationKeyPath "$PWD/AuthKey.p8" \
-authenticationKeyID "${{ secrets.ASC_KEY_ID }}" \
-authenticationKeyIssuerID "${{ secrets.ASC_ISSUER_ID }}"
- run: |
xcrun altool --upload-app -f build/export/MyApp.ipa -t ios \
--apiKey "${{ secrets.ASC_KEY_ID }}" --apiIssuer "${{ secrets.ASC_ISSUER_ID }}"ステップ5と6をfastlaneでまとめるチームも多くあります。中で動くコマンドは同じです。
7. 時間がかかる場所と、runnerの選択
ホスト型runnerでは、ステップ2と3がジョブのたびに繰り返され、1分あたり約$0.062〜$0.102で課金されます。専用Macなら一度で済み、キャッシュもウォームなままです。だから月2,242分前後を超えたチームは、パイプライン全体を固定料金のマシンに移します。変えるのはruns-onの行だけです。その側面は専用ハードウェアでのパイプラインのガイドで扱っています。
よくある質問
GitHub ActionsでiOSのCIを動かすにはMacが必要ですか?
+
はい。iOSアプリのビルドと署名にはXcodeが必要で、XcodeはmacOSでしか動きません。そのためビルドのジョブには、GitHubホスト型か自分で管理するMacの、macOS runnerが必要です。
Apple IDを使わずにCIでiOSアプリに署名するには?
+
App Store Connect APIキーを作成し、そのID、発行者ID、.p8の内容をシークレットに保存します。それを-allowProvisioningUpdatesとともにxcodebuildに渡します。runnerにApple IDやキーチェーンのパスワードは要りません。
テストはプルリクエストのたびに実行すべきですか?
+
プルリクエストのたびに、1つのシミュレータでビルドとテストを実行します。アーカイブ、署名、TestFlightへのアップロードはmainでだけ行います。遅くて高くつくステップだからです。
このパイプラインを専用Macに移すと何が変わりますか?
+
runs-onの行です。マシンがジョブの間も保持するので、Xcodeの選択と依存関係のキャッシュは不要になります。ビルドの前に待ち行列もありません。