記事

iOS Certificates, Identifiers & Profilesの関係|Fastlane Matchで憑證管理とCI/CDを効率化

iOS開発者向けにCertificates, Identifiers & Profilesの関係性を明確化し、Fastlane Matchで証明書を一元管理。CI/CD統合で手動作業を削減し、開発効率を大幅向上させる方法を具体的に紹介。

iOS Certificates, Identifiers & Profilesの関係|Fastlane Matchで憑證管理とCI/CDを効率化

本記事は AI による翻訳をもとに作成されています。表現が不自然な箇所がありましたら、ぜひコメントでお知らせください。

記事一覧


iOS Certificates, Identifiers & Profiles とは何かおよび Fastlane Match による統一 管理 証明書と CI/CD に関するメモ

Certificates、Identifiers、Profilesの関係とFastlane Matchを使った証明書の一元管理およびCI/CDワークフローへの統合についての記録。

Photo by [marcos mayer](https://unsplash.com/@mmayyer?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText){:target="_blank"}

Photo by marcos mayer

はじめに

2025年中に、GitHub Actionsを使ってAppのCI/CDの完全なワークフローを0から1まで構築する一連の記事を書きました:

最近、新しい環境で再度実行しましたが、そのたびに新しいことを学んでいます。今回はiOSコードサイニングのCertificates / Profiles / Devicesの関係に焦点を当て、Fastlane Matchを使って証明書管理とCI/CDを連携させる方法についてです。

Certificates, Identifiers & Profiles, Devices とは?

Appleエコシステムでは、アプリ開発は証明書とプロビジョニングプロファイルの管理に基づいており、Androidのように.apkファイルがあればインストールして使用できるわけではありません。Appleは厳格な証明書対応管理を行っており、規則に合わないものはインストールや使用ができません。

主な項目の構成と機能:

Certificates: アプリ署名の身分(Signing Identity)

  • Development — 開発段階では実機で使用します(シミュレーターのみの場合は証明書不要)。所属は個人またはAPIキー(数に制限あり)です。

  • Distribution — AppStore、TestFlight、またはAd Hocの内部テスト(登録済みデバイス限定)での配布に使用され、数に制限があり、Teamに属します。

  • Enterprise — 企業内向けアプリの使用。

フォーマット :使用するには Private Key(秘密鍵)Certificate .cer(公開鍵証明書) が必要です。または、元の作成したパソコンのKeychainから .p12 ファイルとしてエクスポートすると両方が含まれます。

Identifiers: どの App/Extension (Bundle ID)

AppのBundle ID登録と有効にする必要があるCapabilities(例:Push Notificationsの有効化、App Groups…)、App Services。

Extensionにも独自のIdentifierがあります。

Devices: 登録済みデバイス (iPhone/iPadなど)

Development は実機での動作、Distribution Ad Hoc の内部テストは登録されたデバイスのみ使用可能です。

上限:100個;キャンセルを含み、毎年の支払いサイクルまでリリース枠はリセットされません。

Provisioning Profile (以下簡称 Profile): プロビジョニングプロファイル

Certificates+Identifiers+Devices の関係の組み合わせ。

  • Development — 開発段階で使用するプロビジョニングプロファイルで、実機テストを行う際に必ず使用します。プロファイルにはCertificates、Identifiers、Devicesの関係が含まれています。

  • Ad Hoc — 内部テスト用にパッケージ化されたプロビジョニングプロファイル(例:Firebase App Distributionへのデプロイ)で、プロファイルはCertificates、Identifiers、Devicesの関係を含みます。

  • App Store — App Store / TestFlight にアップロードするためのパッケージに使用されるプロビジョニングプロファイルで、プロファイルはCertificatesとIdentifiersの関係を含みます。

フォーマット: .mobileprovision

注意:Profileはあくまで記述ファイルであり、証明書そのものは含みません。

まとめ

総合すると、クリーンなマシンでXcodeのAppleアカウントにログインせずに実機ビルド(Development Certificate)やアーカイブビルド(Distribution Certificate)を行うには、2つのファイルが必要です

  • .mobileprovision プロビジョニングプロファイル: Certificates、Identifiers、Devices の関係を記述。

  • .p12 Certificate: 証明書の実体(元の証明書を作成したコンピュータからエクスポート)。

また macOS 15以降の Keychain は以下に移動しました:

1
open /System/Library/CoreServices/Applications/Keychain\ Access.app

ずっと探してた…

よくあるエラー

⚠️⚠️⚠️ 証明書やプロファイルが正しいのにエラーが出る場合:

多くの場合、古い証明書や複数の証明書が残っているため、Xcodeが混乱します。

この問題はよく発生します!

  1. Xcodeを閉じる

  2. macOSキーチェーンを開く: open /System/Library/CoreServices/Applications/Keychain\ Access.app

  3. loginキーチェーン -> すべての項目 -> 「apple development」を検索 -> すべての証明書を削除

  4. Finder -> 移動 -> フォルダへ移動 -> ~/Library/MobileDevice/Provisioning\ Profiles -> すべてのプロファイルを削除する

  5. 証明書を再取得する

  6. Xcodeを再起動すれば正常に動作するはずです。

署名用の証明書「iOS Distribution」が見つかりません / 署名用の証明書「iOS Development」が見つかりません:

チームID "" に一致するプライベートキー付きの「iOS Distribution」署名証明書が見つかりませんでした。
チームID "" に一致するプライベートキー付きの「iOS Development」署名証明書が見つかりませんでした。

理由:

  • iOS Distribution/iOS Development Certificate 証明書が不足しています

  • iOS Distribution/iOS Development Certificate の証明書はあるが、対応するプライベートキーがありません

解決策:

  • Keychain 内のすべての古い Certificates(証明書)および Profiles(プロビジョニングプロファイル)を削除する

  • 最初に証明書を作成したコンピュータのキーチェーンから該当の証明書を見つけ、.p12形式でエクスポートし、問題のあるコンピュータにインストールします。

  • Certificates, Identifiers & Profiles にアクセスし、古い証明書を取り消して再生成します
    (ご安心ください、オンライン版のアプリには影響せず、開発およびビルド段階のみ影響します)

プロビジョニングプロファイル “” に署名証明書 “Apple Development: XXX” が含まれていません。 / プロビジョニングプロファイル “” に署名証明書 “Apple Distribution: XXX” が含まれていません。:

理由:

  • 現在選択されているProvisioning Profileは、現在のCertificateと一致していません。

解決策:

  • Keychain 内のすべての古い Certificates(証明書)と Profiles(プロビジョニングプロファイル)を削除する

  • Certificates, Identifiers & Profiles の Profiles で、該当する証明書が選択されているか、またはプロファイルを再生成して使用してください。

チーム ‘’ に対応する ‘’ のプロファイルが見つかりませんでした: Xcodeは‘’に一致するプロビジョニングプロファイルを見つけられませんでした。:

理由:

  • 指定されたプロビジョニングプロファイルが見つかりません

解決策:

  • Keychain内のすべての古いCertificates(証明書)およびProfiles(プロビジョニングプロファイル)を削除する

  • Certificates, Identifiers & Profiles の Profiles から該当するプロファイルをダウンロードして使用する

プロビジョニングプロファイル “” のアプリID “” がバンドルID “” と一致しません。 / プロビジョニングプロファイルがバンドル識別子と一致しません:

理由:

  • Provisioning profile に現在の Bundle Identifier が含まれていません

解決策:

  • Keychain 内のすべての古い Certificates(証明書)と Profiles(プロビジョニングプロファイル)を削除する

  • Certificates, Identifiers & Profiles にアクセスし、IdentifiersでBundle Identifierが登録されていることを確認する

  • Certificates, Identifiers & Profiles の Profiles から対応するプロファイルをダウンロードして使用する

プロビジョニングプロファイル “” に現在選択されているデバイス “”(識別子 )が含まれていません。:

理由:

  • Provisioning profile に選択した実機の Device Identifier が含まれていません

解決策:

別の開発/配布証明書を作成できません。利用可能な開発/配布証明書の最大数に達しました。 :

理由:

作成された Development/Distribution Certificate が上限数に達しました。

解決策:

Xcodeの証明書は正しく正常にビルドできるが、CLI(Fastlane)でビルドコマンドを実行すると署名エラーが発生する:

理由:

ここでまた別の落とし穴にハマりました。自分のミスでプロジェクトをiCloud同期フォルダに置いたところ、なぜかFastlaneがずっと証明書の問題を起こしました(キー チェーンのアクセスに問題がある疑いです)。

解決策:

iCloud同期フォルダから移動するだけです。

日常使用の問題シーン

開発用証明書

  • Match を導入して証明書を一元管理する前は、各開発者が自分の Development CertificateDevelopment Profile を作成していました。組織内に1,000人以上の開発者がいる場合、Certificates, Identifiers & Profiles, Devices の管理画面は非常に混乱し、恐ろしい状態になります。

  • もし外部の開発チームが開発作業のみを担当する場合でも、そのチームをApple Developer Programの管理画面に追加し、彼ら自身の開発用証明書とプロファイルを作成させる必要があります。

配布用証明書

  • Distribution Certificate はチーム単位で作成されるため、各開発者プログラムのチームは限られた数の配布証明書しか作成できません。

  • 一般的な方法は、1人のエンジニアがDistribution Certificateを作成し、.p12ファイルをエクスポートして、他のリリース担当の開発者やCI/CDマシンで使用することです。

  • チームが大きく、アプリの数が多いと、やり取りが非常に面倒で、毎年必ず更新が必要です。

  • Ad Hocでパッケージングする際、新しいデバイスが登録されると、全員およびCI/CDは新しいデバイスを有効にするためにプロファイルを再ダウンロードする必要があります。

Fastlane Match

以上の問題を踏まえ、すべての証明書関連の管理を代行するプラットフォームを求めています。すべての開発者とCI/CDサービスはこのプラットフォームから統一してデータを取得・更新しなければなりません。このプラットフォームの保存は安全である必要があります。これが — Fastlane Match です。

チーム全体で証明書とプロファイルを簡単に同期

iOSおよびmacOSのコード署名に新しい方法:開発チーム全体で1つのコード署名IDを共有し、コード署名の設定を簡単にし、コード署名の問題を防ぎます。

matchは codesigning.guide のコンセプトを実装したものです。matchは必要なすべての証明書とプロビジョニングプロファイルを作成し、それらを別のGitリポジトリ、Google Cloud、またはAmazon S3に保存します。選択したストレージにアクセスできるチームメンバー全員が、これらの資格情報をコード署名に使用できます。matchは壊れた資格情報や期限切れの資格情報も自動的に修復します。チーム間で署名資格情報を共有する最も簡単な方法です

Fastlane Match:

  • App Store Connect と連携し(App Store Connect API または Apple Developer ログインセッションを通じて)、証明書を生成または更新します。

  • 証明書の成果物(.mobileprovision プロファイル、.p12 証明書、.cer 証明書)を暗号化して Git リポジトリにアップロードします(他のストレージも使用可能です)。
    .cer 証明書は独立して保存されます。これは証明書の有効性を確認するためです。

  • 権限を細かく分ける場合、Development証明書を管理するリポジトリとDistribution証明書を管理するリポジトリの2つに分けることができます。

フォルダ構成:

  • certsフォルダには、すべての証明書とそれに対応する秘密鍵が含まれています

  • profilesフォルダにはすべてのプロビジョニングプロファイルが含まれています

<https://docs.fastlane.tools/actions/match/>{:target="_blank"}

https://docs.fastlane.tools/actions/match/

暗号化アルゴリズム: AES-256-GCM

開発者、CI/CD サービス:

  • Fastlane match コマンドを使って証明書を一元管理します。

  • Fastlane Match はまず Git リポジトリから証明書ファイルを取得し、復号して使用します。期限切れや使用不可の場合、Create/Write 権限があれば自動で再生成しリポジトリにプッシュします。Read 権限のみの場合はエラーを報告します。

作成/書き込み:

  • 証明書の管理を担当する人だけが、証明書を生成・更新し、プッシュしてアップロードできます。

  • 重要な Distribution Certificate は別のリポジトリに保管し、CI/CD サービスや管理者のみが使用できるようにすることが望ましい

読む:

  • 他の開発者やCI/CDサービスは 読み取り専用 のPull証明書権限のみ持っています

  • CI/CDサービスは、タスクを実行するたびに最新の証明書を取得します

  • 全員が同じDevelopment & Distribution証明書を共有します

  • 人員異動後は Match Repo の権限を失うため、古い証明書を Revoke して再生成できます。あとは他のメンバーが再度 Pull すればよいです(make project スクリプトと統合していればさらに楽です)。

Fastlane Match の設定と使用

Git Storage を例にすると、すべての証明書。

1. 空の証明書保存用GitプライベートMatchリポジトリを作成する
すべてのCertificatesやProfilesは暗号化して保存されますが、そのリポジトリのアクセス権限は適切に設定する必要があります。

2.ローカルにGitのSSHアクセス権限が設定されていることを確認します。git clone [email protected]:xxx/certificates.git を使用して確認できます。

ここでは SSH Git Cloneリポジトリを統一して使用することを推奨します。なぜならCI/CDでも同じ方法を使うからです。

fastlane match を実行して If cloning the repo takes too long, you can use the clone_branch_directly option in match. でずっと止まる場合、多くは SSH 権限の問題です。

  1. プロジェクトディレクトリで bundle exec fastlane match init を実行して設定を完了する
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[21:54:32]: fastlane match は複数のストレージモードをサポートしています。使用したいものを選択してください:
1. git
2. google_cloud
3. s3
4. gitlab_secure_files
# git を使う場合は 1 を入力してください
?   1

[22:04:40]: 証明書とプロファイルを保存するための新しいプライベートgitリポジトリを作成してください
[22:04:40]: GitリポジトリのURL: git@github.com:xxx/certificates.git
# 作成したGitプライベートMatchリポジトリのSSH URLを入力してください

[22:04:47]: './fastlane/Matchfile' を正常に作成しました。コードエディタで開くことができます。
[22:04:47]: これで `fastlane match development`、`fastlane match adhoc`、`fastlane match enterprise`、`fastlane match appstore` を実行できます
[22:04:47]: 各環境で初めて実行すると、プロビジョニングプロファイルと
[22:04:47]: 証明書を作成します。それ以降は既存のプロファイルを自動でインポートします。
[22:04:47]: 詳細は https://docs.fastlane.tools/actions/match/ をご覧ください
  1. 完了すると fastlane/Matchfile : が生成されます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# あなたのGitプライベートMatchリポジトリのSSH URL
git_url("[email protected]:xxxx/certificates.git")

storage_mode("git")

type("development") # デフォルトのタイプ。appstore、adhoc、enterprise、developmentが指定可能

# app_identifier(["tools.fastlane.app", "tools.fastlane.app2"])
# username("[email protected]") # Apple Developer Portalのユーザー名

# 利用可能なオプションは `fastlane match --help` で確認できます
# 他のオプションを有効にするには行頭の#を外してください

# ドキュメントは https://docs.fastlane.tools/actions/match にあります

5. App Store Connect API .p8 Key を生成し、APIキーで証明書を一元管理する:

⚠️️️️ App Store Connect API .p8 Key の権限は非常に強力 であり、証明書の管理だけでなく、アプリのリリースや審査申請、さらにはバックエンドのユーザー管理、レビュー、財務レポートの操作も可能です。

チームの状況に応じて、チームの .git に入れて全員がアクセスできるようにするかどうかを決めてください。

より高度なリスク管理方法は、管理者のみが操作し、暗号化してCI/CDで使用することです(本文後半で紹介します)。

ここではデモのためにfastlaneディレクトリ内に直接配置しています。

また、本記事のFastlaneスクリプトは、表示を簡潔にするために、コードの重複や構造は考慮していません。

証明書管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
platform :ios do
  lane :match_development do \\|options\\|
    # あなたのApp Identifier IDに変更してください
    app_identifier = "li.zhgchg.myApp"

    type = options.fetch(:type, "development")
    isRead = options.fetch(:isRead, true)
    if isRead 
      readonly = true
      force = false
    else
      readonly = false
      force = true

      # Appleの管理画面で証明書を管理する権限を持つためにApp Store Connect APIキーが必要です
      # App Store Connect APIの.p8キーは./fastlane/フォルダ内にあると仮定しています
      app_store_connect_api_key(
        key_id: "XXXXXX",
        issuer_id: "XXXXXX-XXXXXX-XXXXXX-XXXXXX-XXXXXX",
        key_filepath: "./fastlane/AuthKey_XXXXXX.p8",
      )
    end

    # app_identifierのDevelopment証明書を取得します
    match(
      type: type,
      app_identifier: app_identifier, 
      readonly: readonly, # 必要に応じてcert / profileを更新・アップロードできるかどうか
      force: force # プロビジョニングプロファイルを無条件に再作成するかどうか
    )
  end
end

Development Certificate と Profile を作成し、Match Repo にアップロードする:

1
bundle exec fastlane match_development type:development isRead:false
  • エラーがなければ、Development Certificate と Profile の作成、インストールが成功し、Match リポジトリへのプッシュと同期も成功したことを意味します。

初回作成時に Passphrase の設定が必要です:

1
2
3
4
[23:29:12]: 証明書の暗号化/復号に使用するパスフレーズを入力してください
[23:29:12]: このパスフレーズはリポジトリごとに固有で、ローカルキーチェーンに保存されます
[23:29:12]: 別のマシンでmatchを実行する際に必要になるため、パスワードを忘れないようにしてください
[23:29:12]: Matchストレージのパスフレーズ:
  • この値は、あなたのすべてのMatchリポジトリ上のファイルを暗号化するために必要な参照(パスフレーズ+ランダムソルト)です。

  • ランダム文字列 を生成して設定し、記録しておくことをおすすめします。

  • 今後の更新や他の人がMatchリポジトリの証明書を取得する際には、この文字列を入力して元のファイルを復号化する必要があります。

チームの他のメンバーは統一して Match Repo から Development Certificate と Profile を Pull します:

1
bundle exec fastlane match_development type:development

初めて使用する際にログインパスワード(login keychain)を尋ねられます。これは証明書をkeychainにインストールするためで、2回入力して確認してください:

1
2
3
4
5
6
7
8
9
10
[16:52:59]: 証明書をインストールしています...
[16:53:00]: ローカルのコード署名IDが見つかりません。
security find-identity -v -p codesigning を実行するとこの出力が得られます。
このStack Overflowのスレッドに詳細があります: https://stackoverflow.com/q/35390072/774。
(Keychain Accessで期限切れのWWDR証明書を確認してください: https://stackoverflow.com/a/35409835/774 に詳細があります。)
[16:53:00]: /Users/zhgchgli/Library/Keychains/login.keychain-db のパスワードを入力してください
[16:53:00]: このパスフレーズは fastlane_keychain_login という名前でローカルキーチェーンに保存され、今後の実行で使用されます
[16:53:00]: このプロンプトは 'keychain_password' オプションまたは 'MATCH_KEYCHAIN_PASSWORD' 環境変数を指定することで回避できます
[16:53:00]: ログインキーチェーンのパスワード: ********
[16:53:24]: ログインキーチェーンのパスワードを再度入力してください: ********

もしMatch Developmentで証明書を取得した後にXcodeがエラーや無効と表示し続ける場合:

前述のよくあるエラーを参考にすると、多くは古い不要な証明書が原因です。すべての証明書を削除してから再取得すれば、問題は解決するはずです。

AdHoc配布用の証明書とプロファイルを作成し、Matchリポジトリにアップロードする:

1
bundle exec fastlane match_development type:adhoc isRead:false

AppStore Distribution Certificate と Profile を作成し、Match リポジトリにアップロードする:

1
bundle exec fastlane match_development type:appstore isRead:false

CI/CDサービスは一元的にMatchリポジトリからDistribution Certificate & Profile(isRead:true)をPullし、その後ビルドとリリースのタスクを実行します。

新しいデバイスの登録

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
platform :ios do  
  desc "新しいデバイスを登録してプロファイルを更新する"
  lane :registerDevice do \\|options\\|
    # あなたのApp Identifier IDに変更してください
    app_identifier = "li.zhgchg.myApp"

    # Appleのバックエンドで証明書を管理するにはApp Store Connect API Keyが必要です
    # App Store Connect APIの.p8キーが./fastlane/ディレクトリ内にあると仮定
    app_store_connect_api_key(
      key_id: "XXXXXX",
      issuer_id: "XXXXXX-XXXXXX-XXXXXX-XXXXXX-XXXXXX",
      key_filepath: "./fastlane/AuthKey_XXXXXX.p8",
    )
    # 入力: UDIDとデバイス名
    udid = options[:udid] \\|\\| UI.input("デバイスのUDIDを入力してください:")
    device_name = options[:name] \\|\\| UI.input("デバイス名を入力してください:")
    UI.message("📱 デバイスを登録中 #{device_name} (#{udid})")
    register_device(
      name: device_name,
      udid: udid,
      platform: 'ios'
    )

    # app_identifierのDevelopment証明書を更新
    match(
      type: "development",
      app_identifier: app_identifier, 
      readonly: false, # 必要に応じてcert / profileを更新・アップロード
      force_for_new_devices: true # 新しいデバイスの場合はprovisioning profileを再作成
    )

    # app_identifierのAdHoc証明書を更新
    match(
      type: "adhoc",
      app_identifier: app_identifier, 
      readonly: false, # 必要に応じてcert / profileを更新・アップロード
      force_for_new_devices: true # 新しいデバイスの場合はprovisioning profileを再作成
    )
  end
end

登録が完了した後、他の開発者やCI/CDサービスがMatchリポジトリからProfile(DevelopmentまたはAdHoc)を取得すると、新しいデバイスが含まれます。

Fastlane Match x CI/CD ワークフロー統合

Fastlane MatchでPush/Pullの証明書を生成した大まかな説明の後、次にCI/CDプロセスへの統合方法について説明します。

問題1 — Private Match RepoをどうやってCloneするか

最もよくある問題の一つは、CI/CDでPrivate Match RepoプロジェクトをどうやってCloneするかです。ローカル開発では統一してssh git cloneを使い、自分のアカウントのsshキーを使っているため問題は起きません。しかし、CI/CDにはこのキーがないため、個人のキーを使うこともできますが、安全とは言えません。

GitHub — リポジトリデプロイキー:

1.まずローカルでプライベートキーとパブリックキーを生成します:ssh-keygen -t rsa -b 4096 -f ./id_rsaパスフレーズは入力しないでください

  1. Match Private Repo -> Settings -> Security -> Deploy keys -> Add deploy key に移動:

  1. テキストエディタで「 id_rsa.pub 」を開き、内容をコピーして Key ->「Add key」に貼り付ける

  1. メインのリポジトリに戻り、Settings → Security → Secrets and variables に移動します。

  1. SSHプライベートキーの内容をSecretに追加:

  • 名前: MATCH_REPO_DEPLOY_PRIVATE_KEY
  1. メインリポジトリの GitHub Actions に SSH キーを設定する:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
name: CI - Deploy

on:
  push:
    branches: [ main ]
  pull_request:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: 現在のリポジトリをチェックアウト (Repo A)
        uses: actions/checkout@v4

      - name: デプロイキー用SSH設定
        run: \\|
          mkdir -p ~/.ssh
          echo "${{ secrets.MATCH_REPO_DEPLOY_PRIVATE_KEY }}" > ~/.ssh/id_ed25519
          chmod 600 ~/.ssh/id_ed25519
          ssh-keyscan github.com >> ~/.ssh/known_hosts

      - name: クローンテスト
        run: \\|
          git clone [email protected]:xxxx/match-certificates.git
# 成功!
# .. デプロイジョブを実行...
  1. 設定成功!

問題2— App Store Connect API .p8キーの安全な保管と使用

GitHub Actions はファイルを直接保存できないため、まず文字列として保存し、その後ファイルに書き込みます。

  1. 同じ問題1の手順で、メインのリポジトリに APP_STORE_CONNECT_API_KEY_CONTENT シークレットを追加します。

  2. テキストエディタで AuthKey_XXXXXX.p8 を開き、内容をコピーして貼り付けてください。

  3. メインリポジトリのGitHub Actionsに内容を読み取りファイルに書き込むステップを追加:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
name: CI - Deploy
on:
  push:
    branches: [ main ]
  pull_request:
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: 現在のリポジトリをチェックアウト (リポジトリA)
        uses: actions/checkout@v4

      - name: デプロイキー用のSSHを設定
        run: \\|
          mkdir -p ~/.ssh
          echo "${{ secrets.MATCH_REPO_DEPLOY_PRIVATE_KEY }}" > ~/.ssh/id_ed25519
          chmod 600 ~/.ssh/id_ed25519
          ssh-keyscan github.com >> ~/.ssh/known_hosts  
      
      - name: シークレットキーをファイルに書き込み
        env:
          APP_STORE_CONNECT_API_KEY_CONTENT: ${{ secrets.APP_STORE_CONNECT_API_KEY_CONTENT }}
        run: \\|
          # fastlaneディレクトリが存在することを確認
          mkdir -p ./fastlane
      
          # ファイルパスを作成
          APP_STORE_CONNECT_API_KEY_PATH=./fastlane/AuthKey_XXXXXX.p8
      
          # ファイルに内容を書き込み(改行を保持)
          echo "$APP_STORE_CONNECT_API_KEY_CONTENT" > "$APP_STORE_CONNECT_API_KEY_PATH"
      
          # (任意)権限を制限
          chmod 600 "$APP_STORE_CONNECT_API_KEY_PATH"

      - name: Firebaseへデプロイ
        env:
          MATCH_PASSWORD: "${{ secrets.MATCH_PASSWORD }}"
        run: bundle exec fastlane deploy_to_firebase

問題3 — Private Match Repo のパスフレーズ設定で、Match 実行時のプロンプト中断を防止

  1. 同じ問題 1 の手順で、メインのリポジトリに MATCH_PASSWORD をシークレットとして追加する

  2. 内容を入力して、設定した Fastlane Match リポジトリの Passphrase を入力してください

  3. メインリポジトリの GitHub Actions に env: secret.MATCH_PASSWORD を追加:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
name: CI - Deploy
on:
  push:
    branches: [ main ]
  pull_request:
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: 現在のリポジトリをチェックアウト (Repo A)
        uses: actions/checkout@v4

      - name: デプロイキー用のSSH設定
        run: \\|
          mkdir -p ~/.ssh
          echo "${{ secrets.MATCH_REPO_DEPLOY_PRIVATE_KEY }}" > ~/.ssh/id_ed25519
          chmod 600 ~/.ssh/id_ed25519
          ssh-keyscan github.com >> ~/.ssh/known_hosts  
      
      - name: シークレットキーをファイルに書き込む
        env:
          APP_STORE_CONNECT_API_KEY_CONTENT: ${{ secrets.APP_STORE_CONNECT_API_KEY_CONTENT }}
        run: \\|
          # fastlaneディレクトリが存在することを確認
          mkdir -p ./fastlane
      
          # ファイルパスを作成
          APP_STORE_CONNECT_API_KEY_PATH=./fastlane/AuthKey_XXXXXX.p8
      
          # 内容を書き込み(改行を保持)
          echo "$APP_STORE_CONNECT_API_KEY_CONTENT" > "$APP_STORE_CONNECT_API_KEY_PATH"
      
          # (任意)権限を制限
          chmod 600 "$APP_STORE_CONNECT_API_KEY_PATH"

      - name: Firebaseへデプロイ
        env:
          MATCH_PASSWORD: "${{ secrets.MATCH_PASSWORD }}"
        run: bundle exec fastlane deploy_to_firebase

問題4 — Self-hosted Runner 上の Keychain 処理

クラウドのマシンは毎回クリーンで新しい環境ですが、Self-hosted Runnerを使う場合は、Fastlaneで derived_data_pathoutput_directorybuildlog_pathreinstall_app を指定して毎回クリーンな環境を作れます。しかし、CertificatesやProfilesはシステムのKeychainにインストールされるため、どう対処すればよいでしょうか?

実は Fastlane は私たちのために、Match の前にクリーンな Keychain を作成することも考慮しています:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
name: CI - デプロイ
on:
  push:
    branches: [ main ]
  pull_request:
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: 現在のリポジトリをチェックアウト (Repo A)
        uses: actions/checkout@v4

      - name: デプロイキー用SSH設定
        run: \\|
          mkdir -p ~/.ssh
          echo "${{ secrets.MATCH_REPO_DEPLOY_PRIVATE_KEY }}" > ~/.ssh/id_ed25519
          chmod 600 ~/.ssh/id_ed25519
          ssh-keyscan github.com >> ~/.ssh/known_hosts  
      
      - name: シークレットキーをファイルに書き込み
        env:
          APP_STORE_CONNECT_API_KEY_CONTENT: ${{ secrets.APP_STORE_CONNECT_API_KEY_CONTENT }}
        run: \\|
          # fastlaneディレクトリが存在することを確認
          mkdir -p ./fastlane
      
          # ファイルパスを作成
          APP_STORE_CONNECT_API_KEY_PATH=./fastlane/AuthKey_XXXXXX.p8
      
          # 内容を書き込み(改行を保持)
          echo "$APP_STORE_CONNECT_API_KEY_CONTENT" > "$APP_STORE_CONNECT_API_KEY_PATH"
      
          # (任意)権限を制限
          chmod 600 "$APP_STORE_CONNECT_API_KEY_PATH"

      - name: fastlaneキーチェーンを作成
        env:
          KEYCHAIN_NAME: "${{ runner.name }}"
          MATCH_PASSWORD: "${{ secrets.MATCH_PASSWORD }}"
        run: \\|
          bundle exec fastlane run create_keychain \
            name:"$KEYCHAIN_NAME" \
            password:"$MATCH_PASSWORD" \
            unlock:true \
            timeout:0 \
            lock_when_sleeps:false
      
      - name: Firebaseへデプロイ
        env:
          MATCH_PASSWORD: "${{ secrets.MATCH_PASSWORD }}"
          KEYCHAIN_NAME: "${{ runner.name }}"
        run: bundle exec fastlane deploy_to_firebase

      # 🔥 成功・失敗に関わらず必ず実行
      - name: fastlaneキーチェーンを削除
        if: always()
        env:
          KEYCHAIN_NAME: ${{ runner.name }}
        run: \\|
          bundle exec fastlane run delete_keychain \
            name:"$KEYCHAIN_NAME"
  • 各Runnerは同時に一つだけ実行されるため、Runner名をKeychain名として使用し、各Runnerは自分専用のKeychainを持ちます。

  • 実行完了後、成功・失敗に関わらず削除されます。

  • keychain_password は特に別途設定せず、統一して MATCH_PASSWORD を使用しました。

Fastlane/Fastfile 内の match メソッドに keychain パラメータを追加する:

1
2
3
4
5
6
7
8
9
10
#...
    match(
      type: "adhoc",
      app_identifier: app_identifier, 
      readonly: false, # 必要に応じてcert / profileを更新・アップロード
      force_for_new_devices: true, # 新しいデバイスがあればprovisioning profileを再作成
      keychain_name: ENV['KEYCHAIN_NAME'], # デフォルト値: nil
      keychain_password: ENV['MATCH_PASSWORD'] # デフォルト値: nil
    )
#...

こうすることで、Matchが証明書を取得する際に、共有のloginキーチェーンではなく指定したキーチェーンに保存されます。

結語

Fastlaneの記事は範囲が広すぎるため、ここではFastlane Matchの使用過程のみを記録します。テスト実行やビルド・リリースなどの他のLaneについては、機会があれば別の記事で補足します。Matchに関する他の問題や事例があれば、また追記しますので、コメントでの質問も歓迎します!

関連記事

どうぞご覧ください。🤞🏻

ご質問やご意見がございましたら、こちらからご連絡ください

Post MediumからZMediumToMarkdownによって変換されました。


🍺 Buy me a beer on PayPal

👉👉👉 Follow Me On Medium! (1,053+ Followers) 👈👈👈

本記事は Medium にて初公開されました(こちらからオリジナル版を確認)。ZMediumToMarkdown による自動変換・同期技術を使用しています。

Improve this page on Github.

本記事は著者により CC BY 4.0 に基づき公開されています。