Logo

    ©ゆとりちゃれんじ

    GitHubXInstagram
    GitHub Actions を使って環境毎に eas build する

    GitHub Actions を使って環境毎に eas build する

    はじめに

    ゆとり世代の中野です。

    今回チャレンジした内容は【GitHub Actions を使って環境毎に eas build する】です。

    さっそくチャレンジについて書いていきます。

    チャレンジする背景

    • 手動でビルドするなんて面倒くさいことはできない
    • ブランチごとに環境変数を使い分けたい

    チャレンジ内容

    • pushしたブランチごとに定義してある環境変数が読み込まれビルドされる

    前提知識

    • CI側で使いたい環境変数はEASに登録せずにCI側で登録する
    • ビルド時に読み込ませたいsecretは事前にEASのProjectに登録しておく必要がある
    • EASは1つのProjectで複数環境のsecretを登録できない
      • 環境毎にProjectを作成しsecretを登録しておく必要がある

    やり方

    前提

    • ExpoのProfileにdevelopment(任意の名前)を作成する
      • ここのProfileで定義した名前をEASとActionsで利用します

    EASの設定について

    • こちらからEXPO_TOKEN を発行します
    ‣
    環境毎にProjectを作成する
    • EAS上でprojects→All projects→Createで作成できます
    ‣
    作成したProjectにsecretを登録する
    • projects→Configure→Secrets→Createで作成できます

    GitHubの設定について

    ‣
    EAS側で発行したEXPO_TOKEN をsecretとして登録します
    • Settings→Secrets→Actions→New Repository Secret
    ‣
    Github Actions の設定
    • .github/workflows/development(任意の名前).yml

    Expoの設定について

    ‣
    app.json
    ‣
    Projectを作成した直後のapp.json
    • app.jsonでは可変的な対応ができないためoverrideさせる必要がある
    ‣
    app.config.js
    ‣
    最小の構成でapp.config.jsを作成したのが下記
    • envsはci側で設定された環境変数を読み込んでいます
      • ビルドするタイミングでどのProjectにビルドするのかを決めるのに利用しています
    • extra ではEASに設定したsecretを読み込んでいます
      • 利用する時は下記のようにします
      • ...
        import Constants from 'expo-constants';
        ...
        <>{Constants.manifest?.extra?.appEnv}</>
        ...

    まとめ

    • EASのProjectは環境毎に作成する
    • EAS上でEXPO_TOKEN をsecretを発行する
    • GithubにEXPO_TOKEN をsecretとして登録する
    • Github Actionsを作成する
    • Expoにapp.config.jsを作成する

    さいごに

    CI/CDが絡んだ情報がほとんどなかったので実際にどういう風に実現したのかについて書いてみました

    関連記事

    EASの導入について

    ゆとり世代の中野です。

    yutanakano.com

    EASの導入について

    yutanakano

    WEBエンジニア

    大阪生まれのゆとり世代です

    趣味はバイクでツーリングに行くこと

    愛車は Ninja ZX-25R SE KRT EDITION

    Expoでプロダクトを作っています

    image
    name: development(任意の名前)
    on:
      push:
        branches:
          - feature/*
    env:
      SLUG: development(任意の名前)
    jobs:
      build:
        name: Install and build
        runs-on: ubuntu-latest
        steps:
          - name: Checkout
            uses: actions/checkout@v2
          - name: Setup Node.js
            uses: actions/setup-node@v2
            with:
              node-version: '16.x'
              cache: npm
          - name: Setup Expo
            uses: expo/expo-github-action@v7
            with:
              expo-version: 5.x
              eas-version: latest
              token: ${{ secrets.EXPO_TOKEN }}
          - name: Install dependencies
            run: yarn install --frozen-lockfile
          - name: Build on EAS
            run: npx eas-cli build --platform all --profile development(任意の名前) --non-interactive --no-wait
    {
      "expo": {
        "name": "アプリ名",
        "slug": "アプリ名",
        "version": "1.0.0",
        "orientation": "portrait",
        "icon": "./assets/icon.png",
        "splash": {
          "image": "./assets/splash.png",
          "resizeMode": "contain",
          "backgroundColor": "#ffffff"
        },
        "updates": {
          "fallbackToCacheTimeout": 0
        },
        "assetBundlePatterns": [
          "**/*"
        ],
        "ios": {
          "supportsTablet": true
        },
        "android": {
          "adaptiveIcon": {
            "foregroundImage": "./assets/adaptive-icon.png",
            "backgroundColor": "#FFFFFF"
          }
        },
        "web": {
          "favicon": "./assets/favicon.png"
        }
      }
    }
    import 'dotenv/config';
    
    module.exports = () => {
      const envs = {
        expo: {
          slug: process.env.SLUG,
        },
      };
    
      return {
        expo: {
          owner: 'EASのアカウント名',
          name: 'アプリケーションの名前',
          slug: envs.expo.slug,
          extra: {
            appEnv: process.env.APP_ENV,
          },
          android: {
            package: '逆ドメイン名',
            versionCode: 1,
          },
          ios: {
            bundleIdentifier: '逆ドメイン名',
          },
        },
      };
    };