MoAR で使用しているモデルデータやテクスチャはコードと一緒に GitHub 上で管理されています。これらのデータは GitHub に push されるとそのタイミングで GitHub Action によって AWS の S3 へ自動的にアップロードされます。MoAR アプリは起動後に S3 からデータをロードしてコンテンツが表示されます。
workflow はこんな感じ(いぶくん (@asus4) 作
name: Deploy to staging
on:
push:
branches:
- main
paths:
- RemoteResources/**
workflow_dispatch:
jobs:
deploy:
name: Upload to Staging AWS S3
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
lfs: true
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_REGION }}
- name: Deploy
run: |
aws s3 sync ./RemoteResources s3://${{secrets.AWS_S3_BUCKET_STG}}
RemoteRecources
ディレクトリ以下にモデル&テクスチャデータが入ってるので actions/checkout
でチェックアウトして aws-actions/configure-aws-credentials
で credential 設定して ubuntu-latest
にはデフォルトでインストールされてる AWS CLI で aws s3 sync
するだけ。簡単。
USDZ を gzip 圧縮する
MoAR のモデルデータは USDZ 形式で保存されています。(このへんのはなしは @kidapu が書いてくれるはず…
USDZ っていうくらいなので ZIP 圧縮されてると思いきや、
A usdz package is a zero compression, unencrypted zip archive.
無圧縮で1アーカイブにまとめられているだけ… なぜ無圧縮なのかってのは↑のドキュメントにも書いてあるんだけど展開時に新たなメモリ消費することなく直接 mmap
でデータ読めるようにということっぽい。(テクスチャはすでに圧縮フォーマットになってるから非圧縮なのはそんなにシリアスな問題じゃないとも…
とはいえ、ランタイムにネットワーク経由でデータを読んでくる MoAR の場合ファイルサイズが小さいにこしたこたーないわけで、実際に MoAR で使ってる一番大きい USDZ ファイルを gzip 圧縮してみると
半分‼️
ということで S3 で gzip 配信することにしました。
name: Deploy to staging
on:
push:
branches:
- main
paths:
- RemoteResources/**
workflow_dispatch:
jobs:
deploy:
name: Upload to Staging AWS S3
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
lfs: true
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_REGION }}
- name: Deploy other than usdz and json
run: |
aws s3 sync --exclude "*.usdz" --exclude "*.json" ./RemoteResources s3://${{secrets.AWS_S3_BUCKET_STG}}
- name: Deploy usdz with gzip
run: |
find RemoteResources -name "*.usdz" -exec sh -c "x={}; gzip --best -c {} | aws s3 cp - s3://${{secrets.AWS_S3_BUCKET_STG}}/\${x#RemoteResources/} --content-encoding \"gzip\" --content-type \"model/vnd.usd+zip\"" \; -print
- name: Deploy json with gzip
run: |
find RemoteResources -name "*.json" -exec sh -c "x={}; gzip --best -c {} | aws s3 cp - s3://${{secrets.AWS_S3_BUCKET_STG}}/\${x#RemoteResources/} --content-encoding \"gzip\" --content-type \"application/json\"" \; -print
-
aws s3 sync --exclude "*.usdz"
で USDZ ファイル以外を sync。 - 次に
find RemoteResources -name "*.usdz"
で USDZ ファイルを1つずつ処理。 -
gzip --best -c {} | aws s3 cp -
でgzip
の結果を標準出力に出してaws
コマンドが標準入力から読んでアップロード。 - と同時に
--content-encoding "gzip"
で Content-encoding 指定して、ついでに Content-type も指定。(なくてもいい?
JSON も gzip 必要?
↑の workflow では USDZ だけじゃなくて JSON ファイルも同様に gzip 圧縮してます。
JSON ってそんな圧縮必要なほどでかくなるんか?と思うかもなのだけど Ghost Building の UI アニメーションに使用している Lottie のアニメーションファイルはビットマップも JSON に Base64 エンコードで含められるので意外と大きくなる。
半分‼️
.Lottie というフォーマットを使うと ZIP ファイルとして必要なアセットをまとめることができるので gzip 圧縮不要かも。(時間切れで実装できなかった
ステージング環境と本番環境
↑にでてきた workflow は開発時用なのでデータが push されたらステージング環境に sync されるようになっている。
アプリリリース時だけ本番環境へアップロードされるように別の workflow を用意する。
name: Deploy to production S3
on:
release:
types: [created]
workflow_dispatch:
トリガーを新しいリリースが作成されたタイミングにしてあとは同じ。(バケットが違うだけ
自動化するとらくちん
GitHub のコードを push すると自動で Xcode Cloud でビルドされて(8日目の記事)、データを push すると自動で S3 にアップロードされるのでめっちゃ楽だしミスも発生しづらいのでおすすめ。