Codemagic CLI ツールと GitHub Actions で App Store Connect へアプリをデプロイする

本記事は、佐藤将来が執筆しました。

モバイルアプリのビルドからコード署名、公開までのプロセスは、特に QA エンジニアとビルドを共有する必要がある大規模なチームにおいては、手間がかかり多くの時間を消費します。そこで Codemagic は、最小限の設定でワークフロー全体を自動化できるクラウドベースの CI/CD サービスを提供しています。しかし、Codemagic の機能をローカル環境や他の CI/CD 環境(例:GitHub Actions)で使いたい場合はどうすれば良いでしょうか?そんな時に便利なのが Codemagic CLI ツール です。

Codemagic CLI ツールとは

Codemagic CLI ツール は、Codemagic の CI/CD サービスの裏側で使われている、無料かつオープンソースのコマンドラインツール群です。このツールを使うことで、モバイルアプリ開発に関する様々な作業(ビルド、コード署名、公開など)に簡単に着手することが出来ます。ドキュメントも充実しており、Codemagic チームや外部のコントリビューターによって常に最新の状態に保たれています。

Codemagic CLI ツールの大きな特徴は、プラットフォームに依存しない点です。複数の OS で利用でき、iOS・Android の両方に対応しているため、ストアごとに異なるツールを用意する必要がありません。fastlane のように複雑な設定も不要で、シンプルかつ直感的に使えるため、初心者から上級者まで幅広い層に利用をお勧め出来ます。

本記事では、Codemagic CLI ツールを GitHub Actions と組み合わせて Flutter アプリを App Store Connect へデプロイする方法を解説します。ここでは以下の内容を学ぶことができます:

  • App Store Connect 用の API キーの生成方法
  • Codemagic CLI ツールと GitHub Actions を使ったワークフローの作成方法
  • ローカル環境での Codemagic CLI ツールのインストールと利用方法

この記事を実践することで、アプリの配布プロセスが効率化され、多くの時間やリソースを節約できます。また、バージョニングやテストデバイスの登録など、他の用途にも Codemagic CLI ツールを活用できるようになります。

App Store Connect の事前準備

この記事では、Apple Developer Program への登録、バンドル ID の登録、App Store Connect 上での Flutter アプリの作成が完了していることを前提としています。まだの場合は、先にこれらの準備を済ませてください。

App Store Connect 用 API キーの生成

このセクションでは、App Store Connect 用の API キーを生成する手順を解説します。このキーは、Codemagic CLI ツールが App Store Connect へアプリをアップロードするために必要になるものです。

Codemagic CLI ツールが App Store Connect へアクセスできるようにするには、App Manager 権限を持つ API キーを作成してください。

  1. App Store Connect にログインし、ユーザとアクセス > 統合 へ移動します。
  2. + ボタンをクリックして新しい API キーを生成します。
  3. キー名を入力し、アクセスレベルで App Manager を選択します。
  4. キーが生成されたら、リストに追加されます。ダウンロード をクリックして秘密鍵を保存してください(ダウンロードは一度きりです)。

Issuer ID(有効なキー一覧の上部)と、生成したキーの キーID も控えておきましょう。これらは後ほどパイプライン設定時に必要となります。

環境変数とシークレットの設定

このセクションでは、後ほどパイプラインで必要となる環境変数やシークレットの設定方法を解説します。

前の手順をすべて完了し、アプリケーションの情報とコードが一致していることを確認してください。バンドル ID の不一致などがあると、思わぬトラブルやデバッグの手間が発生します。CLI ツールはこうした問題の多くを軽減してくれます。

シークレットと変数の設定

Codemagic CLI ツールを GitHub Actions で利用するには、リポジトリに環境変数とシークレットを設定する必要があります。環境変数はワークフロー内で参照できるテキスト値ですが、シークレットは暗号化されているため機密情報(パスワードや証明書など)を安全に管理できます。

GitHub リポジトリの Settings > Secrets and Variables から、Secrets および Variables タブで新しい値を追加してください。

以下の変数を設定します:

  • APP_STORE_CONNECT_ISSUER_ID:Apple Developer ポータルの API キー一覧上部に表示される Issuer ID(例:aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
  • APP_STORE_CONNECT_KEY_IDENTIFIER:API キーの Key ID(例:ABC1234567)。キー名の横やファイル名にも含まれています。
  • APP_STORE_APPLE_ID:App Store Connect でアプリに割り当てられる 10 桁の ID(例:0123456789)。App Store Connect の 一般 > App 情報 で確認できます。

GitHub UI 上では以下のように表示されます:

上記に加え、必要なシークレットも設定します。Secrets タブで以下を追加してください:

コード署名の設定には 2 通りの方法があります。Codemagic CLI ツールに 証明書とプロファイルの自動生成を任せる場合 か、既存の署名情報を使う場合 かになります。この記事では両方の手順を紹介します。

証明書とプロファイルの自動生成

既存の署名情報を使いたい場合は、次の 既存の証明書とプロファイルを使う へ進んでください。

自動署名を利用する場合は、証明書の秘密鍵と App Store Connect API キーを Codemagic CLI ツールに渡す必要があります。秘密鍵は RSA 2048bit で、Codemagic が作成する証明書に含まれます。生成されたファイルは App Store Connect で確認できます。

追加で以下のシークレットを Secrets タブに設定してください:

設定後、UI 上では以下のように表示されます:

既存の証明書とプロファイルの利用

既に配布用の証明書やプロファイルがある場合は、上記の秘密鍵生成は不要です。代わりに証明書・プロファイル・パスワードをシークレットとして追加します。

  • DIST_CERTIFICATE:配布証明書(.p12 拡張子)の内容。base64 エンコードしてシークレットに貼り付けます。macOS では以下のコマンドでエンコード&コピーできます:

  • DIST_CERTIFICATE_PASSWORD:証明書エクスポート時に設定したパスワード。

  • DIST_PROFILE:配布プロファイル(.mobileprovision 拡張子)の内容。base64 エンコードして貼り付けます:

    base64 -i .mobileprovision | pbcopy
    

設定後、UI 上では以下のように表示されます:

GitHub Actions パイプラインの構築

このセクションでは、GitHub Actions で Flutter アプリをビルドし、Codemagic CLI ツールを使って App Store Connect へアップロードする方法を解説します。

YAML ファイルはプロジェクトの .github/workflows/ ディレクトリに保存し、拡張子は .yaml となります。

GitHub Actions には Python が事前にインストールされています。Codemagic CLI ツールには Python 3.8 以上が必要ですが、setup-python により明示的にバージョン指定をすることも可能です。

また、署名ファイルの自動生成・既存ファイル利用のどちらでも、YAML の構造やコマンドはほとんど同じですが、両方の例を紹介します。

まずは GitHub Actions に慣れるために Hello world! を出力するシンプルな例から始めましょう:

name: Hello World Workflow
on: [push]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Echo Hello World
        run: echo "Hello, World!"

このワークフローは、リポジトリへの push をトリガーとして実行され、最新の Ubuntu 環境(ubuntu-latest)上で動作します。

今回の要件に合った挙動とするためには、ここからいくつか修正が必要になります。まず、テスト目的でワークフローを手動トリガー(workflow_dispatch)に設定します。また、事前に設定した環境変数やシークレットを使って、App Store Connect との連携やコード署名ができるようにパイプラインを構成する必要があります。

以下のように順を追って、 YAML を追加・修正してください。

  1. コードの取得

actions/checkout@v4 アクションを使って、リポジトリのコードをランナーにチェックアウトします。

- uses: actions/checkout@v4
  1. 実行環境の変更

アプリを正しくビルドするために、runs-onmacos-latest に変更します。

macos-latest ラベルを使う場合、実際に使用されるマシンが最新バージョンとは限りません。このステップでエラーが発生した場合は、こちら で利用可能なバージョンを確認し、必要に応じてバージョンを直接指定してください(例:macos-15)。

  1. Flutter のセットアップ

subosito/flutter-action を使います。ここでは stable チャンネルを利用しますが、特定のバージョンや他のチャンネルも選択可能です。

- name: Set up Flutter
  uses: subosito/flutter-action@v2
  with:
    channel: 'stable'
  1. Codemagic CLI ツールのインストール

Codemagic CLI tools をインストールするジョブを追加します。

- name: Install Codemagic CLI tools
  run: pip install codemagic-cli-tools
  1. 環境変数の設定

既存の証明書を使うか、Codemagic に署名ファイルの作成を任せるかによって env セクションを設定します。パイプライン内で vars プレフィックスで変数、secrets プレフィックスでシークレットを参照できます。

build:
  runs-on: macos-latest
  env:
    APP_STORE_CONNECT_ISSUER_ID: ${{ vars.APP_STORE_CONNECT_ISSUER_ID }}
    APP_STORE_CONNECT_KEY_IDENTIFIER: ${{ vars.APP_STORE_CONNECT_KEY_IDENTIFIER }}
    APP_STORE_CONNECT_PRIVATE_KEY: ${{ secrets.APP_STORE_CONNECT_PRIVATE_KEY }}
    CERTIFICATE_PRIVATE_KEY: ${{ secrets.CERTIFICATE_PRIVATE_KEY }}
    APP_STORE_APPLE_ID: ${{ vars.APP_STORE_APPLE_ID }}

既存の証明書を使う場合は、CERTIFICATE_PRIVATE_KEY の代わりに、前述の手順で設定したシークレットを追加してください:

    DIST_CERTIFICATE: ${{ secrets.DIST_CERTIFICATE }}
    DIST_CERTIFICATE_PASSWORD: ${{ secrets.DIST_CERTIFICATE_PASSWORD }}
    DIST_PROFILE: ${{ secrets.DIST_PROFILE }}
  1. キーチェーンの初期化

コード署名用の新しいキーチェーンを初期化します。

- name: Set up keychain
  run: keychain initialize
  1. 署名ファイルのセットアップ

CLI ツールで新しいファイルを生成したい場合は app-store-connect fetch-signing-files コマンドを使用します。既存のファイルを使う場合は、ビルドマシン上でデコードする必要があります。どちらの場合も keychain add-certificates コマンドで証明書をキーチェーンに追加できます。

Option 1 – 署名ファイルの自動生成

- name: Fetch signing files
  run: |
    app-store-connect fetch-signing-files $(xcode-project detect-bundle-id) \
    --type IOS_APP_STORE \
    --create    
- name: Set up signing certificate
  run: keychain add-certificates

Option 2 – 既存ファイルのセットアップ

既存の証明書・プロファイルを使う場合は、以下のスクリプトを利用します:

- name: Set up Provisioning profiles
  run: |
    PROFILES_HOME="$HOME/Library/MobileDevice/Provisioning Profiles"
    mkdir -p "$PROFILES_HOME"
    PROFILE_PATH="$(mktemp "$PROFILES_HOME"/$(uuidgen).mobileprovision)"
    echo ${DIST_PROFILE} | base64 --decode > "$PROFILE_PATH"
    echo "Saved provisioning profile $PROFILE_PATH"    
- name: Set up signing certificate
  run: |
    echo $DIST_CERTIFICATE | base64 --decode > /tmp/certificate.p12
    keychain add-certificates --certificate /tmp/certificate.p12 --certificate-password $DIST_CERTIFICATE_PASSWORD    

Option 1 では xcode-project detect-bundle-id でプロジェクトからバンドル ID を自動取得しています。手動で値を指定することも可能ですが、ミス防止のため自動取得を推奨します。

  1. Xcode プロジェクト上の署名設定

xcode-project use-profiles コマンドを使って、取得またはデコードしたプロビジョニングプロファイルを Xcode プロジェクトに適用します。

- name: Set up code signing settings on Xcode project
  run: xcode-project use-profiles
  1. ビルド番号のインクリメント

TestFlight 上の最新ビルド番号を取得し、1 増やして新しいビルド番号を設定します。

- name: Increment build number
  run: |
    cd ios
    agvtool new-version -all $(($(app-store-connect get-latest-testflight-build-number "$APP_STORE_APPLE_ID") + 1))    

Codemagic CLI ツールには Google Play 用 にも同様のコマンドがあります。バージョニングはストアごとに一貫して管理するのが難しいことが多いですが、このツールを使えば毎回確実にビルド番号が 1 ずつ増加し、疑似的なビルド番号に頼る必要がなくなります。特に両ストアへデプロイする場合に非常に便利です。

  1. ipa ファイルのビルド

配布用の ipa ファイルを作成するには、flutter build ipa コマンドを使用し、--release フラグでリリースモードのビルドを行います。さらに、アーカイブ設定を正しく行うために --export-options-plist フラグも追加してください。

- name: Build ipa for distribution
  run: |
    flutter build ipa --release --export-options-plist=$HOME/export_options.plist    

export_options.plist ファイルは xcode-project use-profiles コマンドの出力です。

  1. App Store Connect への公開

app-store-connect publish コマンドを使い、ビルド済みのアプリを --path フラグでファイルパスを指定して App Store Connect へアップロードします。

- name: Publish the app to App Store Connect
  run: |
    APP_FILE=$(find $(pwd) -name "*.ipa")
    app-store-connect publish \
    --path "$APP_FILE"    

これで、GitHub Actions と Codemagic CLI ツールを使って iOS アプリを App Store Connect へ自動的に公開するワークフローが完成します。

このパイプラインを使えば、ビルドごとにバージョンが自動的にインクリメントされ、アプリがアップロードされることを保証できます。下記のスクリーンショットは、自動署名・手動署名の両方のワークフローを実行した結果です(どちらか一方のみ設定した場合は、もちろんビルドは一つだけになります)。

コードサンプル(自動署名の場合)

以下は、新しいコード署名情報(証明書とプロファイル)の生成を自動で処理する場合のコードサンプル例の全体になります。

name: Publish to App Store Connect

on:
 workflow_dispatch:
 
jobs:
 build:
   runs-on: macos-latest
   env:
     APP_STORE_CONNECT_ISSUER_ID: ${{ vars.APP_STORE_CONNECT_ISSUER_ID }}
     APP_STORE_CONNECT_KEY_IDENTIFIER: ${{ vars.APP_STORE_CONNECT_KEY_IDENTIFIER }}
     APP_STORE_CONNECT_PRIVATE_KEY: ${{ secrets.APP_STORE_CONNECT_PRIVATE_KEY }}
     CERTIFICATE_PRIVATE_KEY: ${{ secrets.CERTIFICATE_PRIVATE_KEY }}
     APP_STORE_APPLE_ID: ${{ vars.APP_STORE_APPLE_ID }}

   steps:
   - uses: actions/checkout@v4

   - name: Set up Flutter
     uses: subosito/flutter-action@v2
     with:
       channel: 'stable'

   - name: Install Codemagic CLI tools
     run: pip install codemagic-cli-tools

   - name: Set up keychain
     run: keychain initialize

   - name: Fetch signing files
     run: |
       app-store-connect fetch-signing-files $(xcode-project detect-bundle-id) \
       --type IOS_APP_STORE \
       --create       

   - name: Set up signing certificate
     run: keychain add-certificates

   - name: Set up code signing settings on Xcode project
     run: xcode-project use-profiles

   - name: Increment build number
     run: |
       cd ios
       agvtool new-version -all $(($(app-store-connect get-latest-testflight-build-number "$APP_STORE_APPLE_ID") + 1))       

   - name: Build ipa for distribution
     run: |
       flutter build ipa --release --export-options-plist=$HOME/export_options.plist       

   - name: Publish the app to App Store Connect
     run: |
       APP_FILE=$(find $(pwd) -name "*.ipa")
       app-store-connect publish \
       --path "$APP_FILE"       

コードサンプル(手動署名の場合)

以下は、既存のコード署名情報をパイプラインで利用する場合のコードサンプル全体になります。

name: Publish to App Store Connect (manual)

on:
 workflow_dispatch:

jobs:
 build:
   runs-on: macos-latest
   env:
     APP_STORE_CONNECT_ISSUER_ID: ${{ vars.APP_STORE_CONNECT_ISSUER_ID }}
     APP_STORE_CONNECT_KEY_IDENTIFIER: ${{ vars.APP_STORE_CONNECT_KEY_IDENTIFIER }}
     APP_STORE_CONNECT_PRIVATE_KEY: ${{ secrets.APP_STORE_CONNECT_PRIVATE_KEY }}
     DIST_CERTIFICATE: ${{ secrets.DIST_CERTIFICATE }}
     DIST_CERTIFICATE_PASSWORD: ${{ secrets.DIST_CERTIFICATE_PASSWORD }}
     DIST_PROFILE: ${{ secrets.DIST_PROFILE }}
     APP_STORE_APPLE_ID: ${{ vars.APP_STORE_APPLE_ID }}

   steps:
   - uses: actions/checkout@v4

   - name: Set up Flutter
     uses: subosito/flutter-action@v2
     with:
       channel: 'stable'

   - name: Install Codemagic CLI tools
     run: pip install codemagic-cli-tools

   - name: Set up keychain
     run: keychain initialize

   - name: Set up Provisioning profiles
     run: |
       PROFILES_HOME="$HOME/Library/MobileDevice/Provisioning Profiles"
       mkdir -p "$PROFILES_HOME"
       PROFILE_PATH="$(mktemp "$PROFILES_HOME"/$(uuidgen).mobileprovision)"
       echo ${DIST_PROFILE} | base64 --decode > "$PROFILE_PATH"
       echo "Saved provisioning profile $PROFILE_PATH"            
   - name: Set up signing certificate
     run: |
       echo $DIST_CERTIFICATE | base64 --decode > /tmp/certificate.p12
       keychain add-certificates --certificate /tmp/certificate.p12 --certificate-password $DIST_CERTIFICATE_PASSWORD       

   - name: Set up code signing settings on Xcode project
     run: xcode-project use-profiles

   - name: Increment build number
     run: |
       cd ios
       agvtool new-version -all $(($(app-store-connect get-latest-testflight-build-number "$APP_STORE_APPLE_ID") + 1))       

   - name: Build ipa for distribution
     run: |
       flutter build ipa --release --export-options-plist=$HOME/export_options.plist       

   - name: Publish the app to App Store Connect
     run: |
       APP_FILE=$(find $(pwd) -name "*.ipa")
       app-store-connect publish \
       --path "$APP_FILE"       

おまけ – ローカル環境での利用について

Codemagic CLI ツールは、CI/CD パイプラインだけでなくローカル環境でも便利に利用できます。CI/CD 環境と同様に、ローカルで利用する場合も Python 3.8 以上が必要です。

まずは、以下のコマンドでツールをインストールしましょう:

pip3 install codemagic-cli-tools

ローカルでツールを実行することで、CI/CD パイプラインで利用する前に環境変数や設定をテストでき、トラブルシューティングやデバッグが容易になります。これにより、CI/CD のビルド時間の節約も見込めます。

Codemagic の公式ドキュメント には、アプリのビルドアーカイブ作成などローカル利用の例が掲載されています。尚、ローカルマシンで keychain initialize を実行した後は、keychain use-login も実行してログインキーチェーンをデフォルト設定にしてください。これにより、アプリの認証問題を防ぐことができます。

Codemagic CLI ツールはアーカイブ作成だけでなく、チェンジログ生成やレビュー提出管理、デバイス登録など様々な作業を効率化できます。

チェンジログの生成

git-changelog generate コマンドを実行すると、リポジトリ内で行った変更(コミット)の一覧テキストを自動生成できます。

vearnold@Arnolds-MBP cm_cli_tools_demo % git-changelog generate
* Add manual pipeline
* Add pipeline
* Create flutter demo project
Generated 3 change log lines

git-changelog ツールの詳細や使い方は公式ドキュメントをご覧ください。

レビュー提出の自動化

app-store-connect review-submissions コマンドを使うことで、アプリのレビュー提出を管理できます。CI/CD 上やローカル環境において、アプリの審査提出プロセスを自動化することが出来て非常に便利です。このツールの導入により、時間のかかるビルドのステータスを確認し、準備ができたタイミングで提出することができます。

Codemagic CI/CD ではこの機能がパイプラインに組み込まれているため、Apple への通知用スクリプトを自作する必要はありません。ビルド完了後の Post-processing ステップで自動的に実行され、ビルド分数を消費することもありません。そして、これは他の CI/CD パイプラインやローカル環境でも同様に活用できます。

review-submissions ツールの詳細や使い方は公式ドキュメントをご覧ください。

デバイス登録の自動化

app-store-connect devices register コマンドを使うことで、プロビジョニングプロファイルに新しいデバイスを登録できます。新しい実機でアプリをテストしたい場合、Apple Developer Portal で手動登録する必要がなく、このコマンドでデバイス名と UDID を指定するだけで簡単に登録できます。

app-store-connect devices register --name iPhone8-Arnold --udid 

テストデバイスが多数ある場合でも、一括で登録できるため非常に効率的です。

app-store-connect devices ツールの詳細や使い方は公式ドキュメントをご覧ください。

おわりに

Codemagic CI/CD は、モバイル開発やコード署名、シンプルな YAML 設定に最適化された最新の環境を提供するだけでなく、CLI ツールを活用することで Codemagic 内外のパイプラインでも追加機能を利用できます。ローカル環境でも CI/CD パイプライン上でも、これらのツールを使うことで柔軟かつ効率的にモバイルアプリのビルド・公開が可能です。

本記事では、Codemagic CLI ツールを使って GitHub Actions パイプラインから iOS ビルドを App Store Connect へ公開する手順を紹介し、その手軽さと柔軟性を解説しました。ぜひ一度お試しください!

さらに詳しく知りたい方へ

Leave a Comment

Verified by MonsterInsights