ガイド

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@v4

2. 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 only

4. シミュレータでビルドとテスト

      - 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の選択と依存関係のキャッシュは不要になります。ビルドの前に待ち行列もありません。

関連ガイド