iOS用のアプリは、macOSから開発・配布するのが理想です。iOSプラットフォーム向けのアプリ開発は、macOSなしでは考えられません。しかし、React NativeとCodemagicを組み合わせれば、macOSを使わずにiOSアプリを開発・配布できます。本記事では、Macを使わずにiOSアプリを開発・配布するための設定を行います。Linuxを使用し、Codemagicでカスタム/手動コード署名を行います。
本記事はSneh Pandyaさんが執筆いたしました。
LinuxでのReact Nativeアプリの開発
2015年以降、React Nativeはモバイル開発者に広く採用されており、その人気はますます高まっています。React Nativeは、クロスプラットフォームのモバイルアプリケーション開発フレームワークで、1つのソースコードからiOSとAndroidのアプリを開発できます。
React NativeはJavaScriptをベースにしており、ウェブ開発者にとってはチャンスが広がります。なぜなら、React Nativeを使ってモバイルアプリの開発もできるからです。iOSアプリを開発する上での最大の障害は、開発・配布する際にiOSのネイティブコンポーネントとmacOSが必要なことです。しかし、React Nativeの登場により、macOS環境に完全に依存することなく、iOS向けであってもアプリの開発・配布が可能になりました。
LinuxでReact Nativeアプリを開発する方法
iOSアプリは、React Nativeプラットフォームを利用して、Linuxから構築・公開することができます。本記事では、ReactNativeAppSigningというプロジェクトを使用します。このアプリでは、React Nativeを使ってLinux上でAndroidやiOSのアプリを構築する方法をご紹介いたします。注意すべき点は、LinuxはネイティブにiOSでアプリを作ることができないことです。したがって、Androidアプリが作られ、同じコードベースを使って、Android版と比べて最小限の変更でiOSアプリを生成し、デプロイすることになります。進め方は主に3つあります:
-Linuxマシンを使ってアプリを構築
-Dockerコンテナを使ってアプリを構築
-Codemagicを使ってアプリを構築
Linuxマシンでアプリを構築
Linuxマシンがお手元にある場合は、こちらの方が簡単に進められます。まず、LinuxマシンにAndroid SDKとReact Nativeをインストールする必要があります。その後、ReactNativeAppSigningのリポジトリをクローンして進める必要があります。
Dockerコンテナを使ってアプリを構築
お手元にLinuxマシンがない場合、Dockerコンテナを使うのが理想的で最も簡単な方法です。すでにDockerエコシステムに精通している場合は、Android SDKとReact NativeがすでにインストールされているDockerfileを直接作成できます。
Dockerエコシステムに慣れていない場合は、以下の手順に従ってください:
- Dockerをセットアップし、
Dockerfile
とpackage.json
を作成して、React Native環境をDockerコンテナに構築します。package.json
ファイルには、React Native Expo CLIの実行に必要な最低限のパッケージが含まれています。
{
"main": "node_modules/expo/AppEntry.js",
"private": true,
"scripts": {
"android": "expo-cli start --android",
"ios": "expo-cli start --ios",
"start": "expo-cli start"
},
"dependencies": {
"expo": "30.0.0",
"expo-cli": "2.2.4",
"react": "16.3.1",
"react-native": "https://github.com/expo/react-native/archive/sdk-30.0.0.tar.gz"
}
}
2. このDockerfileは、React Native環境のセットアップと実行に役立ちます。ここでは、node.jsの公式Dockerイメージを使用します。これには、yarn
やnpm
などの依存関係がすでにインストールされています。この構成により、ポートが公開され、Dockerコンテナはこれらのポートのデータにアクセスできることを知ることができます。依存関係のインストールには、package.json
とyarn.lock
が使用され、Expoではapp.json
が最低限必要とされています。私たちのReactNativeAppSigningアプリのDockerfileは以下のようになります:
FROM node:latest
LABEL version=1.2.1
ENV ADB_IP="192.168.1.1"
ENV REACT_NATIVE_PACKAGER_HOSTNAME="192.255.255.255"
EXPOSE 19000
EXPOSE 19001
RUN mkdir /reactnativeappsinging
WORKDIR /reactnativeappsinging
ADD . /reactnativeappsinging
RUN apt-get update &&
apt-get install android-tools-adb
WORKDIR /app
COPY package.json yarn.lock app.json ./
RUN yarn --network-timeout 100000
CMD adb connect $ADB_IP &&
yarn run android
3. また、Dockerコンテナの環境変数は、実行時に設定することもできます。このコードスニペットはご説明用のものですが、ご必要に応じてDockerfileをカスタマイズできます。DockerfileとDockerをインストールしたら、Dockerを使ってアプリを取得できます。
docker build -t reactnativeappsigning .
docker run -e ADB_IP=192.168.112.101
-e REACT_NATIVE_PACKAGER_HOSTNAME=192.168.1.1
-p 19000:19000
-p 19001:19001
name expo-ios
これらのコマンドを実行すると、React Native環境を備えたDockerコンテナが稼働します。
Codemagicを使用してアプリを構築
CI/CDに関して言うと、Codemagicは、React Nativeのようなクロスプラットフォームフレームワーク用のワークフローを含め、開発者にとって興奮するものをたくさん備えています。Codemagicへの登録はこちらから簡単にできます(無料):
これらのワークフローは、Codemagicで新しいプロジェクトを作成し、オプションからReact Native Appを選択するだけで使用できます。
それをクリックすると、React Native用の「入門ガイド」が開きます:
「開始(Start)」をクリックすると、「codemagic.yaml」ファイルが表示されます。これをダウンロードして、ローカルリポジトリに追加できます。これはCodemagicのパイプラインを構成し、CodemagicがそのビルドサーバーでReact Nativeのビルドを実行する方法を知れるようにします。
このプロセスの次のステップは、ソリューションを構築するために、codemagic.yaml
ファイルを修正することです:
workflows:
react-native:
name: reactnativeappsigning
environment:
vars:
XCODE_WORKSPACE: "{{ ADD WORKSPACE NAME HERE }}"
XCODE_SCHEME: "{{ ADD SCHEME NAME HERE }}"
node: latest
scripts:
- npm install
- echo "sdk.dir=$ANDROID_SDK_ROOT" > "$FCI_BUILD_DIR/android/local.properties"
- |
# build Android
cd android
./gradlew assembleDebug
- |
# build iOS
cd ios
pod install
xcodebuild build -workspace "$XCODE_WORKSPACE.xcworkspace" -scheme "$XCODE_SCHEME" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO
artifacts:
- android/app/build/outputs/**/**/*.apk
- $HOME/Library/Developer/Xcode/DerivedData/**/Build/**/*.app
ビルドを正常に完了させるためには、App Store Connectからの証明書とモバイルプロビジョニングファイルの両方をビルドエージェントに読み込む必要があります。この例では、署名証明書をCM_CERTIFICATE
、証明書のパスワードをCM_CERTIFICATE_PASSWORD
、プロビジョニングプロファイルをCM_PROVISIONING_PROFILE
として暗号化しています。
今回のビルドでは、こんなことをしています:
- 署名証明書をビルドエージェントにインポートするためにkeychain initializeを実行
PROFILES_HOME
をモバイルプロビジョニング証明書が置かれる場所に設定PROFILE_PATH
を “PROFILES_HOME “内の一時的な場所に設定PROVISIONING_PROFILE
を仮の名前でPROFILE_PATH
に書き込む- 署名証明書(
CM_CERTIFICATE
)を/tmp/certificate.p12
に書き込む - そうするために、この証明書を、
CM_CERTIFICATE_PASSWORD
を使用して、ビルドボックスのローカル証明書ストアに追加 xcode-project use-profiles
コマンドを実行- そして、基本的には、iOSディレクトリに移動し、
pod install
を実行し、xcode-project build-ipa
を使って、使用するワークスペースとスキームを指定してアプリを構築
- keychain initialize
- |
# set up provisioning profiles PROFILES_HOME="$HOME/Library/MobileDevice/Provisioning Profiles"
mkdir -p "$PROFILES_HOME"
PROFILE_PATH="$(mktemp "$PROFILES_HOME"/$(uuidgen).mobileprovision)"
echo ${CM_PROVISIONING_PROFILE} | base64 --decode > $PROFILE_PATH
echo "Saved provisioning profile $PROFILE_PATH"
- |
# set up signing certificate
echo $CM_CERTIFICATE | base64 --decode > /tmp/certificate.p12
keychain add-certificates --certificate /tmp/certificate.p12 --certificate-password $CM_CERTIFICATE_PASSWORD
- xcode-project use-profiles
- |
# build iOS
cd ios
pod install
- xcode-project build-ipa --workspace "ios/$XCODE_WORKSPACE.xcworkspace" --scheme "$XCODE_SCHEME"
App Store Connectからのコード署名アセットの生成
iOSアプリにコード署名するには、Appleの開発者アカウント、開発証明書と配布証明書、アプリID、アプリ用に作成したプロビジョニングプロファイルが必要です。Codemagic上でiOSアプリの開発ビルドまたはデバッグビルドに手動コード署名を構成するには、以下のものが必要です:
.P12
形式の開発証明書または配布証明書。証明書とプロビジョニングプロファイルは、Apple Developer Portalの「証明書、識別子、プロファイル(Certificates, Identifiers and Profiles )」セクションに移動してダウンロードできます。- App Store ConnectまたはApple Developer Portalからダウンロードしたプロビジョニングプロファイル。CodemagicでiOSアプリをコード署名するには、証明書とプロビジョニングプロファイルの両方が必要なため、これらのファイルは後の使用に向けて保存しておきます。
- iOSアプリのバンドル識別子で、これもApple Developer Portalのダッシュボードから収集できます。
Xcodeプロジェクトファイルの更新
Apple Developer Portalからコード署名資産をすべて収集後、正しいチームとプロビジョニングプロファイルで手動コード署名を使用できるように、Xcodeプロジェクトファイルをソートして更新します。手動コード署名を動作させるために、リポジトリ上の ios/YOUR_APP.xcodeproj/project.pbxproj
ファイルの以下のフィールドを更新する必要があります:
DevelopmentTeam = YOUR_DEVELOPMENT_TEAM_ID
ProvisioningStyle = Manual
PROVISIONING_PROFILE_SPECIFIER = NAME_OF_YOUR_PROVISIONING_PROFILE
内部ビルドの場合はデバッグ構成で、App Storeビルドの場合はリリース構成で、変更を行うようにしなければなりません。project.pbxproj
に値が設定されると、CodemagicからiOSアプリをデプロイする準備が整います!
Codemagicによるコード署名の設定
アプリを配布する準備ができたら、Codemagicを使ってアプリのCI/CDを簡単に設定できます。入門ガイドをご覧ください。
手動コード署名
CodemagicのiOSアプリの手動コード署名は、これまでは「設定(Settings) → 公開(Publish) → iOSコード署名(code signing) → 手動(Manual)」と進み、そこで証明書とプロビジョニングプロファイルをアップロードして利用できました。現在、自動コード署名という簡単な方法が導入され、手間がかからないようになっています。
自動コード署名
Apple Developer Portalに統合された自動コード署名機能では、認証にApp Store Connect APIキーを使用するようになりました。これにより、セッションの期限切れや2要素認証の煩わしさがなくなります。コード署名用に複数のキーを設定し、ワークフロー設定で適切なキーを選択できます。Codemagicはほとんどのユーザーを自動的に移行させましたが、もしApple Developer Portal統合の接続を求められた場合は、ドキュメントの指示に従ってください。
これで、ビルドを実行すると、IPAファイルの形でiOSアプリができあがり、プロビジョニングされた端末にデプロイできます。プロビジョニングプロファイルに追加された任意のiOS端末にこのアプリをインストールして、iOSアプリをテストできます。もしそこでバグが発生しても、Linux環境に戻ってバグを修正できます。
iOSアプリをApple App Storeに配布
現時点では、社内でテストするために、iOSアプリのデバッグ版を作成しました。同様に、iOSアプリをApp Storeに配布することもできます。アプリをApp Storeにデプロイする準備ができたら、配布証明書とプロダクション・プロビジョニング・プロファイルを使用して、アプリをリリースモードでビルドする必要があります。証明書やプロファイルも同様に生成できますが、プロビジョニングプロファイルの作成時にApp Store配布を選択する必要があります。ディストリビューション・プロビジョニング・プロファイルは、どの端末でもiOSアプリを実行するので、プロビジョニングプロファイルに明示的に端末を追加する必要はありません。
iOSの配布証明書とプロダクション・プロビジョニング・プロファイルが手元にあれば、Codemagicのビルドセクションで、図のようにリリースモードを選択できます。
また、ビルドの引数をデバッグではなくリリースに設定しました。「公開(Publish)」セクションでは、App Storeバージョンのアプリを生成するために、配布証明書とプロダクション・プロビジョニング・プロファイルをアップロードする必要があります。
Codemagicがビルドの成果物を生成したら、App Storeガイドラインに従って、App Store Connect(旧iTunesConnect)にビルドを追加し、アプリを審査に提出します。
結論
クロスプラットフォームのモバイルアプリケーション開発フレームワークとCodemagicのような魔法のようなCI/CDソリューションを組み合わすと、iOSアプリ開発用にMacを所有することは全く必須ではありません。iOS向けの開発では、アプリのデバッグに問題があるかもしれませんが、React NativeとCodemagicを組み合わせて使用し、iOSアプリを開発してApp Storeに公開することは完全に可能です。
Snehさんは、バローダ(Baroda)に拠点を置くシニアプロダクトマネージャーです。Snehさんは、Google Developers Groupのコミュニティオーガナイザーで、NinjaTalksポッドキャストの共同ホストでもあります。意義のある製品を作りたいという情熱から、ブログを書いたり、様々な会議で講演したり、才能のある人たちを指導したりしています。
Snehさんへの連絡は、Twitter (@SnehPandya18)やメール(sneh.pandya1@gmail.com)で可能です。
Discussion about this post