
STORES ブランドアプリチームで iOS エンジニアをしている榎本 ( @enomot_ ) です。
以前、「fastlane match の内部実装を活用して複数の iOS 開発者証明書の期限を一括チェックする方法」という記事で、暗号化された証明書ファイルから有効期限を取得する方法を紹介しました。この方法により、fastlane match で管理している証明書の期限をプログラムで確認できるようになりました。
本記事では、前回紹介した証明書の期限取得の仕組みを発展させ、 fastlane match の GitHub リポジトリを、開くだけで証明書の状態が分かるダッシュボードとして運用する事例を紹介します。
前回の記事で残った課題
前回の記事では、fastlane のカスタムアクションを使って暗号化された証明書から有効期限を取得する方法を実装しました。これにより、証明書の期限を確認する技術的な基盤はできましたが、実運用を続けていくなかで使いづらい部分がわかってきました。
コマンドを実行すると、証明書の情報がターミナルに出力されます。しかし、数十のアカウントの証明書を管理している状況では、ターミナル出力ではやや可読性が低く、「今すぐ対応が必要な証明書はどれか」を一目で把握するのが困難でした。また、毎回コマンドを実行しなければ最新の状態を確認できず、チーム全体で情報を共有するにはあまり使い勝手の良いものではありませんでした。
この課題を解決するため、README.md によるダッシュボード化と、GitHub Actions による自動更新の2つのアプローチで改善を図りました。
解決策:README.md によるダッシュボード化
fastlane match のリポジトリは、すでにチーム全体で共有されています。このリポジトリの README.md を証明書ステータスのダッシュボードとして機能させれば、新しいツールやインフラを追加することなく、リポジトリを開くだけで証明書の状態を確認できるようになります。
実装の方針
これまで fastlane はアプリ側のリポジトリで実行していましたが、今回は証明書管理用リポジトリ自体に fastlane をセットアップし、証明書の確認と README.md の生成をこのリポジトリで完結させるようにしました。
- 証明書リポジトリに fastlane をセットアップ:Gemfile と Fastfile を追加し、証明書リポジトリで直接 fastlane を実行できるようにする
- 証明書・プロファイル情報を取得:前回実装した Distribution 証明書に加え、Provisioning Profile の有効期限も取得する
- Markdown テーブルの整形と README.md の出力:取得した情報を見やすいテーブル形式に変換し、README.md を自動生成する
- GitHub Actions で定期実行:週次で自動実行し、手動操作を不要に
なお、Provisioning Profile の復号化も、Distribution 証明書と同じく Match::Encryption::MatchFileEncryption を使用することで実現できます。暗号化の仕組みは共通しているため、同じアプローチで両方の有効期限を取得できます。
README.md 生成の実装
前回の記事 で実装した証明書取得の仕組みを活用し、取得した情報を Markdown テーブルとして README.md に出力する実装を行いました。
# fastlane/Fastfile lane :check_certificates do # 証明書とプロビジョニングプロファイルの情報を取得 profiles = check_profiles(password: ENV['MATCH_PASSWORD'], types: ['appstore']) certificates = check_certs(password: ENV['MATCH_PASSWORD'], types: ['distribution']) # README.md を生成 generate_readme(profiles: profiles, certificates: certificates) end
生成される README.md は、以下のような Markdown テーブル形式になります(ダミーデータを用いています)
# iOS Certificates & Provisioning Profiles Status Last updated: 2025-01-16 09:00:00 JST ## Provisioning Profiles: App Store | Branch | Team Name | App ID | Profile Name | Expiration Date | Status | |--------|-----------|--------|--------------|-----------------|--------| | brand-a | Example Brand A Inc. | ABC123XYZ.com.example.brand-a | match AppStore com.example.brand-a | 2026-08-27 | ✅ Valid | | brand-b | Sample Company B Ltd. | DEF456UVW.com.sample.brand-b | match AppStore com.sample.brand-b | 2026-01-10 | ⚠️ Expiring Soon | | brand-c | Demo Corporation C | GHI789RST.com.demo.brand-c | match AppStore com.demo.brand-c | 2025-06-13 | ❌ Expired | ... ## Certificates: Distribution | Branch | Common Name | Expiration Date | Status | |--------|-------------|-----------------|--------| | brand-a | Apple Distribution: Example Brand A Inc. (ABC123XYZ) | 2026-08-27 | ✅ Valid | | brand-b | Apple Distribution: Sample Company B Ltd. (DEF456UVW) | 2026-01-10 | ⚠️ Expiring Soon | | brand-c | Apple Distribution: Demo Corporation C (GHI789RST) | 2025-06-13 | ❌ Expired | ...
この実装により、証明書の取得ロジックと、ダッシュボードとしての表示ロジックが分離され、それぞれ独立してメンテナンスできるようになっています。 また証明書の期限までの日数に応じて、アイコンを自動的に表示するようにしました。これにより、リポジトリを開いたら注意が必要な証明書を即座に識別できるようになりました。
GitHub Actions による自動更新
README.md の自動生成ができても、手動で実行する必要があれば、前回の課題は完全には解決できません。そこで、GitHub Actions で定期的に証明書の状態をチェックし、README.md を自動更新する仕組みを構築しました。
証明書の有効期限は年単位であるため、毎週月曜日の朝(JST 9:00)に自動実行するように設定しています。これにより、週の初めに最新の状態を確認でき、手動での確認作業が不要になりました。復号化に必要な MATCH_PASSWORD は GitHub Secrets で安全に管理し、ワークフロー実行時のみアクセス可能にしています。
結果:リポジトリがダッシュボードに
実装完了後、fastlane match のリポジトリを開くと、以下のような証明書ステータステーブルが表示されるようになりました。

得られた効果
ゼロクリックでの状態確認
リポジトリを開くだけで、全ての証明書の状態が一目で把握できるようになりました。コマンドを実行する必要がなくなり、確認のハードルが大幅に下がりました。
自動更新による鮮度の維持
GitHub Actions による週次の自動実行により、情報の鮮度が常に保たれます。最終更新日付を気にする必要がなくなりました。
追加インフラ不要
専用の Web アプリケーションやダッシュボードサービスを導入せずに、既存の fastlane match リポジトリだけで完結しています。運用コストやメンテナンスコストが最小限に抑えられています。
まとめ
前回の記事で実装した証明書取得の仕組みを発展させ、fastlane match リポジトリを証明書ダッシュボードとして機能させる仕組みを紹介しました。 複数の Apple Developer Program アカウントを管理する必要がある組織では、同じような運用で悩んでいる方もいらっしゃるかもしれません。本記事が少しでも参考になれば幸いです。