Flutter アプリを GitHub Actions & Xcode Cloud で社内配布する

沖縄モバイルアプリ開発勉強会 #2 で登壇しました。 okimobdev.connpass.com

当日の資料はこちら。

この記事では、資料に書ききれなかった補足と、当日いただいた質問について書いていきます。

公式ドキュメントに記載の方法から外れている点について

Flutter のドキュメントには Xcode Cloud を用いた CI/CD についても記載があります。 Post-clone で pod install だけ行えばよい、というような内容です。 docs.flutter.dev

今回扱っているプロジェクトは build flavor で開発環境・本番環境を分けているため pod install だけでは不十分で、 Post-clone で flutter build まで行う必要がありました。

実際の ci_post_clone.sh を一部抜粋するとこんな感じです。

flutter precache --ios
flutter pub get
flutter pub run build_runner build --delete-conflicting-outputs
flutter gen-l10n

case "$CI_XCODE_SCHEME" in
  "Develop" ) flutter build ios --flavor production --config-only --no-codesign ;;
  "Production" ) flutter build ios --flavor production --config-only --no-codesign ;;
  * ) echo "Unknown scheme: $CI_XCODE_SCHEME"; exit 1 ;;
esac

テストはどこでやる?

flutter test は GitHub Actions のワークフロー内でやるのがおすすめです。 Xcode Cloud は Xcode Cloud でしかできないことに専念させて、それ以外は GitHub Actions に寄せるほうがよいと思います。

各 OS ネイティブのコードで書いている処理をテストするとかでない限り、 GitHub Actions と Xcode Cloud の両方でテストをやる必要はないです。

xcodebuild が無駄に走っちゃうのどうにかならない?

発表後、「flutter build で iOS のプロジェクトファイルだけ生成して、 xcodebuild する手前で止めることもできそうなものだけどね」とコメントをもらいました。 ドキュメントを読んでもそれらしいものを見つけられなかったので「一旦仕方がない」としていましたが、その後改めて調べてみると、 flutter build ios に --config-only オプションを指定すると実現できることがわかりました。

※ flutter build や build ios, build ipa の --help を読んでいて見つけました

Android のバージョンコードに総コミット数を採用した理由は?

これも発表後に「GitHub Actions の GITHUB_RUN_NUMBER を使ってもいいのでは」というコメントをもらったんですが、これはうまくいかなくて見送っていました。ワークフローごとに独立した通し番号なので、ワークフロー自体を別のものに作り直そうとしたときに番号がリセットされてしまうことが理由です。実際に、ワークフローを作っているときは actions_test.yaml みたいな名前で内部テストへのリリースまで試してしまっていたので、実運用むけにワークフローの名前を整えるとバージョンコードが若返ってしまいリリースに失敗していました。 $(( $GITHUB_RUN_NUMBER + n )) みたいに下駄を履かせればいいんですが、マジックナンバーを新しく作るのもなぁ… と思ってやめました。

総コミット数を取得するのは、ワークフローとは分けて専用の composite action を作っています。 fetch-depth: 0 で checkout するのは時間がかかりそうかなと思ったんですが、今のところは 1 秒程度で実行できていてボトルネックにはなっていないので、しばらくはこの運用でいくつもりです。

name: "Get build number"
description: Get commit count from git and set it to BUILD_NUMBER.

runs:
  using: composite
  steps:
    - uses: actions/checkout@v4
      with:
        fetch-depth: 0

    - name: Get commit count from git
      run: |
        echo "BUILD_NUMBER=$(git rev-list --count HEAD)" >> $GITHUB_ENV
      shell: bash

Codemagic と比較してどう?

参加者の方で Flutter エンジニアでは Codemagic が多数派だったのでこの質問があったんですが、 iOS の証明書めんどくさい → Xcode Cloud を使うと楽になるらしい、が動機で始めたので Codemagic は検討していませんでした。 使い勝手どうなんだろう…?機会があったら試してみようと思います。


勉強会に参加するのは久しぶりだったんですが、話しながらツッコミもらってそこから話が膨らんだり、発表後にも質問や感想をもらったり、参加者の皆さんといろいろお話しできて楽しかったです。ありがとうございました!