React Nativeアプリ用の継続的インテグレーションとデリバリー

> **これは[Codemagic](https://codemagic.io/?utm_source=qiita&utm_medium=referral&utm_campaign=flutter_distribution&utm_content=japanese_lang) CI/CDを使ってReact Nativeアプリを構築するためのスタートガイドです。2021年5月に更新。**

CI/CDに関して言うと、Codemagicは開発者に提供するエキサイティングなものがたくさんあります。（簡単なプロジェクトのセットアップ、本当に素晴らしいSlackコミュニティ、ビルドボックスへのリモートアクセスなど）。しかし今では、CodemagicでReact Native用のワークフローもあります。これは**最高**です。

![how-to-build-react-native-app-on-codemagic (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2028491/e2fde3ba-a082-3b08-fec8-6168cc21a21a.png)


## React NativeアプリにCodemagic CI/CDを使うべき上位の理由

### 簡単なプロジェクト設定
[React Nativeアプリの構築を始める](https://reactnativeci.com)は、構成テンプレートも用意されていて簡単です。スターターワークフローとしてReact Native Appを選択するだけで、プロジェクトを開始できます。

### iOSとAndroid向けにカスタマイズ可能なワークフロー
Codemagicは、クロスプラットフォームでのアプリ開発を念頭に置いて作られています。開発チームのニーズに合ったiOSとAndroid用のワークフローで、React Nativeパイプラインを完全にコントロールすることができます。

### iOSとAndroidのシームレスなコード署名
AndroidキーストアとiOSのコード署名ファイルをアップロードするだけで、署名付きの成果物を受け取ることができます。iOS向けの自動コード署名では、Codemagicがあなたのために署名証明書とプロビジョニングプロファイルの作成と管理を行います。

### ユニットテストと統合テスト
自動化されたテストにより、React Nativeアプリケーションの品質を保証します。[Jest](https://blog.codemagic.io/testing-react-native-apps-with-jest/?utm_source=qiita&utm_medium=referral&utm_campaign=flutter_distribution&utm_content=japanese_lang)を使ってユニットテストを実行したり、[Appium](https://blog.codemagic.io/mobile-testing-appium-react-native-apps/?utm_source=qiita&utm_medium=referral&utm_campaign=flutter_distribution&utm_content=japanese_lang)や[Detox](https://blog.codemagic.io/react-native-detox-tests-on-codemagic/?utm_source=qiita&utm_medium=referral&utm_campaign=flutter_distribution&utm_content=japanese_lang)を使ってシミュレーター/エミュレーターや実際のデバイス上でアプリ全体をテストしたりすることができます。

### React Nativeアプリを簡単に配布
TestFlight、Google Play、Firebase App Distributionでアプリの最新版をテスターに配布したり、Apple App StoreやGoogle Playに自動的に公開するようにワークフローを構成したりすることができます。

### ファーストクラスのサポート
[Codemagic Slackワークスペースコミュニティ](https://slack.codemagic.io/)には、3,000人以上のメンバーが参加しています。迅速な解決策を見つけ、仲間の開発者の方々とプロジェクトについて話し合うことができます。 


## ソフトウェアと依存関係のインストール

Windows、Linux、macOSのいずれかを使って、React Nativeを始めることができます。macOSではiOSとAndroidの両方の環境を利用できますが、LinuxやWindowsではAndroidの環境のみ対応しています。ここでは、React Nativeの開発にmacOSを使用していることを前提としていますが、WindowsやLinuxでも常に同じような手順を踏むことができます。

React Nativeを始めるには、2つの方法が考えられます：
* Expo CLI
* React Native CLI

### Expo CLIのインストール

この方法を利用するには、ローカルマシンに**Node 12 LTS**以降がインストールされている必要があります。`npm`を使って、Expo CLIコマンドラインユーティリティをインストールします：

```bash
npm install -g expo-cli
```

### React Native CLIのインストール

macOSの場合は、Node、React Nativeのコマンドラインインターフェイス、JDK、Android StudioまたはXcodeをインストールする必要があります。

推奨される方法は、Homebrewを使ってNodeとWatchmanをインストールすることです。Homebrewのインストール後、ターミナルで以下のコマンドを実行します：

	`brew install node`
	`brew install watchman`
  
また、CocoaPodsをインストールする必要もあります。以下のコマンドでCocoaPodsをインストールします：

```bash
sudo gem install cocoapods
```

WindowsとLinuxの場合は、Node、React Nativeコマンドラインインターフェイス、Python、JDK、Android Studioが必要です。アプリの開発にはお好みのエディタを使用できますが、Android用のReact Nativeアプリを構築するために必要なツールをセットアップするには、Android Studioをインストールする必要があります。

React Nativeには、コマンドラインインターフェイスが組み込まれています。特定のバージョンのCLIをグローバルにインストールして管理するのではなく、Node.jsに同梱されている`npx`を使って、実行時に最新のバージョンにアクセスすることをお勧めします。

`npx react-native <command>`では、コマンドの実行時に、現在の安定バージョンのCLIがダウンロードされ、実行されます。以前にグローバルな `react-native-cli` パッケージをインストールした場合は、予期せぬ問題を引き起こす可能性があるため、削除してください。


## React Nativeアプリケーションのセットアップ

> 本記事は、React Nativeのバージョン `0.64` 安定版のリリースに特化して書かれています。

まず、以下のコマンドでReact Nativeの新規プロジェクトを作成します：

```bash
react-native init ReactNativeApp
cd ReactNativeApp
react-native run android
```

## React Nativeアプリ用のCodemagic CI/CDの使用開始について

Codemagicへのサインアップは、[GitHub](https://github.com)、[Bitbucket](https://bitbucket.org)、[GitLab](https://gitlab.com)のアカウントかメールアドレスを使用して行うことができます。サインアップ後は、異なるリポジトリプロバイダーを接続し、セルフホスト型またはクラウドベース型のGitリポジトリからアプリを追加できます（[リポジトリの追加（Adding repositories）](https://docs.codemagic.io/getting-started/adding-apps-from-custom-sources/?utm_source=qiita&utm_medium=referral&utm_campaign=flutter_distribution&utm_content=japanese_lang)を参照）。

サインアップ時に、リポジトリへのアクセスを許可することなく、Codemagicがあなたを認証するのを承認するよう求められます。

そうすると、Codemagicで新しいプロジェクトを作成し、オプションから**React Native App**を選択するだけで、**React Nativeワークフロー**を使用することができます。

![左側にあるのは私たちの合図です!](https://blog.codemagic.io/uploads/2020/07/newimg1.png)

**続行（Continue）**をクリックすると、`codemagic.yaml`ファイルが表示されます。

![](https://blog.codemagic.io/uploads/2020/07/newimg2.png)

これをダウンロードして、ローカルリポジトリに追加できます。これはCodemagicのパイプラインを構成し、CodemagicがそのビルドサーバーでReact Nativeのビルドを実行する方法を知れるようにします。

## ビルド用のYAMLファイルの修正

このプロセスの次のステップは、ソリューションを構築するために`codemagic.yaml`ファイルを修正することです。では、このファイルがどのようなものか見てみましょう：

```yaml
# 詳細はhttps://docs.codemagic.io/getting-started/building-a-react-native-app/ をご覧ください。
# 中括弧内の値を確認し、更新してください。

workflows:
    react-native:
        name: React Native App
        environment:
            vars:
                XCODE_WORKSPACE: "ReactNativeApp"
                XCODE_SCHEME: "ReactNativeApp"
                CM_KEYSTORE: Encrypted(...)
                FCI_KEYSTORE_PASSWORD: Encrypted(...)
                FCI_KEY_PASSWORD: Encrypted(...)
                FCI_KEY_ALIAS: Encrypted(...)
                CM_CERTIFICATE: Encrypted(...)
                CM_CERTIFICATE_PASSWORD: Encrypted(...)
                CM_PROVISIONING_PROFILE: Encrypted(...)
            node: latest
        scripts:
            - npm install
            - echo "sdk.dir=$HOME/programs/android-sdk-macosx" > "$FCI_BUILD_DIR/android/local.properties"
            - |
                chmod -R 777 $FCI_BUILD_DIR
                echo $CM_KEYSTORE | base64 --decode > $FCI_BUILD_DIR/keystore.jks
                # build Android
                cd android
                ./gradlew assembleRelease
            - keychain initialize
            - |
              # set up provisioning profiles
              PROFILES_HOME="$HOME/Library/ProvisioningProfiles"
              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"
        artifacts:
            - android/app/build/outputs/**/**/*.apk
            - build/ios/ipa
```

明らかに、ビルドを成功させるには、このYAMLファイルにいくつかの変更を加える必要があります。

## 必要な変更

### Android

一般的には、CI/CDパイプラインでアプリのデバッグバージョンを構築したいと思うことはまずありません。その代わりに、ビルドプロセスにリリースビルドを作るように指示する必要があります。そのためには、`#build Android`の下の行を更新して、以下のようにするだけです：

```yaml
- |
  # build Android
  cd android
  ./gradlew assembleRelease
```

ビルドプロセスは、`build.gradle`で定義されたパスに沿って行われるようになります。コード署名はそれ自体がトピックです（詳しくは[こちら](https://blog.codemagic.io/the-simple-guide-to-android-code-signing/)で説明しています）ので、ここでは単にビルドを動作させるために必要な手順を説明します。

**アプリレベル**の`build.gradle`（`YourProjectDirectory\android\app`の下にあります）では、リリース署名の詳細を追加する必要があります。一方で、リリース署名の詳細は、ビルドがローカルではなく**Codemagic**上で実行される場合に**のみ**使用する必要があります。

そして、リリースファイルから署名の詳細を読み取るようにビルドプロセスを構成します。

```groovy
signingConfigs {
    debug {
        storeFile file('debug.keystore')
        storePassword 'android'
        keyAlias 'androiddebugkey'
        keyPassword 'android'
    }

    release {
        if (System.getenv()['CI']) { // CI=true is exported by Codemagic
            storeFile file(System.getenv()['FCI_BUILD_DIR'] + '/keystore.jks')
            storePassword System.getenv()['FCI_KEYSTORE_PASSWORD']
            keyAlias System.getenv()['FCI_KEY_ALIAS']
            keyPassword System.getenv()['FCI_KEY_PASSWORD']
        }
        else {
            def keystorePropertiesFile = rootProject.file('key.properties')
            def keystoreProperties = new Properties()
            keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
            keyAlias keystoreProperties['keyAlias']
            keyPassword keystoreProperties['keyPassword']
            storeFile file(keystoreProperties['storeFile'])
            storePassword keystoreProperties['storePassword']
        }
    }
}
```

ここで実際に何が起こっているのでしょうか？　簡単に言うと、**release**のビルドで実行している場合、CI環境変数が宣言されているかどうかをチェックします。(Codemagicのビルドマシンはこの変数を宣言します。) そうであれば、環境変数からキーストアの場所と適切な署名の詳細を取得します。そうでなければ、これらの詳細に対してローカルの `key.properties` を使用し、代わりにそこから詳細を取得します。これは、ビルドがローカルだけでなく、Codemagic上でも継続して動作することを意味しています（いいボーナスですね）。

ローカルデバッグの `key.properties` は次のようになります（これはデバッグキーストアを対象としたものなので、あなたのものは異なると思います）。

```groovy
storePassword=android
keyPassword=yourpassword
keyAlias=androiddebugkey
storeFile=keystore.keystore
```

これらはデバッグキーストアのただのキーですが、通常、これらは非常に機密性の高い情報です。これらの設定を誰にでも読めるようにはしたくないので、これらのファイルをソース管理にチェックインするのは本当にまずいです。その代わりに、それらをCodemagicで暗号化し、ビルドが実行される直前に必要な詳細情報をビルドプロセスで復号化するようにします。

#### ビルド時の依存関係の暗号化

プロジェクトの構成ページで、ノートブックのアイコンをクリックすると、プロジェクトの設定に役立つガイドのリンク集が表示されます。

![](https://blog.codemagic.io/uploads/2020/07/newimg3.png)

鍵のアイコンをクリックすると、**環境変数の暗号化**関数を使用して、機密情報を安全にチェックインできる形式に変換します。

![](https://blog.codemagic.io/uploads/2020/07/newimg4.png)

次に、キーストアファイルをこのウィンドウにドラッグすると、キーストアを含む暗号化された変数を受け取ることができます。アイコンの隣にある小さなクリップボードをクリックするだけで、暗号化されたキーストア変数がクリップボードにコピーされます。

![](https://blog.codemagic.io/uploads/2020/07/newimg5.png)

また、この画面を使って、キーストアのエイリアスやパスワードなど、個々の変数を暗号化することもできます。ここでは、これらの値を `codemagic.yaml` ファイルに貼り付けて行います。完了すると、こんな感じになっているはずです：

![](https://blog.codemagic.io/uploads/2020/07/newimg6.png)

ビルド変数の構成が完了したので、後のビルドプロセスで使用できるようになりました。これらの4つの環境変数（キーストア、キーストアのパスワード、キーエイリアス、パスワード）を暗号化しておけば準備完了です。

#### ビルドスクリプト

Androidのビルドでは、以下のようなことをしたいと思います：

1. クローンディレクトリを書き込み可能にする。(これがないとビルドに失敗していたので、`chmod`を使用しました)
2. ビルドプロセスで使用できるように、キーストアファイルをリポジトリに書き込みます。
3. Androidディレクトリに移動して、`assembleRelease`というGradleタスクを実行すると、署名入りのAPKが生成されます。

`codemagic.yaml`ファイルでは、以下のようになっています：

```yaml
- npm install
- echo "sdk.dir=$HOME/programs/android-sdk-macosx" > "$FCI_BUILD_DIR/android/local.properties"
- |
  chmod -R 777 $FCI_BUILD_DIR
  echo $CM_KEYSTORE | base64 --decode > $FCI_BUILD_DIR/keystore.jks
  # build Android
  cd android
  ./gradlew assembleRelease
```

Androidの場合、本当に簡単です！　iOSの場合は、もう少し複雑ですが...

### iOS

ビルドを正常に完了させるためには、App Store Connectからの証明書と`.mobileprovision`ファイルの両方をビルドエージェントに読み込む必要があります。この例では、署名証明書を**CM_CERTIFICATE**、証明書のパスワードを**CM_CERTIFICATE_PASSWORD**、プロビジョニングプロファイルを**CM_PROVISIONING_PROFILE**として暗号化しています。

#### ビルドスクリプト

これはAndroidで相当するものよりも少し複雑に見えますが、✨イケてるCodemagic CLI関数✨を使って動作させることもできます。今回のビルドでは、こんなことをしています：

1. 署名証明書をビルドエージェントにインポートするための準備として、`keychain initialize`を実行
2. `PROFILES_HOME`をモバイルプロビジョニング証明書が置かれる場所に設定してから、そのディレクトリを作成
3. `PROFILE_PATH`を "PROFILES_HOME "内の一時的な場所に設定
4. **PROVISIONING_PROFILE**を仮の名前で`PROFILE_PATH`に書き込む
5. 署名証明書（**CM_CERTIFICATE**）を`/tmp/certificate.p12`に書き込む
6. そうするために、この証明書を、**CM_CERTIFICATE_PASSWORD**を使用して、ビルドボックスのローカル証明書ストアに追加
7. `xcode-project use-profiles`コマンドを実行
8. iOSディレクトリに移動し、`pod install`を実行し、`xcode-project build-ipa`を使って、使用するワークスペースとスキームを指定してアプリを構築

```yaml
- 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"
```

### 完成したcodemagic.yamlファイル

以上の作業を終えると、以下のような `codemagic.yaml` ファイルができあがります：

```yaml
workflows:
  react-native:
    name: React Native App
    environment:
      vars:
        XCODE_WORKSPACE: 'ReactNativeApp'
        XCODE_SCHEME: 'ReactNativeApp'
        CM_KEYSTORE: Encrypted(...)
        FCI_KEYSTORE_PASSWORD: Encrypted(...)
        FCI_KEY_PASSWORD: Encrypted(...)
        FCI_KEY_ALIAS: Encrypted(...)
        CM_CERTIFICATE: Encrypted(...)
        CM_CERTIFICATE_PASSWORD: Encrypted(...)
        CM_PROVISIONING_PROFILE: Encrypted(...)
      node: latest
    scripts:
      - npm install
      - echo "sdk.dir=$HOME/programs/android-sdk-macosx" > "$FCI_BUILD_DIR/android/local.properties"
      - |
        chmod -R 777 $FCI_BUILD_DIR
        echo $CM_KEYSTORE | base64 --decode > $FCI_BUILD_DIR/keystore.jks
        # build Android
        cd android
        ./gradlew assembleRelease
      - 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"
    artifacts:
      - android/app/build/outputs/**/**/*.apk
      - build/ios/ipa
```

注意点を1つ。`Encrypted(...)`の値はプレースホルダーです。ビルドプロセスに合わせて、Codemagicで独自の値を暗号化する必要があります。

## CodemagicでReact Nativeアプリを構築

Codemagicでビルドを開始する前に、バージョン管理システムを介して、'codemagic.yaml' ファイルが同じプロジェクトのルートレベルでコミットされていることを確認します。

`codemagic.yaml`ファイルの完全なバージョンの詳細なリファレンスについては、[React Nativeアプリケーションのサンプルをご覧ください](https://github.com/codemagic-ci-cd/codemagic-sample-projects/blob/main/react-native/react-native-demo-project/codemagic.yaml)。

ビルドを開始するには、以下の手順に従います：

1. React Nativeプロジェクトのアプリケーション設定で、「**構成ファイルの確認**」をクリックします。

2. **最初のビルドを開始**をクリックすると、React NativeプロジェクトからAndroidとiOSアプリのビルドを開始できます。

![](https://blog.codemagic.io/uploads/2020/07/newimg7.png)

3. `codemagic.yaml`ファイルからワークフローを選択して、**新規ビルドを開始**をクリックします。

![](https://blog.codemagic.io/uploads/2020/07/newimg8.png)

これにより、プロジェクトの新規ビルドが開始され、ビルド処理ページが表示されます。

![](https://blog.codemagic.io/uploads/2020/07/newimg9.png)

ビルドが完了すると、成果物をダウンロードできるだけでなく、`codemagic.yaml`ファイルで自動公開を設定している場合、アプリを公開することもできます。

上記の手順を簡潔にまとめたものが、[Codemagicドキュメントページ](https://docs.codemagic.io/getting-started/building-a-react-native-app/?utm_source=qiita&utm_medium=referral&utm_campaign=flutter_distribution&utm_content=japanese_lang)にあります。

以上です！　これでReact NativeアプリがCodemagicでビルドされるはずです。ご質問やご意見がございましたら、ぜひ[CodemagicのSlackチャンネル](https://slack.codemagic.io/)にお立ち寄りになって、お知らせください。楽しんで開発しましょう！