effidevFlutter・Cloudflareエッジ・クラウドコスト最適化
日本語

Fastlane + GitHub ActionsでFlutter iOS/Androidのビルド、コード署名、App Store配信を自動化

CI/CD配信パイプラインとApp Store、Google Playのアイコンが描かれたイラスト

Flutterでのアプリ開発は楽しいものですが、完成したアプリをApp StoreやGoogle Play Storeに配信するプロセスは、しばしば開発者にとって大きなストレスとなります。証明書の管理、プロビジョニングプロファイルの紐付け、ビルドバージョンのバンプ、そしてストアへのアップロードまで、手作業で行うべきことが多すぎるからです。

このガイドでは、FastlaneGitHub Actionsを組み合わせて、FlutterアプリのiOSおよびAndroidのビルド、コード署名、そしてストア配信のプロセスを完全に自動化する構築方法を取り上げます。

なぜCI/CDの自動化が必要なのか?

手動の配信プロセスでは、次のような問題が頻繁に発生します。

GitHub ActionsとFastlaneを使用すれば、コードをmainまたはreleaseブランチにプッシュするだけで、これらすべてのプロセスをクラウド上で安全に処理できます。


1. Fastlaneの設定(ローカル)

まず、FlutterプロジェクトのandroidiosディレクトリそれぞれでFastlaneを初期化する必要があります。

Android Fastlaneの初期化

cd android
fastlane init

初期化プロセスで、パッケージ名とJSONシークレットキーのパスを尋ねられます。Google Play Consoleで発行されたサービスアカウント(Service Account)のJSONキーが必要です。

android/fastlane/Fastfileの例:

default_platform(:android)

platform :android do
  desc "Submit a new Beta Build to Crashlytics"
  lane :beta do
    gradle(task: "clean bundleRelease")
    upload_to_play_store(track: 'beta')
  end
end

iOS Fastlaneの初期化

iOSの配信は、証明書とプロビジョニングプロファイルの管理が重要です。Fastlaneのmatchを使用すると、このプロセスをGitリポジトリを通じてチームメンバーと安全に共有し、CI/CDで簡単に読み込むことができます。

cd ios
fastlane init
fastlane match init

ios/fastlane/Fastfileの例:

default_platform(:ios)

platform :ios do
  desc "Push a new beta build to TestFlight"
  lane :beta do
    setup_ci
    match(type: "appstore", readonly: true)
    
    # FlutterのビルドはGitHub Actionsで行うため、Fastlaneでは既にビルドされたアプリを処理します。
    build_app(workspace: "Runner.xcworkspace", scheme: "Runner")
    upload_to_testflight
  end
end

[!IMPORTANT] iOSのコード署名をCI環境で実行するには、Fastlane Matchの使用を強く推奨します。ローカルから証明書をエクスポートしてCIにアップロードするよりも、はるかに安全で管理が簡単です。


2. GitHub Actions ワークフローの構成

次に、リポジトリの最上位に.github/workflows/deploy.ymlファイルを作成します。

ワークフローの基本構造と環境変数

GitHub Secretsに次の値を事前に保存しておく必要があります。

ワークフロー全体のスクリプト

name: Deploy to App Store & Google Play

on:
  push:
    tags:
      - 'v*' # v1.0.0 のようなタグがプッシュされたときに実行

jobs:
  build-and-deploy:
    runs-on: macos-latest
    
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
      
      - name: Setup Java
        uses: actions/setup-java@v3
        with:
          distribution: 'zulu'
          java-version: '17'
          
      - name: Setup Flutter
        uses: subosito/flutter-action@v2
        with:
          channel: 'stable'
          
      - name: Install dependencies
        run: flutter pub get
        
      # --- iOS 配信パイプライン ---
      - name: Setup Ruby for Fastlane
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: '3.2'
          bundler-cache: true
          working-directory: ios
          
      - name: Decode App Store Connect API Key
        run: |
          mkdir -p ~/.appstoreconnect/private_keys/
          echo "${{ secrets.APP_STORE_CONNECT_API_KEY_KEY }}" > ~/.appstoreconnect/private_keys/AuthKey_${{ secrets.APP_STORE_CONNECT_API_KEY_KEY_ID }}.p8
          
      - name: Build iOS App
        run: flutter build ipa --release --export-options-plist=ios/ExportOptions.plist
        
      - name: Deploy iOS to TestFlight
        working-directory: ios
        env:
          MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
          MATCH_GIT_BASIC_AUTHORIZATION: ${{ secrets.MATCH_GIT_BASIC_AUTHORIZATION }}
        run: bundle exec fastlane beta
        
      # --- Android 配信パイプライン ---
      - name: Setup Ruby for Fastlane (Android)
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: '3.2'
          bundler-cache: true
          working-directory: android
          
      - name: Decode Play Store JSON
        run: echo "${{ secrets.PLAY_STORE_CONFIG_JSON }}" > android/play_store_config.json
        
      - name: Build Android App
        run: flutter build appbundle --release
        
      - name: Deploy Android to Play Store
        working-directory: android
        run: bundle exec fastlane beta

重要な考慮事項

  1. Mac環境の選択: iOSビルドには、必ずmacos-latestランナー(Runner)を使用する必要があります。(Linuxランナーよりも課金率が高い点に注意してください。)
  2. Flutterビルドの最適化: iOSの場合、flutter build ipaコマンドにアーカイブまでのすべてを処理させることができます。この場合、Fastlaneはアップロードの役割のみを担当するように構成する方が、速度面で有利です。
  3. API Key認証: 従来のApple ID / パスワード方式は、二要素認証(2FA)のため、CI環境での使用が非常に困難です。必ずApp Store Connect API Keyを発行して使用してください。

トラブルシューティングガイド

症状 原因と解決策
Missing private key for ... (iOS) Fastlane Matchリポジトリにアクセスできなかったか、MATCH_PASSWORDが間違っています。Secretの値を確認してください。
Google Api Error: Invalid request - Invalid package name (Android) Google Play Consoleにアプリがまだ一度も登録されていない場合に発生します。最初の配信は、必ず手動でAABをアップロードする必要があります。
Code signing is required for product type 'Application' (iOS) Xcodeプロジェクトファイル(.pbxproj)の署名設定が「Automatic」になっており、プロビジョニングプロファイルが注入されていない場合です。Matchを使用するようにプロジェクト設定を変更してください。

おわりに

CI/CDパイプラインの構築は、初期設定に半日程度の時間がかかる場合がありますが、一度構築しておけば、その後の数十回、数百回の配信プロセスで膨大な時間とストレスを節約できます。特にチーム単位の開発では、「誰が配信するのか」という悩みを解消し、開発文化を肯定的に変化させます。

今すぐプロジェクトにFastlaneとGitHub Actionsを導入し、開発だけに集中できる環境を整えてみてください。