4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

iOSAdvent Calendar 2023

Day 5

【iOS】fastlane (or xcodebuild) で `TestFlight Internal Only` を使う

Last updated at Posted at 2023-12-04

はじめに

Xcode Cloud の登場など、 1st party の CD 環境も提供されている今、 fastlane への依存は少しずつ減っているかもしれません。
とはいえ、開発現場ではまだまだ活用されているツールかと思うので、今回は TestFlight Internal Only のビルドを fastlane を利用して作成する方法をご紹介します。

そもそも TestFlight Internal Only とは?

WWDC 2023 にて発表された TestFlight の新しい機能です。1
従来、TestFlight で配布するためのビルドは、内部テスターだけではなく、外部テスターへの配布や App Store への配信が可能なものを利用するしかありませんでした。
Xcode 15 以降、 TestFlight Internal Only の設定を行なってビルドを作成することによって、そのビルドは「内部テスター」への配布に限定できるようになります。
「社内関係者のみに配布したいケース」などにおいて、意図せず App Store への配信を行なってしまうリスクを軽減することができます。
前述の通りですが、 TestFlight Internal Only の設定でビルドができるのは Xcode 15 以降になります。

結論

fastlane の GitHub Discussion のコメントの通り、 fastlane gym のオプションに設定を追加して TestFlight に上げることで内部用の TestFlight ビルドになります。

lane :internal_only_beta do
  gym(
    # ...
    export_options: {
      # ⭐️ これを追加
      testFlightInternalTestingOnly: true
    }
  )
  pilot(
    # ...
  )
end

これで配布された TestFlight のビルドは「内部」という表示がされ、内部テスターのみの配信に限定されます。

ScreenShot_2023-12-03_14_51_10.png

fastlane に詳しい方や単純に利用できれば良い方は、ここまで見ていただければ大丈夫かと思います :ok_hand:
もう少し詳細を知りたい方はもう少々お付き合いください。

fastlane gym の export_options は何者?

fastlane gym は(強引な言い方をすると) xcodebuild のラッパー2 のようなものです。
gym の export_options オプションに渡す Hash の key/value は、 xcodebuild コマンドの -exportOptionsPlist オプションで指定する plist ファイルに設定可能な key/value を設定することができます。
gym では、 export_options で設定した key/value から 一時的な plist ファイルを生成し、その plist ファイルのパスを xcodebuild コマンドの -exportOptionsPlist に渡すようになっています。

xcodebuild コマンドを確認してみる

ということで、 xcodebuild コマンドのヘルプを見て -exportOptionsPlist オプションについて調べてみます。 (必要部分のみ抜粋)

xcodebuild -help
Usage: xcodebuild [-project <projectname>] [[-target <targetname>]...|-alltargets] [-configuration <configurationname>] [-arch <architecture>]... [-sdk [<sdkname>|<sdkpath>]] [-showBuildSettings [-json]] [<buildsetting>=<value>]... [<buildaction>]...
       xcodebuild [-project <projectname>] -scheme <schemeName> [-destination <destinationspecifier>]... [-configuration <configurationname>] [-arch <architecture>]... [-sdk [<sdkname>|<sdkpath>]] [-showBuildSettings [-json]] [-showdestinations] [<buildsetting>=<value>]... [<buildaction>]...
       xcodebuild -workspace <workspacename> -scheme <schemeName> [-destination <destinationspecifier>]... [-configuration <configurationname>] [-arch <architecture>]... [-sdk [<sdkname>|<sdkpath>]] [-showBuildSettings] [-showdestinations] [<buildsetting>=<value>]... [<buildaction>]...
       xcodebuild -version [-sdk [<sdkfullpath>|<sdkname>] [-json] [<infoitem>] ]
       xcodebuild -list [[-project <projectname>]|[-workspace <workspacename>]] [-json]
       xcodebuild -showsdks [-json]
       xcodebuild -exportArchive -archivePath <xcarchivepath> [-exportPath <destinationpath>] -exportOptionsPlist <plistpath>
       xcodebuild -exportNotarizedApp -archivePath <xcarchivepath> -exportPath <destinationpath>
       xcodebuild -exportLocalizations -localizationPath <path> -project <projectname> [-defaultLanguage <language>] [-exportLanguage <targetlanguage>... [-includeScreenshots]]
       xcodebuild -importLocalizations -localizationPath <path> -project <projectname> [-mergeImport]
       xcodebuild -resolvePackageDependencies [-project <projectname>|-workspace <workspacename>] -clonedSourcePackagesDirPath <path>
       xcodebuild -create-xcframework [-help] [-framework <path>] [-library <path> [-headers <path>]] -output <path>

Options:
    # ~ 略 ~
    -exportOptionsPlist PATH                                 specifies a path to a plist file that configures archive exporting
    # ~ 略 ~

Available keys for -exportOptionsPlist:

    # ~ 略 ~
	testFlightInternalTestingOnly : Bool

		When enabled, this build cannot be distributed via external TestFlight or the App Store. This is recommended for pull requests, development branches, and other builds that are not suitable for external distribution.

	# ~ 略 ~

-exportOptionsPlist オプションに利用可能なキー一覧も出力されますが、ここに testFlightInternalTestingOnly というものがあることが分かります。

説明にも、このフラグを立てることで外部テスターや App Store への配布ができないビルドになることが書かれています。

When enabled, this build cannot be distributed via external TestFlight or the App Store.

尚、筆者環境では Xcode 15.0.1 の xcodebuild を利用していますが、 Xcode 15 以降であれば利用可能なはずです。

xcodebuild -version                                                                                                                     [14:41:17]

Xcode 15.0.1
Build version 15A507

xcodebuild コマンドから TestFlight Internal Only を使う

ここまで分かれば、 fastlane を使用しない場合でも、 xcodebuild コマンドでのアーカイブでも TestFlight Internal Only の設定ができることが分かってきます。

要するに、 -exportOptionsPlist に渡す plist ファイルに testFlightInternalTestingOnly キーを Boolean で YES に設定して xcodebuild コマンドから Archive を行えば良いのです。

ScreenShot 2023-12-03 14.47.53.png

Archive できれば、 altool などで生成したビルドをアップロードすれば内部テスター限定のビルドとして TestFlight で利用できそうですね :ok_hand: (そこまでは試していないですが)

おわりに

ということで、 fastlane や xcodebuild から TestFlight Internal Only を使う方法の紹介でした。
私自身、「fastlane が TestFlight Internal Only に対応しないかな〜」と思っていたところ、冒頭にも記載の fastlane の GitHub Discussion の回答 を見つけ、内部的にどのように作用しているのかを調べてみたというのがこの記事の経緯になります。
ニッチな内容なだけに、あまり知らない方もいるかもなと思い記事にしてみました。
誰かのお役に立てれば幸いです。

参照

  1. https://developer.apple.com/videos/play/wwdc2023/10117/?time=275

  2. xcodebuild の機能の中でも ipa や app ファイルの生成部分にフォーカスしたもので、 xcodebuild コマンドが持つさまざまな機能(例えば xcframework の生成など)を網羅しているものではないので、ラッパーというのは少々強引かもしれないですが、簡易的に説明するためラッパーと表現しました

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?