見出し画像

Expoアプリの運用をいい感じに整える

note株式会社でバックエンドエンジニアをしているkeinumaです。
この記事は note株式会社 Advent Calendar 2022 の4日目の記事です。

はじめに

僕はこれまでの経験もあり、モバイルアプリを開発するときにReact NativeとExpoを使って開発することが多いです。Expoは昨年Expo Application Services(以下 EAS)が正式版になりどんどんサービスが進化してきています。

この記事ではEASを活用していい感じのReact Native,Expoを使った開発からデプロイまでの運用例を紹介したいと思います。

(注意)note社ではアプリをReact NativeではなくiOS, Androidそれぞれネイティブアプリで開発しています。

アプリ開発の課題

アプリ開発ではWebとは相対的に手作業が多くなりがちです。デプロイするためにも審査が必要だったり、検証環境を別途用意する必要があります。

今回は以下の課題にフォーカスして解決案をまとめたいと思います。

  • アプリのバージョン管理

  • ビルド・デプロイの自動化

  • 柔軟な検証環境の構築

それぞれご紹介します。

アプリのバージョン管理

アプリ開発では常に最新のバージョンを採番しないといけないものの、Expoのファイル(Expoの場合はapp.json, app.config.js)の更新を忘れがちです。

そこで自動的にバージョンを更新しつつどのバージョンがどこで動いているか分かりやすくするためにsongmuさんが開発している tagpr を活用しています。

タグを使っているため、mainブランチからfeatureブランチを切って開発したものをどんどんmainに取り込むブランチ戦略を採用しています。

ブランチ戦略

図の中でv1.0.0からv1.1.0にバージョンアップする場合、mainブランチを更新したあとに手作業でタグを作成、アプリのバージョン情報も修正してリリースする必要があります。タグとアプリのバージョンがずれたり、リリースノートを書き忘れる可能性がありました。

これらの作業をtagprを使って自動化していきます。

tagprはmainブランチが更新されたときにリリースPull Request(以下PR)を自動作成し、作成されたPRをマージするときのワークフローを指定できます。

GitHub Actionsに設定するYAMLは以下です。

name: tagpr
on:
  push:
    branches:
      - main
jobs:
  tagpr:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: Songmu/tagpr@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

設定後にmainブランチが更新されると以下のPRが作成されます。

tagprによって作成されたPull Request

tagprがデフォルトでパッチバージョンを1つあげたPRを作成します。マイナーバージョンやメジャーバージョンを上げる場合は直接バージョンファイルを修正するか、PRにラベルを追加することで対応できます。
PRをマージするとリリースバージョンのタグが作成されGitHub Releasesが更新されます。

tagprではバージョンファイルを環境ごとに指定できます(Rubyの場合はgemspec)。バージョンファイルをpackage.jsonに変更することでtagprが発行するバージョンをExpoに反映してみます。

tagprの設定ファイル(.tagpr)のversionFileをpackage.jsonに変更します。

[tagpr]
	vPrefix = true
	releaseBranch = main
	versionFile = package.json

さらにExpoのapp.config.ts上でアプリのバージョンをpackage.jsonから読み込むように修正します。

import { ConfigContext, ExpoConfig } from '@expo/config';

import packageJson from './package.json';

export default ({ config }: ConfigContext): ExpoConfig => {
  return {
    ...config,
    version: packageJson.version
    ...
  };
};

これでtagprが作成したPRをマージするだけでExpoのバージョンも自動的にあがるようになりました。

次にExpoのビルド・デプロイを自動化してみたいと思います。

EASを利用したビルド・デプロイの自動化

iOSアプリの場合、Expoでビルド・デプロイするためには以下のステップが必要です。

  1. ローカル or CI/CD環境でアプリをビルド

  2. ビルドしたアプリをダウンロード

  3. Transporter経由でアプリを提出

  4. 審査提出

  5. リリース

チームで開発していると、アプリの手順が多くビルド時間も長いためリリース担当が特定のメンバーに偏りがちです。多くのメンバーがリリースできるようにするためにも自動化することが大事です。

EASのBuildとSubmitを利用することで1.~3.の手順を自動化することができます。

EAS Build

EASを利用するためにはexpo-cliとは別にeas-cliをインストールします。ログインコマンドはexpoと一緒です。

$ npm install -g eas-cli
$ eas login
ブラウザが立ち上がってログインする

$ eas build:configure
iOS, Androidのアプリ情報を入力するとeas.jsonが作成される

作成されたeas.jsonの中を見てみると以下のようになっています。

{
  "build": {
    "development": {
      "developmentClient": true,
      "distribution": "internal"
    },
    "preview": {
      "distribution": "internal"
    },
    "production": {}
  }
}

デフォルトでは環境がdevelopment, preview, productionの3つ用意されていています。

ビルドコマンドを実行するとApple, Googleの情報を入力してExpo Buildを実行することができます。実行結果はexpo.dev上で確認できます。

Expo Buildでビルドした詳細画面

EASは無料でも1ヶ月に30回、1ビルドあたり45分まで利用できます。ビルドキューの優先度が低いため、深夜に実行すると30分ほど待機することがあります。(日本ではあまり使われてないかもしれないですね)

GitHub Actionsで利用する場合はビルド時間が長いので、 --no-waitオプションをつけてビルドイベントを通知した段階で完了するようにしています。

$ npx eas-cli build --non-interactive --no-wait

EAS Submit

EAS Submitはアプリを自動的にストアに提出できます。ビルド初期化時に作成されたeas.jsonに以下の内容を追加することで提出できます。

{
  "submit": {
    "production": {
      "ios": {
        "appleId": "dummy@keinuma.com",
        "ascAppId": "dummy",
        "appleTeamId": "dummy"
      },
      "android": {
        "track": "production",
        "releaseStatus": "draft"
      },
    }
  }
}

GitHub Actionsでビルド後に自動的にSubmitする場合はオプションに--auto-submitを追加します。

$ npx eas-cli build --non-interactive --no-wait --auto-submit

このCLIをGitHub Actionsにいれると、自動的に作成されたPRをマージするだけでアプリのビルド、提出まで実現できます。

柔軟な検証環境の構築

アプリの検証環境構築はiOSの場合、TestFlightを利用することが多いと思います。TestFlightは審査提出までシームレスにできて便利なのですが、同時に複数環境みれないためチームで開発しているときにバッティングすることがありました。

Expoが提供しているInternal distribution機能をしようすることで複数の検証用アプリをビルドし、URLで共有することができます。

Internal distributionは事前にデバイスをCLI上で登録する必要があります。

$ eas device:create

デバイスをメールアドレスから招待でできないのでエンジニア以外のメンバーに共有しづらいのがネックだなと個人的に感じてます。Slack Botからできるようにしてもいいかもしれないです。

ビルド設定はeas.jsonの初期化時に記載されていたpreview環境のように、distribution=internalを指定してビルドすることで利用できます。

{
  "build": {
    "preview": {
      "distribution": "internal"
    }
  }
}
$ eas build --profile preview

最初にビルドするとAppleの場合、Ad Hocプロビジョニングプロファイルの登録が要求されます。

ビルドが成功するとQRコードとURLが発行されます。登録したデバイスからQRコードを読み込むことでビルドした検証環境アプリをインストールできます。

特定のブランチからInternal distributionするために以下のようなGitHub Actionsのワークフローを設定しておくと便利です。



name: preview
on:
  workflow_dispatch:

jobs:
  build:
    name: Install and build
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: 16.x

      - name: Setup Expo
        uses: expo/expo-github-action@v7
        with:
          expo-version: 4.3
          token: ${{ secrets.EXPO_TOKEN }}

      - name: Install dependencies
        run: yarn install --frozen-lockfile

      - name: Build and submit on EAS for staging
        run: npx eas-cli build --profile staging --platform all --non-interactive --auto-submit --no-wait

これで複数人が同時に検証環境アプリを作成することができます。

まとめ

tagprとEASを使うことで人がやらなくていい部分を自動化しつつ、バージョン管理や検証環境を運用しやすいかたちでフローをつくってみました。

旧expo-cliからeas-cliに移行するのは大変ですが移行ドキュメントも豊富に用意していただいているので気になる人はぜひ検討してみてください。


note社はExpoを利用していないですが、Android,iOSの技術記事がたくさんあります!アドベントカレンダーも続くのでぜひ他の記事もみてみてください。


この記事が気に入ったらサポートをしてみませんか?