メインコンテンツにジャンプ
CI/CD

自動 Capacitor IOS ビルドと GitHub アクションのマッチング

How to set up a CI/CD pipeline for your IOS Ionic app using fastlane and GitHub Actions in 5 mins (2022)

マーティン・ドナディュー

マーティン・ドナディュー

コンテンツマーケター

自動 Capacitor IOS ビルドと GitHub アクションのマッチング

iOSの自動ビルドを行うためのGitHubアクションを使用します。

CI/CDの設定を行うためのCapacitorアプリの設定は複雑で時間がかかります。ここでは必要な情報をご紹介します。

現在、__CAPGO_KEEP_0__ビルドを使用することをお勧めします。 CapgoビルドとCapgoCLIを使用します。 ネイティブのCapacitorビルドのために使用します。 このFastlane Matchのガイドは、既存のGitHubアクションのパイプラインを維持しているチーム向けのものですが、新しいiOSビルドの場合はCapgoCLIを使用することをお勧めします。これにより、Fastlane、Matchのリポジトリ、Xcodeランナー、証明書、アップロードスクリプトの維持を自分で行う必要がなくなります。

CapgoビルドはCapgoによってCI/CDを実行します。

Fastlane Match、Xcodeランナー、証明書、プロビジョニングプロファイル、アップロードスクリプトの維持をスキップします。 Capgoビルド __CAPGO_KEEP_0__ビルドは、既存のCI/CDパイプラインから署名されたネイティブのiOSビルドを実行します。

  • 既存のパイプラインと連携します。: Capgo を GitHub からビルドするトリガー npx cap sync.
  • CIシークレットから署名: App Store Connectのキー、証明書、プロビジョニングプロファイル、パスワード、チームIDをCIシークレットに保存してください。
  • ネイティブランナーのメンテナンスなし: Capgo ビルドはAppleのビルド環境を維持しているので、macOSランナー、Xcodeイメージ、Fastlane、またはMatchリポジトリを管理する必要がありません。
  • アーティファクトと提出: QA用に署名済みアーティファクトをダウンロードしたり、Capgo CLI を通じてリリースビルドを提出することができます。

価格

  • Capgo プランは月額 $12 で始まります。
  • OTA更新と約 15 回のネイティブビルドが含まれます。
  • 追加のビルド分数はクレジット単位で請求されます。

Capgo ビルドをCI/CDに設定してください。

マニュアルセットアップガイド

ここで、行う必要のあることを説明します:

iOS向けのFastlaneとGitHubアクションを使用した継続的デリバリー

前提条件

チュートリアルを続ける前に…

価格についての注意

価格 GitHub アクション

https://github.com/features/actions

制限まで無料です。選択したマシンに依存します。
このチュートリアルで使用するのは macOS マシンです。スクリーンショットに表示されている価格と制限(価格はこのチュートリアルの作成時点のもので、将来の変更が可能です)をご覧になれます。

🔴 要件と価格についての注意を出してから、続ける場合はどうですか?

📣 この投稿では、iTunes Connectでアプリを作成し、Apple エコシステムの証明書を持っていることを前提としています。Fastlaneですべてをコピーします。

では、始めましょう!

この投稿で従うべきステップ

  1. App Store Connectを使用するAPIとFastlane Matchを使用する
  2. 要件
  3. App Store ConnectAPIキーを作成する
  4. App Store ConnectAPIキーを使用する
  5. Fastlaneファイルをコピーする
  6. Fastlane matchを設定する

1. App Store ConnectAPIを使用するFastlane Match

2021年2月以降、すべてのユーザーがApp Store Connectにサインインするには、2要素認証または2段階認証が必要になります。Apple IDの追加セキュリティ層は、自分のアカウントにアクセスできるのは自分だけであることを保証するのに役立ちます。
From Apple Support

matchを使用して始めるには、既存の証明書を取り消す必要があります。ですが、心配する必要はありません。新しい証明書は直接取得できます。

要件

App Store Connect API を使用するには、Fastlane が 3 つの 必要なものがあります。

  1. 発行者 ID.
  2. キー ID.
  3. キー ファイルまたはキー コンテンツ。

App Store Connect API キーを作成する

キーを生成するには、App Store Connect での Admin 権限が必要です。権限がない場合は、この記事を指示することで、関連する人に権限を与えることができます。次に、以下の手順に従ってください。

1 — App Store Connect に ログインする.

2 — ユーザーとアクセスを選択する.

App Store Connectユーザー権限

3 — Integrationタブを選択してください。

App Store ConnectAPI統合

4 — Generate API KeyまたはAdd(+)ボタンをクリックしてください。

App Store ConnectAPIキーを作成

5 — キーの名前を入力してください。名前はあなたの参考用にのみ使用され、キー自体には含まれません。

App Store ConnectAPIキーを作成する名前

6 — アクセスセクションで、キーに対するロールを選択してください。キーに対するロールは、チームのユーザーに対するロールと同じです。詳しくは ロールの権限をご覧ください。 App Store Connect__CAPGO_KEEP_0__キーを作成するロール.

7 — App managerを選択してください。

API のアクセスは特定のアプリに制限できません。

新しいキー名、キーID、ダウンロードリンク、他情報がページに表示されます。

App Store Connect ダウンロードキー

必要な3つの情報をすべてここで取得できます。
<1> Issue ID.
<2> Key ID.
&#x3C;3> Click “Download API Key” to download your API private key. The download link appears only if the private key has not yet been downloaded. Apple does not keep a copy of the private key. So, you can download it only once.

🔴 プライベートキーを安全な場所に保存してください。キーを共有しないでください、キーを code リポジトリに保存しないでください、またはクライアントサイド code にキーを含めないでください。

App Store Connect API キーを使用する

API キー ファイル(ダウンロードしたp8ファイル)、キーID、発行者IDが必要です。これらの情報をFastlaneにinputする方法は複数あります。Fastlaneの新しいアクションを使用して、 app_store_connect_api_keyFastlaneドキュメントを参照してください。 Fastlaneドキュメントを参照してください。. CI環境の多くで環境変数を設定できるため、最も簡単な方法と考えているため、この方法を示します。

App Store ConnectのAPIキーを使用してFastlaneを管理できるようになりましたね!

2. Fastlaneファイルのコピー

Fastlaneは、Android Studioを使用せずにモバイル開発タスクを自動化するためのRubyライブラリです。Fastlaneを使用すると、カスタムの「レーン」を構成できます。これらの「レーン」には、「アクション」が含まれます。これらの「アクション」は、通常、Android Studioを使用して実行するタスクを実行します。Fastlaneを使用すると、多くのことが実行できますが、このチュートリアルの目的のために、コアアクションの少数を使用することになります。

プロジェクトのルートディレクトリにFastlaneフォルダを作成し、次のファイルをコピーしてください: Fastfile

default_platform(:ios)

DEVELOPER_APP_IDENTIFIER = ENV["DEVELOPER_APP_IDENTIFIER"]
DEVELOPER_APP_ID = ENV["DEVELOPER_APP_ID"]
PROVISIONING_PROFILE_SPECIFIER = ENV["PROVISIONING_PROFILE_SPECIFIER"]
TEMP_KEYCHAIN_USER = ENV["TEMP_KEYCHAIN_USER"]
TEMP_KEYCHAIN_PASSWORD = ENV["TEMP_KEYCHAIN_PASSWORD"]
APPLE_ISSUER_ID = ENV["APPLE_ISSUER_ID"]
APPLE_KEY_ID = ENV["APPLE_KEY_ID"]
APPLE_KEY_CONTENT = ENV["APPLE_KEY_CONTENT"]
GIT_USERNAME = ENV["GIT_USERNAME"]
GIT_TOKEN = ENV["GIT_TOKEN"]

def delete_temp_keychain(name)
  delete_keychain(
    name: name
  ) if File.exist? File.expand_path("~/Library/Keychains/#{name}-db")
end

def create_temp_keychain(name, password)
  create_keychain(
    name: name,
    password: password,
    unlock: false,
    timeout: 0
  )
end

def ensure_temp_keychain(name, password)
  delete_temp_keychain(name)
  create_temp_keychain(name, password)
end

platform :ios do
  lane :build do
    build_app(
      configuration: "Release",
      workspace: "./ios/App/App.xcworkspace",
      scheme: "App",
      export_method: "app-store",
      export_options: {
        provisioningProfiles: { 
            DEVELOPER_APP_ID => "#{PROVISIONING_PROFILE_SPECIFIER}"
        }
      }
    )
  end
  lane :refresh_profiles do
    match(
      type: "development",
      force: true)
    match(
      type: "adhoc",
      force: true)
  end
  desc "Register new device"
  lane :register_new_device do  |options|
      device_name = prompt(text: "Enter the device name: ")
      device_udid = prompt(text: "Enter the device UDID: ")
      device_hash = {}
      device_hash[device_name] = device_udid
      register_devices(
                       devices: device_hash
                       )
    refresh_profiles
  end
  lane :closed_beta do
    keychain_name = TEMP_KEYCHAIN_USER
    keychain_password = TEMP_KEYCHAIN_PASSWORD
    ensure_temp_keychain(keychain_name, keychain_password)

    api_key = app_store_connect_api_key(
      key_id: APPLE_KEY_ID,
      issuer_id: APPLE_ISSUER_ID,
      key_content: APPLE_KEY_CONTENT,            
      duration: 1200,            
      in_house: false
    )

    match(
      type: 'appstore',
      git_basic_authorization: Base64.strict_encode64("#{GIT_USERNAME}:#{GIT_TOKEN}"),
      readonly: true,
      keychain_name: keychain_name,
      keychain_password: keychain_password,
      api_key: api_key
    )

    gym(
      configuration: "Release",
      workspace: "./ios/App/App.xcworkspace",
      scheme: "App",
      export_method: "app-store",
      export_options: {
        provisioningProfiles: { 
            DEVELOPER_APP_ID => "#{PROVISIONING_PROFILE_SPECIFIER}"
        }
      }
    )

    pilot(
      apple_id: "#{DEVELOPER_APP_ID}",
      app_identifier: "#{DEVELOPER_APP_IDENTIFIER}",
      skip_waiting_for_build_processing: true,
      skip_submission: true,
      distribute_external: false,
      notify_external_testers: false,
      ipa: "./App.ipa"
    )

    delete_temp_keychain(keychain_name)
  end
  lane :submit_review do
    version = ''
    Dir.chdir("..") do
      file = File.read("package.json")
      data = JSON.parse(file)
      version = data["version"]
    end
    deliver(
      app_version: version,
      submit_for_review: true,
      automatic_release: true,
      force: true, # Skip HTMl report verification
      skip_metadata: false,
      skip_screenshots: false,
      skip_binary_upload: true
    )
  end
end

Appfile

app_identifier(ENV["DEVELOPER_APP_IDENTIFIER"])
apple_id(ENV["FASTLANE_APPLE_ID"])
itc_team_id(ENV["APP_STORE_CONNECT_TEAM_ID"])
team_id(ENV["DEVELOPER_PORTAL_TEAM_ID"])

Fastlaneの設定

Fastlane match iOSのcode署名に新しいアプローチです。Fastlane matchは、iOSアプリの必要な証明書とプロビジョニングプロファイルを管理するチームに簡単にアクセスできるようにします。

新しいプライベートリポジトリを作成してください、 certificates例えば、GitHubの個人アカウントまたは組織で

iOSアプリのFastlane matchを初期化します。

fastlane match init

次に、オプション#1(Git Storage)を選択します。

[01:00:00]: fastlane match supports multiple storage modes, please select the one you want to use:1. git2. google_cloud3. s3?

新しく作成されたリポジトリのURLを割り当てます。

[01:00:00]: Please create a new, private git repository to store the certificates and profiles there[01:00:00]: URL of the Git Repo: <YOUR_CERTIFICATES_REPO_URL>

Fastlaneフォルダ内にファイル名が"Matchfile"のファイルが作成されます。 この"Matchfile"は、証明書リポジトリのHTTPS URLに設定する必要があります。 オプションでSSHを使用することもできますが、実行するための別のステップが必要になります。 _git_url_次に、Fastlane Matchで証明書を生成し、必要な情報を入力してください。

# ios/Matchfilegit_url("https://github.com/gitusername/certificates")storage_mode("git")type("appstore")

__CAPGO_KEEP_0__アクションが証明書リポジトリを復号するために使用するパスフレーズを入力するように求められます。

You will be prompted to enter a passphrase. Remember it correctly because it will be used later by GitHub Actions to decrypt your certificates repository.

fastlane match appstore

__CAPGO_KEEP_0__と必要な権限に関して問題が発生した場合、以下の記事を参照してください。

[01:40:52]: All required keys, certificates and provisioning profiles are installed 🙌

If you experienced any problem with GitHub and the necessary permissions, maybe this post gitの認証トークンを生成するのに役立ちます。

生成された証明書とプロビジョニングプロファイルは、証明書リポジトリのリソースにアップロードされます。

App Store Connect証明書

最後に、 project Xcodeで開き、リリース構成のアプリのプロビジョニングプロファイルを更新してください。

XCode証明書

💡注意点

MATCH

CI/CDが証明書とプロビジョニングプロファイルをインポートするには、証明書リポジトリにアクセスする必要があります。

In GitHub, go to In __CAPGO_KEEP_0__、設定パーソナル アクセス トークン → クリック Generate New Token → チェック repo スコープ → その後クリック Generate token.

パーソナル アクセス トークンを作成

__CAPGO_KEEP_0__ Actionsで使用する証明書とプロビジョニング プロファイルをインポートするために、__CAPGO_KEEP_0__で生成されたパーソナル アクセス トークンを使用します。後で環境変数として使用します。 GIT_TOKEN.

Fastlane フォルダ内の生成されたマッチ ファイルを置き換えます Matchfile

CERTIFICATE_STORE_URL = ENV["CERTIFICATE_STORE_URL"]
GIT_USERNAME = ENV["GIT_USERNAME"]
GIT_TOKEN = ENV["GIT_TOKEN"]
FASTLANE_APPLE_ID = ENV["FASTLANE_APPLE_ID"]

git_url(CERTIFICATE_STORE_URL)
storage_mode("git")
type("appstore")
git_basic_authorization(Base64.strict_encode64("#{GIT_USERNAME}:#{GIT_TOKEN}"))
username(FASTLANE_APPLE_ID)

This will be used by GitHub Actions to import the certificates and provisioning profiles. And var will be set in GitHub Secrets, instead of hard-coding them in the file.

__CAPGO_KEEP_0__ Actionsで実行されるCI/CD ワークフローに基づいて、実行時間に応じて請求されます。実際には、App Store Connectでビルドが処理されるまでに約10~15分かかります。

In GitHub Actions, あなたはCI/CDワークフローを実行するのにかかった分数に基づいて請求されます。実際には、App Store Connectでビルドが処理されるまでに約10~15分かかります。 10~15分

For private projects, the estimated cost per build can go up to $0.08/min x 15分 = $1.2, or more, depending on the configuration or dependencies of your project.

If you share the same concerns for the pricing as I do for private projects, you can keep the skip_waiting_for_build_processing to true.

What’s the catch? You have to manually update the compliance of your app in App Store Connect after the build has been processed, for you to distribute the build to your users.

This is just an optional parameter to update if you want to save on the build minutes for private projects. For free projects, this shouldn’t be a problem at all. See pricing.

3. Setup GitHub Actions

Configure GitHub secrets

Ever wonder where the values of the ENV are coming from? Well, it’s not a secret anymore – it’s from your project’s secret. 🤦

 GitHub を設定するシークレットを設定してください

1. APP_STORE_CONNECT_TEAM_ID - App Store Connect のチーム ID

2. DEVELOPER_APP_ID - App Store Connect にアクセスし、 アプリ情報 → 下にスクロールしてアプリの General Information セクションを探してください Apple ID.

3. DEVELOPER_APP_IDENTIFIER - アプリのバンドル ID

4. DEVELOPER_PORTAL_TEAM_ID - デベロッパーポータルのチーム ID

5. FASTLANE_APPLE_ID - アプリを管理するために使用する Apple ID またはデベロッパー E メール

6. GIT_USERNAME &#x26; GIT_TOKEN - Git のユーザー名とパーソナル アクセス トークン

7. MATCH_PASSWORD - match を初期化したときに割り当てたパスフレーズが使用され、証明書とプロビジョニング プロファイルを暗号化するために使用されます。

8. PROVISIONING_PROFILE_SPECIFIER - match AppStore <YOUR_APP_BUNDLE_IDENTIFIER>, 例。 match AppStore com.domain.blabla.demo.

9. TEMP_KEYCHAIN_USER &#x26; TEMP_KEYCHAIN_PASSWORD - ワークフロー用に一時的なキーチェーンユーザーとパスワードを割り当てます。

10. APPLE_KEY_ID — App Store Connect API キー 🔺キーID。

11. APPLE_ISSUER_ID — App Store Connect API キー 🔺発行者ID。

12. APPLE_KEY_CONTENT — App Store Connect API キー 🔺キーファイルまたはキーコンテンツ (.p8)。 確認してください。, — Match キーのリポジトリ URL (例:

13. CERTIFICATE_STORE_URL https://__CAPGO_KEEP_0__.com/***/fastlane_match.git 4. github ワークフロー ファイルを設定します。)

GitHub ワークフロー ディレクトリを作成します。

4. GitHub workflow fileを設定します。

cd .github/workflows

フォルダ内で、ファイル名を workflow に作成し、以下の内容を追加してください。 build-upload-ios.ymlこのワークフローは、各__CAPGO_KEEP_0__

name: Build source code on ios

on:
  push:
    tags:
      - '*'

jobs:
  build_ios:
    runs-on: macOS-latest
    steps:
      - uses: actions/checkout@v6
      - name: set Node.js
        uses: actions/setup-node@v6
        with:
          node-version: '24'
          cache: npm
      - name: Install dependencies
        id: install_code
        run: npm ci
      - name: Build
        id: build_code
        run: npm run build
      - uses: actions/cache@v5
        with:
          path: ios/App/Pods
          key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }}
          restore-keys: |
            ${{ runner.os }}-pods-
      - name: Sync
        id: sync_code
        run: npx cap sync
      - uses: ruby/setup-ruby@v1
        with:
          ruby-version: 2.7.2
      - uses: maierj/fastlane-action@v2.3.0
        env:
          DEVELOPER_APP_IDENTIFIER: ${{ secrets.DEVELOPER_APP_IDENTIFIER }}
          DEVELOPER_APP_ID: ${{ secrets.DEVELOPER_APP_ID }}
          PROVISIONING_PROFILE_SPECIFIER: match AppStore ${{ secrets.DEVELOPER_APP_IDENTIFIER }}
          TEMP_KEYCHAIN_USER: ${{ secrets.TEMP_KEYCHAIN_USER }}
          TEMP_KEYCHAIN_PASSWORD: ${{ secrets.TEMP_KEYCHAIN_PASSWORD }}
          APPLE_ISSUER_ID: ${{ secrets.APPLE_ISSUER_ID }}
          APPLE_KEY_ID: ${{ secrets.APPLE_KEY_ID }}
          APPLE_KEY_CONTENT: ${{ secrets.APPLE_KEY_CONTENT }}
          CERTIFICATE_STORE_URL: https://github.com/${{ secrets.CERTIFICATE_STORE_REPO }}.git
          GIT_USERNAME: ${{ secrets.GIT_USERNAME }}
          GIT_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
          FASTLANE_APPLE_ID: ${{ secrets.FASTLANE_APPLE_ID }}
          MATCH_USERNAME: ${{ secrets.FASTLANE_APPLE_ID }}
          MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
          APP_STORE_CONNECT_TEAM_ID: ${{ secrets.APP_STORE_CONNECT_TEAM_ID }}
          DEVELOPER_PORTAL_TEAM_ID: ${{ secrets.DEVELOPER_PORTAL_TEAM_ID }}
        with:
          lane: closed_beta
      - name: Upload release bundle
        uses: actions/upload-artifact@v2
        with:
          name: ios-release
          path: ./App.ipa
          retention-days: 60

This workflow should be triggered after each GitHub を参照してください。自動ビルドとリリースのワークフロー Automatic build and release with GitHub actions 最初に、このワークフローはNode.jsの依存関係を取得し、JavaScriptアプリケーションをビルドします。

各コミットを送信すると、テストフライトでリリースが作成されます。

アプリはIonicを使用する必要はありません。ただし、

Your App doesn’t need to use Ionic, only Capacitor base is mandatory., it can have old Cordova module, but Capacitor JS plugin should be preferred.

JSプラグインを使用することを推奨します。

Create a Commit

Make a commitTrigger the workflow

Trigger the workflow

Push the new commits to the branch main or development to trigger the workflow.

Started with commit

After a few minutes, the build should be available in your App Store Connect dashboard.

After a few minutes, the build should be available in your App Store Connect dashboard.

Testflight Dashboardの表示は可能ですか?

Yes, you can, and it is effortless.

Imagine that you have a private repository, and you have used up the minutes of the free plan and you do not want to pay for new releases, or maybe you prefer to submit the application manually.

Let's go for it

Ok, first we need to create in my_project_path/fastlane path a file called .env, just in the same path as Fastfile, to be able to create the same secret properties found in our _GitHub, a_s below:

.envファイルのローカルマシンからのデプロイ

現在、ローカルマシンからデプロイするための.envファイル ローカルマシンからデプロイするための.envファイル ローカルマシンからデプロイするための.envファイル ローカルマシンからデプロイするための.envファイル ローカルマシンからデプロイするための.envファイル

fastlane closed_beta

❌ .envファイルの重要な点ですが、データを公開するのを避けるため、.gitignoreに追加する必要があります。 ❌ 例えば、次のように追加します。 ローカルマシンからデプロイするための.envファイル ローカルマシンからデプロイするための.envファイルローカルマシンからデプロイするための.envファイル

fastlane/*.env

It should work the same as it happens from GitHub Actions on the remote machine but in our local machine. 🍻

ローカルFastlane実行

ターミナル実行: $ Fastlane closed_beta

ここまで来たら、祝福の言葉を贈ります。FastlaneとGitHubアクションでiOSアプリの完全自動化プロセスを手に入れました。

毎回コミットを送信するたびに、Google Playコンソールのベータチャンネルでリリースが作成されます。 martin@capgo.app

martin@__CAPGO_KEEP_0__.app

デバイス上でビルド デバイス上でビルドする必要がある場合は、手動でプロビジョニングに追加する必要があります。
デバイスをMacに接続し、デバイスメニューを開きます。 デバイスiOSメニュー 次に、識別子をコピーしてください。 識別子iOS fastlane register_new_device 次に、以下のコマンドを実行してください。 識別子を設定(iOS)

問題が発生した場合

開発用デバイスでテストできないなど問題が発生した場合、通常はその解決策で済みます。

あなたを救う魔法のコマンドがあります:

fastlane match nuke development
fastlane match development

次に: プロジェクトをクリーンするためにShift(⇧)+Command(⌘)を押してください、またはProduct > Clean(プロジェクトをクリーンする)を選択してください(「Clean Build Folder」とラベル付けされている場合もあります)

次に、デバイス上でアプリを再度実行してください。

ありがとうございます

このブログは以下の記事に基づいています:

自動的にGitHubアクションを使用してCapacitorのiOSビルドを続行してください

Capgoを使用している場合 自動的なCapacitor IOSビルドをGitHubアクションで実行するには、matchを使用します。 CI/CDの自動化を計画するには、__CAPGO_KEEP_0__ CI/CDに接続します。 Capgo CI/CD Capgo CI/CDの製品ワークフロー Capgo Native Builds Capgo Native Buildsの製品ワークフロー Capgo Integrations Capgo Integrationsの製品ワークフロー CI/CDの統合 CI/CD統合の実装詳細 GitHub Actions Integration 実装詳細の GitHub Actions統合のために。

Capacitor アプリのリアルタイム更新

Capgo を使用して、ウェブ層のバグが生じた場合に、修正をアプリストアの承認待ちの日数を待たずに配信することができます。ユーザーはバックグラウンドで更新を受け取り、ネイティブの変更は通常のレビュー経路を通じます。

今すぐ始める

最新のブログ記事

Capgo で最も必要な洞察を得て、実際にプロフェッショナルなモバイルアプリを作成できます。