🐸

Expo + EASで実現する週次リリースフローの効率化

に公開

はじめに

株式会社Another worksで「複業クラウド」の開発をしている野々山と申します。

モバイルアプリの継続的なリリースは、Web開発と比較してハードルが高いと感じる方も多いのではないでしょうか。ビルド、コード署名、ストア審査...などやることがたくさんあります。

本記事では、Expo + EAS(Expo Application Services)+ GitHub Actions を活用して、週次リリースフローを効率化した事例を紹介します。

対象読者

  • React Native / Expo でアプリ開発をしている、またはこれから始めたい
  • CI/CD を整備してリリースを自動化したい

EAS / EAS Build とは

知っている方も多いかと思いますが、EAS(Expo Application Services) は、Expoが提供するクラウドサービス群です。

その中核となる EAS Build は、クラウド上でiOS/Androidのネイティブビルドを実行するサービスです。EASのクラウド環境にはXcodeやAndroid SDKがインストールされているため、ローカルに開発環境がなくても eas build コマンド一発でアプリをビルドできます。

主なメリット:

  • 環境構築不要: MacがなくてもiOSビルドが可能
  • コード署名の自動管理: 証明書やProvisioning Profileを自動で管理
  • CI/CDとの連携: GitHub Actionsから簡単に呼び出し可能

GitHub Actions ワークフローの実装

ワークフローは以下の4つのJobで構成しています:

on:
  schedule:
    - cron: "0 5 * * FRI" # 日本時間で金曜14:00
  workflow_dispatch: # 手動実行も可能

jobs:
  check-types:    # 型チェック
  create-tag:     # タグ作成 & リリースノート生成
  trigger-build:  # EAS Build のトリガー
  notify-slack:   # 失敗時の通知

workflow_dispatch を設定しておくことで、緊急リリースが必要な場合にも手動でビルドを実行できます。

毎週金曜日15:00のQA会に合わせて直前でビルドとリリースノートが作成されます。

ポイント1: リリースノートの自動生成

ビルドのたびにバージョンタグ(v1.2.3 → v1.2.4 → ...)を自動で作成し、GitHub Releaseも同時に生成しています。

gh pr listjq を組み合わせて、前回タグ以降にマージされたPRからリリースノートを自動生成しています。

# 1. 前回のタグを取得
last_tag=$(git tag -l 'v*' --sort=-v:refname | head -n1)

# 2. 前回タグの日時を取得
since_date=$(git log -1 --format=%aI "$last_tag")

# 3. それ以降にマージされたPRを取得(モノレポの場合はラベルでフィルタ)
pr_json=$(gh pr list \
  --state merged \
  --base master \
  --label my-app \
  --json number,title,author,mergedAt)

# 4. 前回タグ以降のPRのみ抽出
release_prs=$(echo "$pr_json" | \
  jq --arg d "$since_date" '[.[] | select(.mergedAt > $d)]')

# 5. リリースノート形式に整形
echo "$release_prs" | \
  jq -r '.[] | "* \(.title) by @\(.author.login) in #\(.number)"'

生成されるリリースノートの例:

* ユーザープロフィール画面の改善 by @developer1 in #1234
* プッシュ通知のバグ修正 by @developer2 in #1235
* パフォーマンス改善 by @developer3 in #1236

これにより、「このバージョンには何が含まれているか」が自動で可視化され、QAやリリース判断がスムーズになります。

ポイント2: EAS Build のトリガー

expo/expo-github-action を使用してEAS CLIをセットアップし、staging と release の両プロファイルでビルドを実行します。

検証用(staging)と本番用(release)のビルドを同時に生成することで、QAで確認したビルドとストアに提出するビルドが同一のコードベースから生成されることを保証できます。「QAは通ったのに本番ビルドで問題が発生」というリスクを防げます。

EAS の設定

eas.jsondevelopment / staging / release の3つのビルドプロファイルを定義しています。

プロファイル 用途 distribution
development 開発用 internal
staging QA用 internal
release ストア提出用 store

distribution はビルドの配布方法を指定するオプションです:

  • internal: 社内配布用。Expo Dashboardからダウンロードリンクを取得して直接インストールできます。TestFlightや内部テストトラックを経由しないため、すぐにQAを開始できます。
  • store: ストア提出用。App Store / Google Play にアップロード可能な形式(ipaやaab)でビルドされます。

app.config.jsAPP_ENV 環境変数に応じて設定ファイルを切り替えることで、同じコードベースから staging と production のビルドを生成できます。

ビルドコマンドは以下のオプションを指定して実行しています:

eas build --platform all --profile release --clear-cache --non-interactive --no-wait
  • --platform all: iOS と Android を同時にビルド
  • --clear-cache: 毎回クリーンビルド
  • --non-interactive: CI環境での実行に必須
  • --no-wait: ビルド完了を待たずに次のステップへ(ビルドは時間がかかるのでCIの時間を削減してコストを下げる)

QAフロー

EAS Buildで distribution: "internal" を指定すると、TestFlight(iOS)や内部テストトラック(Android)を経由せずに直接インストール可能なビルドが生成されます。

QAチームにはExpo Dashboardから対象のビルドを選択し、ダウンロードリンクを取得して共有するだけでOKです。

リリースOKだった場合、審査に提出します。

まとめ

Expo + EAS + GitHub Actions を組み合わせることで、毎週金曜日にビルドからQA、審査提出までを一気に行う週次リリースフローを構築できました。

ビルドの自動化により手作業が減り、リリースノートの自動生成で「何が変わったか」が明確になるため、チーム全体のリリース作業がスムーズになりました。

今後の展望

  • EAS Submit: ストア審査提出の自動化
  • EAS Update(OTA): JavaScriptのみの変更は審査なしで即時反映

Expoアプリのリリースフローを整備したい方の参考になれば幸いです。

参考リンク

Discussion