Claude CodeでFastlaneのリリースを自動化 — uploadはaskで止める
Fastfileの作成をClaude Codeに任せつつ、TestFlightやApp Storeへ送るlaneは権限ルールで確認を挟む。検証用laneとFastfile編集の守り方まで書きます。
Fastlaneの公開系アクションは、lane名で確認を挟む
Fastlaneは、ビルド、署名、TestFlight配信、App Storeへの提出といった手作業を、Fastfileに書いたlane(一連の処理に付けた名前)として自動化するツールです。Claude Codeに任せるなら、Fastfileを書かせてビルドまでを自走させる使い方が向いています。一方で、App Store ConnectやGoogle Playへ送るアクションは、実行した時点で外部に残ります。
整える方針は3つです。
- ビルドと検証だけのlaneは、確認なしで走らせる
- アップロードするlaneは、
askルールで毎回確認を挟む - 審査提出まで進むlaneは、Claude Codeからは実行させない
ここで押さえたい点があります。Claude Codeの権限ルールが見るのは、Claudeが書いたシェルのコマンド文字列です。upload_to_app_storeがFastfileの中で呼ばれていても、ルールにはlane名しか見えません。つまり、止める単位はアクションではなくlaneです。この前提で、lane設計、権限設定、Fastfile自体の守り方を順に組みます。
iOSアプリ自体の作り方はClaude CodeでSwiftUI iOSアプリを開発する手順にあります。ここでは、アプリが手元でビルドできる状態から、リリース工程だけを扱います。
どのアクションが外部に書き込むのか
Fastlaneのアクション一覧は、カテゴリ別に分かれています。リリース関連の「Releasing your app」には、deliver(upload_to_app_storeの別名)、supply(upload_to_play_storeの別名)、upload_to_app_store、upload_to_play_store、upload_app_privacy_details_to_app_storeなどが並びます。TestFlightに送るpilotは、Betaカテゴリでupload_to_testflightの別名として載っています。
確認を挟む対象を決めるため、外へ書き込む側と読むだけの側に分けておきます。
| 分類 | アクション | 外部への影響 |
|---|---|---|
| 読むだけ | アクションapp_store_build_number、latest_testflight_build_number | 外部への影響App Store Connectの現在値を取得する |
| ローカルのみ | アクションbuild_app(ipaを作る) | 外部への影響手元にipaができる |
| 書き込む | アクションupload_to_testflight(pilot) | 外部への影響ビルドをTestFlightへ送る |
| 書き込む | アクションupload_to_app_store(deliver) | 外部への影響メタデータ・スクリーンショット・バイナリを送る |
| 書き込む | アクションupload_to_play_store(supply) | 外部への影響Google Playへメタデータやバイナリを送る |
| 書き込む | アクションupload_app_privacy_details_to_app_store | 外部への影響App Privacy Detailsを送る |
注意したいのはdeliverです。ipaを指定しない場合は、アプリのメタデータだけがアップロードされます。バイナリを送らない実行でも、ストア上の説明文やスクリーンショットは書き換わります。「ipaを送らないから安全」とは言えません。
権限ルールはlane名しか見ない
Claude Codeの権限ルールは、deny、ask、allowの順に評価され、最初に一致したものが結果を決めます。広いdenyの中に狭いallowで例外を作ることはできません。askとallowの関係も同じで、askに一致する呼び出しは、より細かいallowがあっても確認が出ます。
これを使うと、lane名ごとに3段階の運用を置けます。次の例は、後述のlane名に合わせた.claude/settings.jsonの断片です。
{
"permissions": {
"allow": [
"Bash(bundle exec fastlane build_only *)",
"Bash(bundle exec fastlane verify *)",
"Bash(bundle exec fastlane actions)",
"Bash(bundle exec fastlane action *)"
],
"ask": [
"Bash(bundle exec fastlane beta *)",
"Bash(bundle exec fastlane release *)",
"Bash(bundle exec fastlane deliver *)",
"Bash(bundle exec fastlane pilot *)",
"Bash(bundle exec fastlane supply *)",
"Edit(fastlane/**)"
],
"deny": [
"Bash(bundle exec fastlane submit_review *)",
"Read(**/*.p8)"
]
}
}書き方で気をつける点が3つあります。
- 末尾の
*の前にスペースを置く:Bash(... build_only *)は引数なしのbuild_onlyにも一致します。スペースがない書き方だと、別名のlaneにも一致してしまいます。 bundle execは自動で外れない: Claude Codeが実行前に取り除くラッパーはtimeout、time、nice、nohup、stdbufなどの固定の一覧で、bundle execは含まれていません。プロジェクトで使う呼び方に合わせて書き、同じ形で実行するようCLAUDE.mdにも書いておきます。- 直接呼びも塞ぐ: lane名だけ押さえても、
fastlane deliverやfastlane pilotを直接呼べば同じ書き込みができます。そのためaskに直接呼びの形も入れています。
Claudeに渡す検証用laneを先に作る
確認を挟むだけでは、実行する側の判断材料が足りません。「送る前に何が起きるか」を安全に見られるlaneを別に用意すると、askの承認が形式で終わりません。
Fastfileの例を示します。オプション名はFastlaneのアクション解説に載っているものを使った形で、アプリ名、スキーム名、環境変数名は仮のものです。
default_platform(:ios)
platform :ios do
lane :build_only do
build_app(
scheme: "MyApp",
export_method: "app-store",
output_directory: "./build"
)
end
lane :verify do
build_app(scheme: "MyApp", export_method: "app-store",
output_directory: "./build")
app_store_connect_api_key(
key_id: ENV["ASC_KEY_ID"],
issuer_id: ENV["ASC_ISSUER_ID"],
key_filepath: ENV["ASC_KEY_PATH"]
)
deliver(verify_only: true)
end
lane :beta do
build_app(scheme: "MyApp", export_method: "app-store",
output_directory: "./build")
app_store_connect_api_key(
key_id: ENV["ASC_KEY_ID"],
issuer_id: ENV["ASC_ISSUER_ID"],
key_filepath: ENV["ASC_KEY_PATH"]
)
upload_to_testflight(
changelog: "検証用ビルド",
skip_submission: true
)
end
lane :release do
build_app(scheme: "MyApp", export_method: "app-store",
output_directory: "./build")
app_store_connect_api_key(
key_id: ENV["ASC_KEY_ID"],
issuer_id: ENV["ASC_ISSUER_ID"],
key_filepath: ENV["ASC_KEY_PATH"]
)
deliver(
submit_for_review: false,
automatic_release: false
)
end
end各lane、各オプションの役割は次のとおりです。
build_only: ipaを作るだけで、外には何も送りません。allowに置けます。verify:deliverのverify_onlyは、アーカイブをApp Store Connectで検証し、アップロードはしないオプションです。バイナリが受理される形かを、送る前に確かめるために使います。beta:skip_submission: trueは、ipaをアップロードするだけでテスターへの配布はしないオプションです。ビルド処理待ちを飛ばすskip_waiting_for_build_processingは、trueにするとdistribute_externalが効かなくなり、テスターへの配布もされません。CIの課金時間を抑える用途のオプションなので、ここでは使いません。release:submit_for_reviewの既定値はfalse、automatic_releaseは「承認されたら全ユーザーに自動公開するか」の指定です。両方を明示的にfalseにしておけば、このlaneはアップロードまでで止まります。
deliverのforceはtrueにしません。forceを指定すると、アップロード前のHTMLレポートが作られなくなります。レポートが作られる状態のままにしておけば、送る内容を目で見られます。
審査提出は人が打つlaneに分ける
既にApp Store Connectにあるビルドを審査に出す処理は、deliverのbuild_number、submit_for_review: true、skip_binary_upload: trueなどを組み合わせたlaneとして書けます。コマンドならfastlane deliver submit_build --build_number 830の形です。
このlaneはsubmit_reviewという名前でFastfileに置き、前節のdenyに入れました。Claude Codeには「審査提出の直前まで」を任せ、最後の1回は自分の端末で打ちます。
lane :submit_review do
deliver(
submit_for_review: true,
automatic_release: false,
skip_metadata: true,
skip_screenshots: true,
skip_binary_upload: true
)
endbuild_numberを省くと、編集中のバージョンについて最新のビルド番号が自動で選ばれます。意図したビルドかどうかは、app_store_build_numberやlatest_testflight_build_numberで現在値を見てから提出します。
認証キーをClaudeに読ませない
Fastlaneの認証は、App Store Connect APIキーが推奨されています。2FA(二段階認証)が要らない点と、性能・信頼性の向上が利点に挙げられています。従来のApple ID認証は、クッキー方式のWebセッションを使います。app_store_connect_api_keyアクションに、キーID、発行者ID、.p8ファイルのパスを渡す形が基本になります。
キーの渡し方で、Claude Codeの運用に直結する点が2つあります。
- キーの値は環境変数に置き、
Fastfileには変数名だけを書きます。FastfileをClaudeが編集・表示してもキー本体は出ません。 .p8ファイルは、Read(**/*.p8)のdenyで読み取りを止めます。Readのdenyは、.envのようなファイル名のパターンでも書けます。
.p8は認証に使う秘密鍵です。リポジトリには入れず、.gitignoreにも載せておきます。
Fastfileそのものをaskで守る
ここが最大の穴です。lane名で権限を分けても、ClaudeがFastfileのbuild_onlyの中にupload_to_app_storeを足せば、allowのlaneが外部に書き込めます。またreleaseのsubmit_for_review: falseをtrueに直せば、askの承認を通った1回で審査提出まで進みます。
Edit(fastlane/**)をaskに入れたのは、このためです。Fastfile、Appfile、Deliverfileへの変更は毎回差分が見えます。承認画面で見るのは次の3点です。
build_onlyとverifyに、upload_*やdeliverの呼び出しが増えていないかsubmit_for_review、automatic_release、forceの値が変わっていないかskip_*系のオプションで、意図しない範囲の書き込みが生まれていないか
より確実にしたい場合は、PreToolUseフックでFastfileの変更内容を検査する方法があります。終了コード2で終わるフックは、権限ルールの評価より前にツール呼び出しを止めます。たとえば編集後のFastfileにsubmit_for_review: trueが含まれていたら拒否する、といった判定です。フックの考え方は、実行後に走るPostToolUse hookでの後処理と同じ仕組みで、実行前に挟む点が異なります。
ルールが止められないもの
権限ルールは、Claudeが書いたコマンドの文字列に一致する範囲しか止められません。Bash(git push *)のdenyがgit -C . pushを止めないのと同じで、/usr/local/bin/fastlaneのようなパス指定やsh -c経由の実行には別の対処が要ります。権限ルールの限界として、ドキュメントにも「セキュリティ境界ではない」旨が書かれています。
そのため、次の層を組み合わせます。
| 層 | 止めるもの | 向いている使い方 |
|---|---|---|
| 権限ルール(ask・deny) | 止めるもの通常の呼び方のlane実行 | 向いている使い方日常の確認とログ |
| PreToolUseフック | 止めるものコマンド全文とFastfileの中身 | 向いている使い方抜け道になる書き方の検査 |
| サンドボックス | 止めるものファイルとネットワーク | 向いている使い方外部通信そのものの制限 |
| CLAUDE.md | 止めるものClaudeの手順の選び方 | 向いている使い方呼び方の統一(強制力はない) |
CLAUDE.mdは強制力を持たないので、守らせたい制約の本体にはしません。呼び方の統一と、確認の手順を書く場所と割り切ります。
CLAUDE.mdに書く規約の断片
Claudeがlaneを選ぶ手がかりとして、次のような記述を置けます。
## リリース手順(Fastlane)
- 実行は必ず `bundle exec fastlane <lane>` の形にする
- 変更後はまず `build_only` と `verify` を実行し、結果を報告する
- `beta` と `release` は承認を得てから実行する。送信先と内容を事前に説明する
- `submit_review` は実行しない。必要なときは実行コマンドを提示して止まる
- Fastfile の変更では、upload 系アクションと submit_for_review の値を差分で示す
- APIキー(.p8)は読まない。キーは環境変数 ASC_KEY_ID / ASC_ISSUER_ID / ASC_KEY_PATH で渡される実際に回す順序
初回は次の順序で進めると、どこで確認が入るかが体感できます。
Fastlaneのリリース工程を回す順序
- 1
Fastfileを書かせる
build_only、verify、beta、release、submit_reviewの5つのlaneを作らせます。upload系はFastlaneのアクション名の一覧で確認させます。 - 2
allowのlaneで動作を確かめる
build_onlyでipaを作り、verifyでApp Store Connectでの検証だけを通します。承認は求められません。 - 3
askのlaneで確認を受ける
betaを実行させると、権限プロンプトが出ます。lane名と、これから外へ送るものを見て承認します。 - 4
提出は自分で打つ
submit_reviewは自分の端末で実行します。直前にapp_store_build_numberなどで対象のビルド番号を見ます。
Fastlaneで使えるアクションの名前とオプションは、fastlane actionsで一覧を、fastlane action アクション名で個別の説明を出せます。
bundle exec fastlane actions
bundle exec fastlane action upload_to_testflightどちらも読むだけのコマンドです。Bash(bundle exec fastlane action *)はactionsに一致しないので、一覧用にBash(bundle exec fastlane actions)もallowに足します。
つまずきやすい点
落とし穴
askのlaneを直接のコマンドで迂回される
lane経由のbetaをaskにしても、bundle exec fastlane pilot uploadの直接呼びは別のコマンドです。pilot、deliver、supplyをaskに足していない設定では、承認なしで同じ書き込みが通ります。
もう1つは、環境変数の渡し方です。Claude Codeの子プロセスにASC_KEY_PATHなどが渡らないと、verifyが認証エラーで止まります。シェルの設定に書いたうえで、Claude Codeを起動したシェルの環境で動かします。
最後に、deliverをipaなしで直接呼ぶ癖です。メタデータだけが書き換わるため、askの対象に残しておく意味があります。
任せる範囲を狭く始める
Claude Codeに向いているのは、Fastfileの下書きと、ビルドエラーの読み解き、検証laneの反復です。外部に残る操作は、lane名のaskとdenyで線を引き、Fastfileの変更を差分で見る運用にすると、任せる範囲を広げても確認点が残ります。
最初はbuild_onlyとverifyだけをallowにし、betaをaskに加えるのは、検証laneの結果がClaudeの報告と一致することを何度か見てから、という進め方もあります。IDE内でのAI支援を使いたい場合は、Claude for Xcodeの使い方が入口になります。権限ルールで実行を絞る考え方は、OpenTofuでvalidateとplanだけを許可する権限設計と同じ型です。