EC2Macインスタンス内にCordovaの本番ビルド環境を用意した件

EC2Macインスタンス内にCordovaの本番ビルド環境を用意した件

去年の12月に公開されたEC2Macインスタンスを利用して、Cordovaのビルド環境を作ったので手順を整理する

目的

cordovaのビルド環境を構築するのは結構簡単ではない、しかもビルド環境が出来上がったと思っていても各環境によって微妙に差異が出ることがよくある(このプラグインがインストールできない、ビルドで正体不明のエラーが出る)。各環境毎の差異をできるだけ埋めるために、ビルドエラーやプラグインインストール時のエラーに関するTipsを用意してもなかなかそれでも新しいエラーが出てくる環境もある。。

そもそもビルドができなければアプリをリリースすることができないので、とても重要な問題だと考えている。

そこで、ちょうど去年の12月に公開されたばかりのMacインスタンスを利用して、その中にビルド環境を用意することになった。こうすることで各ビルド環境毎の差異をなくし、だれでもそのインスタンスにsshで繋ぎ一連のコマンドを叩けばアプリをビルドできる

手順

Macインスタンスを立ち上げる

基本的には クラスメソッドさんのブログを参考にすればできるのだが、リージョンに当たり外れがあってとても困った…

バージニアでやってみると、起動後にステータスチェックが1/2しか通らずsshができない状態のままだった。いくら待っても2/2にならないので別のリージョンで試すことにした。この間にも専有ホストが用意されているのでお金がかかっていて辛い😭(ちなみにバージニアで1時間あたり1.083 USDほど。しかし専有ホストは最低24時間の利用をしなければならないため最低24USDほどかかる)

シンガポールで試してみると、専有ホストの作成時に承認が必要だから待ってろと言われた(Macインスタンスを立ち上げるためには前もって専有ホストの作成を行う必要がある)。通常は数十分で終わるから待ってたが一向にメールは届かなかった…

Your request for accessing resources in this region is being validated, and you will not be able to launch additional resources in this region until the validation is complete. We will notify you by email once your request has been validated. While normally resolved within minutes, please allow up to 4 hours for this process to complete. If the issue still persists, please let us know by writing to aws-verification@amazon.com for further assistance.

今度はオハイオで試したがこれもシンガポールと同様に待ってろと言われた。が、結局24時間ほど待ってもメールは来なかった😭

この時点でもうこれ無理ちゃう?と思いつつダメ元でオレゴンで試したら、ここもステータスチェックが1/2しか通らなかったが10分ほど待てば2/2になり無事ssh接続できた!👏👏👏

この精神状態で10分間我慢した自分を褒めたい

/img/2021-05-29.png

一方バージニアではまだステータスチェックが通らない...

sshで接続してGUI環境の準備

AWS公式が出しているドキュメント通りでOK

https://aws.amazon.com/jp/premiumsupport/knowledge-center/ec2-mac-instance-gui-access/

$ sudo defaults write /var/db/launchd.db/com.apple.launchd/overrides.plist com.apple.screensharing -dict Disabled -bool false
$ sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.screensharing.plist

$ sudo /usr/bin/dscl . -passwd /Users/ec2-user

GUIで接続

VNCを使ってMacからGUIで接続するためにsshでポートフォワード。VNCサーバーの認証はユーザー名とパスワードのみでsshに比べて脆弱なので絶対にポートを開けない方が良い

# ローカルマシンで
$ ssh -i "your-ec2-instance.pem" ec2-user@xx.xx.xx.xx -L 5900:localhost:5900

macならspotlight検索で画面共有を起動し、 ホスト=localhost:5900, ユーザー名=ec2-user, パスワード={上の手順で登録したパスワード} でアクセス、

よく見るmacのログイン画面が表示される。ここのパスワードも先ほどのものを入力してログイン

ボリュームの増強

インスタンス起動時にEBSの容量をいくら増やしても、Macインスタンスの容量がインスタンス起動直後では60GB固定になっていた。

この動画の手順を参考に実行すると、EBSの容量が反映されていた。

手順は以下の通り

# EBSのボリュームがどこにあるか確認、EBSに300GBを設定した場合に以下の出力だと IDENTIFIER=disk1がそれに該当する。また、TYPE=Apple_APFSの IDENTIFIERもメモしておく
$ diskutil list
/dev/disk0 (internal, physical):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      GUID_partition_scheme                        *121.3 GB   disk0

/dev/disk1 (external, physical):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      GUID_partition_scheme                        *322.1 GB   disk1
   1:                        EFI EFI                     209.7 MB   disk1s1
   2:                 Apple_APFS Container disk2         64.2 GB    disk1s2

/dev/disk2 (synthesized):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      APFS Container Scheme -                      +64.2 GB    disk2
                                 Physical Store disk1s2
   1:                APFS Volume Macintosh HD - Data     48.5 GB    disk2s1
   2:                APFS Volume Preboot                 80.9 MB    disk2s2
   3:                APFS Volume Recovery                529.0 MB   disk2s3
   4:                APFS Volume VM                      2.1 GB     disk2s4
   5:                APFS Volume Macintosh HD            11.0 GB    disk2s5

# 途中、Yで先に進む。出力は省略
$ diskutil repairdisk /dev/disk1

# 出力は省略
$ diskutil apfs resizeContainer disk1s2 0

これが終わり、ストレージから容量を見るとEBSに設定した容量になっている。

ちなみにこれをやらないとXCodeとAndroidStudioのインストール後に容量がなくなって死ぬ。

cordovaのビルド環境の用意

AndroidStudioのインストール

公式サイトからインストールするだけ。

ただし、インストール中に途中で HAXMというライブラリ?のインストールに許可を求められるので、システム環境設定 > セキュリティとプライバシー の画面の下部に許可するボタンか何かが出てくるので許可する

https://qiita.com/simapow/items/a822db6652b7babdd9ef

インストール後、NDKの設定が必要になるので、 config>SDK Manager>SDK Toolsから、NDKをインストールする。もしかするとすでにNDKが入っているかもしれないが、 NDKのバージョンは21.0.6113669.でなければならないため、他のバージョンの場合はこのバージョンに変更する必要がある

XCodeのインストール

もし選択したMacOSのバージョンがBig SurだったらストアからXCodeをインストールすればよかったのだが、Macインスタンスの構築のゴタゴタ時にBig Surにsshできない原因があると考えて Catalinaを選択してしまっていたため、ストアからインストールできず、まずバージョンを上げてBig Surにしろと言われる。

今からまたインスタンス立ち上げるのは時間がかかるしまたsshがつながらなくってしまうのでBig Surにするのは諦めて、以下のサイトから古いバージョンのXCodeのパッケージをダウンロードし、展開するだけで古いXCodeがインストールできる

https://developer.apple.com/download/more/

npm周りのインストール

npmなどをインストールするためにNode.jsをbrewインストールする。

$ brew install node

で node.jsとnpmをインストールすると、Nodeのバージョンが16になり、それに伴ってcordovaコマンドを打つたびに何らかの依存ライブラリによるwarningが出てしまいとても出力が読みづらくなってしまった。

(node:5225) [DEP0128] DeprecationWarning: Invalid 'main' field in '/Users/ec2-user/.config/yarn/global/node_modules/objectorarray/package.json' of 'dist/index.js'. Please either fix that or report it to the module author
(Use `node --trace-deprecation ...` to show where the warning was created)

しかもNode.jsのバージョンがすぐ上がるので毎回バージョンを上げるときに苦労するのが嫌だったので、nvmを利用してバージョン14をインストールすることにした。Macでは以下のコマンドでインストールできる。

# nvmインストール
$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash
# 合わせて.zshrcに記述しておくとよい
$ export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm

# 14を指定
$ nvm install 14
$ nvm use 14
# cordovaをグローバルインストール
$ yarn global install  cordova@10

Androidのデバッグビルド環境準備

androidでは、 JDKとGradleとAndroidSDKが必要になる。

AndroidSDKはAndroidStudioインストール時に合わせてインストールされているのでJDKとGradleをインストールする。

この2つはSDKMAN!を使ってインストールする

$ curl -s "https://get.sdkman.io" | bash
$ source "$HOME/.sdkman/bin/sdkman-init.sh"

上記の途中でcomplete:13: command not found: compdefというエラーが出るので、 .zshrcに以下を追記。なぜこれが起きるかという話はこの記事が分かりやすかった。これを行った後もう一度source ~ を試すと正常に終了する

autoload -Uz compinit
compinit
# JDKのインストール
# cordovaでは 8 である必要があるので必然的にOpenJDKしか選択肢がなかった
sdk install java 8.0.292.j9-adpt

# Gradleのインストール
sdk install gradle

sdkman経由でインストールしたパッケージは $HOME/.sdkman/candidates/に保存されているのでこの2つを環境変数に設定

$ export JAVA_HOME=$HOME/.sdkman/candidates/java/current
$ export PATH=$PATH:$HOME/.sdkman/candidates/gradle/current/bin

また、環境変数にANDROID_SDK_ROOTも未設定だった場合は設定する

$ export ANDROID_SDK_ROOT=$HOME/Library/Android/sdk

これでAndroidのデバッグビルドができるようになる

$ cordova build android

Androidの本番ビルド

ここでいう本番ビルドは、GoolgePlayに提出するために必要な.aabを生成するためのビルドをさす。

まずは(もしなければ)秘密鍵を作る。この時のaliasやパスフレーズは後々使うのでメモ

https://developer.android.com/studio/build/building-cmdline?hl=ja

$ keytool -genkey -v -keystore my-release-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias {任意のalias}

cordova buildでビルド。 --packageType=bundleを忘れずに付与

$ cordova build android --release -- --keystore={鍵の保存先}  --storePassword={鍵のパスワード} --alias={} --password={鍵のパスワード} --packageType=bundle

これで所定の場所に .aabファイルが吐き出される

iOSのビルド環境準備

まずはcocoapodをインストール。gemでインストールしている例が多いが、エラーが出たのでbrewで行う

$ brew install cocoapods

次に、 xcode-selectが設定されていないので設定する。以下の通りでOK。

https://qiita.com/eytyet/items/59c5bad1c167d5addc68#%E7%9B%B4%E3%81%97%E6%96%B9

iOSのビルド時には、デバッグビルドでもAppStore配布用の本番ビルド(以降、面倒なので本番ビルドと呼ぶ)でもprovisioningprofileがないとipaファイルが出力されない。以下の手順でprovisioningprofileを生成・設定してビルドし、.ipaファイルが出力されるようにする

以下のサイトの手順でこのインスタンス固有のCertificate Signing Request (CSR)を作成する

https://www.ssl.com/how-to/csr-generation-in-macos-keychain-access/

AppleDeveloperのサイトから、certificateとprovisioningprofileを生成する。

まずcertificateを作成する。デバッグビルドを行うのであれば iOS Development、本番ビルドを行うのであれば iOS Distribution、両方ならそれぞれ生成。

certificateは生成後にダウンロードして開く(プロンプトが出てきた場合はSystemを選択)。そうするとキーチェーンに iPhone Distribution : xxxx.yyy.zzzという感じの名前の証明書が追加される。この名前をメモしておく(※1)

その後、そのcertificateに紐づくprovisioningprofileを生成。それをダウンロードして開く。すると~/Library/MobileDevice/Provisioning\ Profiles/にファイルが出てくるはず。このファイルの拡張子を除いたファイル名をメモしておく(※2)

cordovaディレクトリのbuild.jsonを以下の様に設定。細かい設定項目はこちらを参照。

{
  "ios": {
      "debug": { // デバッグビルドをする場合に必要
          "codeSignIdentity":"{※1}",
          "provisioningProfile":"{※2}"
      },
      "release": { // 本番ビルドをする場合に必要
          "codeSignIdentity":"{※1}",
          "provisioningProfile":"{※2}",
          "packageType": "app-store" // これを忘れると profleに関して謎のエラーが出る
      }
  }
}

これで設定は完了したのでビルド

# デバッグビルド
$ cordova build ios --device
# 本番ビルド
$ cordova build ios --device --release

これで所定の場所に.ipaファイルが吐き出される

まとめ

  • さくっと終わるイメージだったが、リージョンのゴタゴタにそこそこ時間がかかってしまった
  • AWSの新機能って毎回こんなに不安定なものなのか?🤔
    • それとも今回だけ?
  • ビルド環境に差異・属人性がなくなって気分が良い
  • これからEBSのスナップショットを取って横展開したい
tech  cordova  AWS 

See also